Open AllanChain opened 4 years ago
Thanks @AllanChain It really helped.
But I have few things, gridsome is still loading all chunks on the index page, but vuejs does page-wise.
Any idea how to only load relevant js bundle on the page ?
@milindsingh I am not having this issue 🤷♂️ As reference, you can try gridsome branch of this repo and comment out PWA plugin section in gridsome.config.js
for simplicity. For example axios is loaded when the page needs it.
View Post on Blog
Preface: Why I Need PWA
More than 300 KB of vendor chunks (
vue
,vuex
,vue-router
,vue-meta
,vuetify
, etc.) with a not-that-fast network is very slow to load. I really don't want it to happen again. Also if the page service is down or unreachable (does happen from time to time, at least for my region), I want the site still to work properly.First of All: Optimise Assets
If your sites updates frequently, you need to change the default behavior.
Cache Busting
By default, gridsome write hashes to page html and json file. While it helps controlling versions, the hash itself is unreliable. That's becuase the hash is generated by webpack build, which is somewhat random. I am even getting different hashes when building
gridsome.org
, without changing a single character!Also, if the hashes do work properly, I don't want to invalidate all cached data just because I change one byte of javascript code.
So I jut turned cache busting off:
But I still don't want browser to load old assets for new HTML. So I turns on assets hashing manually:
Splitting Chunks
By default, gridsome packs
main.js
,App.vue
, etc., and used node modules into oneapp.hash.js
, which is more than 300 KB in my case, basically vuetify and gridsome with modules it depends on. Changing one byte ofApp.vue
means downloading all 300 KB again, which is a pretty awful UX.Let's split the chunks:
I can only split out 1 chunk if
maxInitialRequests
is not set.Note: The above code overwrites gridsome's
css: { split: false }
config and always splits CSS. To disable CSS splitting, add these lines:Choosing Cache Strategy
Precache v.s. Runtime Cache
In short, precache caches all files specified in the manifest, which is usually a list of js and css assets, at install time.
Runtime cache is more flexiable and have a lot of strategies to choose.
My Best Practice Now
Precache the assets, use
NetworkFirst
strategy for HTML pages and post data, andCacheFirst
for images. Don't worry if the network is slow and still taking a long time to load, just setnetworkTimeoutSeconds
.Why not...
StaleWhileRevalidate
for JSON Data FilesThe user will not receive changes immediately:
Also, caching JSON data means https://github.com/gridsome/gridsome/issues/1032#issuecomment-632908706
Add Revision to JSON Data Files
Yes, this is posible by using
injectManifest
and precache some of them, while runtime caching with a handler to add revision to the url. (Detailed implemantation)However, compiling service worker with webpack is currently limited that I cannot split chunks with it. That means if the post data changed one byte, the user have to redownload the service worker file again, which is about 50 KB. Even if I managed to split the service worker, that's still 13 KB of manifest and will grow overtime. That's quite annoying that the service worker is always updating, slowly.
Of course if you are sure your users' network is fast, you can ignore above drawback.
Just Precache all JSON Data Files
Precaching all data files has the same drawback as above. Plus, precaching all data files means the user is downloading the whole site on first visit, which is a horrible UX, as well as large network overhead. And only after precache is done will the service worker complete installing.
For example, first visit to https://v3.vuejs.org/ takes a long time to complete. ~400 files to precache.
Of course if the users should be able to browse the full site while offline, and you do not care first visit loading and service worker installing time, go ahead with precaching.
Still Problem
Though using
NetworkFirst
, sw will still use the cached JSON data version if offline. And the cached file may have different versions. For example:Since the user is offline, it is expected that some pages are not available. Better to show freindly offline message instead of getting a wrong version of data and having the broken page. Maybe using the GraphQL query hash as part of JSON filename?