-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Offline and Manifest plugin #687
Conversation
Gatsby core won't have SW precaching built-in in the next release so this is necessary for a fast site. And even if a browser is precaching bundles, pulling bundles from the SW and evaling them still adds latency to page transitions. Doing this work ahead of time in spare moments means that page transitions will be always be fast.
The webpack offline-plugin is great but it doesn't work with content not handled by Webpack as Gatsby is increasingly moving towards. Also by handling this in plugins instead of core, it'll offer users more choices about how to handle "offline" than trying to meet all needs in core.
Overly expensive for pages with lots of links.
This adds a basic setup for handling loading a website with a service worker generated by sw-precache. It uses the AppShell technique to load first a simple HTML shell of the website (which would generally show the header for most sites) which then loads the Javascript for the actual page and renders that.
Deploy preview ready! Built with commit e74abe6 |
Deploy preview ready! Built with commit e74abe6 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm excited for this! I left a few comments—sorry that the way sw-precache
uses RegExps isn't as clear as it could be.
@@ -0,0 +1,26 @@ | |||
{ | |||
"name": "gatsby-plugin-offline", | |||
"description": "Gatsby plugin which sets up a site to be able to run offline\"", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like there's an extra trailing \"
escape sequence.
navigateFallback: `/offline-plugin-app-shell-fallback/index.html`, | ||
cacheId: `gatsby-plugin-offline`, | ||
dontCacheBustUrlsMatching: /(.*.woff2|.*.js)/, | ||
runtimeCaching: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
urlPattern
will trigger on partial URL matches, so there's no need to put in the leading .*
wildcard.
If you wanted to combine all of the RegExps, you could do /\.(?:png|jpg|jpeg)$/
If you want to keep them separate, then I'd just tweak each of them a bit to escape that .
character, and enforce that the match happens at the end of the URL string. So, e.g., /\.png$/
.
skipWaiting: false, | ||
} | ||
|
||
precache.write(`public/sw.js`, options, err => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sw-precache
's write()
method returns a promise, so you should just be able to return it and not mess around with the callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah nice :-)
stripPrefix: rootDir, | ||
navigateFallback: `/offline-plugin-app-shell-fallback/index.html`, | ||
cacheId: `gatsby-plugin-offline`, | ||
dontCacheBustUrlsMatching: /(.*.woff2|.*.js)/, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably safer to include a RegExp here that matches the specific hash format you're using in your versioned filenames. So if you're using an 8 character hash surrounded by .
characters, leading to filenames like 'app.123456ab.js, something like
/.\w{8}./` would make sense.
You don't need to match the entire URL, so there's no need for the leading .*
wildcard.
@jeffposnick thanks for the feedback! And of course doing a lot of heavy-lifting on building/maintaining sw-precache. It's super easy to use and very flexible. |
Notes on implementation and ideas for future.
|
Was the README updated? |
Looking to get the sw.js working in my gatsby build but getting this
|
With these two new plugins, most Gatsby sites can very easily become full-blown Progressive Web Apps! This includes working offline and (on Android) being able to “install” the website to your homescreen. Nifty! Once I got things working on my blog, I was able to quickly "offline-ize" three other websites very quickly.
This is the Lighthouse result I recorded while testing my blog.
These plugins are also a nice illustration of the versatility of Gatsby's plugin system and its ability to extract complex intertwining (complected) behaviors into a modular, reusable plugin. I'll walk through how the offline plugin works to illustrate this.
The offline plugin converts Gatsby to use the AppShell pattern. For SPA apps, in short this pattern works by caching an HTML page which acts as a "shell" for the app. Since it'd be tedious to ask every user of the offline plugin to add a special page, the plugin simply implements the
createPages
API and adds one itself.The plugin also ships with the component seen there.
Next the plugin uses
postBuild
to create the service worker w/ precaching and offline support enabled:And finally, it uses the
modifyPostBodyComponents
API to add the snippet of Javascript to the end of the body necessary to load the service worker.Still need to add READMEs to the plugins before I merge this.