Search code examples
angularprogressive-web-appsangular-universalserver-side-rendering

Is it reasonable to use TransferState with PWA?


When I was creating my app in Angular 5 with Universal to achieve Server Side Rendering I used TransferState to not duplicate my requests to API endpoint.

I have upgraded my application to work as Progressive Web APP, but now browser requests for all resources. As I understand index.html sent by node.js server can't send html with data in state.

So is it reasonable to use TransferState when application works as PWA?


Solution

  • Yes it is reasonable to use Transferstate with PWA in Angular but there's a caveat.

    Transferstate is going to come into effect when you first visit the webapp. Angular universal will fully render the html for the view matching your URL, and send any data retrieved through Transferstate as you'd expect, to prevent the "flash" that happens when the client-side app loads and makes all the same API calls again.

    In the background the serviceworker will either cache or pro-actively download the extra PWA elements of your application such as your index.html file. Afterwards, subsequent visits to the webapp will be handled entirely by the PWA now cached in the browser, initiating any API calls from the browser, completely bypassing server side rendering and the need for transferstate. This happens even if you happen to jump into the webapp on a route you haven't visited before.

    In this scenario transferstate has it's purpose to prevent the "flash" that occurs when first visiting the webapp on browsers that are PWA capable, as well as for subsequent visits to the webapp for browsers that are not PWA capable as those requests will always go to the Angular Universal server.

    The caveat here is that transferstate should not be treated as the only possible source of data. There should always be some API to fallback to if the data you're looking for is not there in the transferstate.

    An example from my personal experience on this: I was using transferstate to send configuration values read from the server's environment variables up to the browser. When the PWA took over the configurations were no where to be found because there was no transferstate in the index.html of the PWA. The solution was to setup an API endpoint to serve the configurations, and not rely on transferstate for this.

    Previous Answer (ignore suggestions here):

    It seems like there is a limitation when using Transferstate with PWA. I've found that the script tag which stores the Transferstate json is not in the DOM at the time the 'DOMContentloaded' trigger fires.

    With Chrome Devtools open to the Application tab, under 'Service Workers' uncheck the 'Update on reload' and 'Bypass for network' boxes. Then reload your app and observe that any XHR requests that you may have cached in your Transferstate are actually being made in the browser, though they should have already been made during Server Side Rendering.

    It's not perfect but one option is to remove the /index.html entry from any assetGroups.resources.files array in your ngsw-config.json file. This prevents your app from being a full PWA with offline capabilities, but it does still have the benefit of loading other resources from the service worker.