I have a SSR Angular app which I am trying to transform into a PWA. I want it to be server-side rendered for SEO and for the "fast first rendering" that it provides.
The PWA mode works fine when combined with SSR, but once the app is loaded, when we refresh it, the client index HTML file is loaded instead of the server-side rendered page.
I have dug into the code of ngsw-worker.js
and I saw this:
// Next, check if this is a navigation request for a route. Detect circular
// navigations by checking if the request URL is the same as the index URL.
if (req.url !== this.manifest.index && this.isNavigationRequest(req)) {
// This was a navigation request. Re-enter `handleFetch` with a request for
// the URL.
return this.handleFetch(this.adapter.newRequest(this.manifest.index), context);
}
I have no control over this file since it's from the framework and not exposed to developers. Did anybody find a solution or workaround for this?
Adding a service worker to an Angular application is one of the steps for turning an application into a Progressive Web App (also known as a PWA). At its simplest, a service worker is a script that runs in the web browser and manages caching for an application. Service workers function as a network proxy.
Angular Universal executes on the server, generating static application pages that later get bootstrapped on the client. This means that the application generally renders more quickly, giving users a chance to view the application layout before it becomes fully interactive.
I have found a working solution, the navigationUrls
property of ngsw-config.json
contains a list of navigation URLs included or excluded (with an exclamation mark) like explained in the documentation.
Then I configured it like this:
"navigationUrls": [
"!/**"
]
This way, none of the URLs redirect to index.html
and the server-side rendered app comes into play when the app is first requested (or refreshed), whatever the URL is.
To go further, the three kinds of URLs managed by the service worker are:
ngsw.json
file with their corresponding hashesindex.html
by default, forwarded to the server if the "!/**"
configuration is usedGET
requests to the backend: forwarded to the backendIn order to distinguish a GET
XMLHttpRequest
from a navigation request, the service worker uses the Request.mode property and the Accept
header that contains text/html
when navigating and application/json, text/plain, */*
when requesting the backend.
For more details on this, please take a look at the Angular's team member answer to my feature request: https://github.com/angular/angular/issues/30861
Angular now has a navigationRequestStrategy
option which allows to prioritize server requests for navigation. Extract of the changelog:
service-worker: add the option to prefer network for navigation requests (#38565) (a206852), closes #38194
To be used wisely! This warning appears in the documentation:
The
freshness
strategy usually results in more requests sent to the server, which can increase response latency. It is recommended that you use the default performance strategy whenever possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With