Skip to content
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

feat(workbox): workbox 3 + offlinePage #60

Merged
merged 51 commits into from
Aug 24, 2018

Conversation

manniL
Copy link
Member

@manniL manniL commented Apr 4, 2018

Workbox has released version 3, so we could upgrade to v3 as well. But there are some obstacles.

In version 3, there is no WorkboxSW class anymore. workbox is exposed as a global variable instead (see the Migration Guide). The problem is that workbox is always undefined when compiling the sw.template.js lodash template.

+ Use global variable instead of class instance
+ Update methods
+ Add cleanUrls property
@manniL
Copy link
Member Author

manniL commented Jul 14, 2018

Unfortunately I don't know how to proceed further :( Hope if someone could give it a go and take over from here.

@XanderLuciano
Copy link

Just doing some preliminary research currently, but looks like vue-cli has a work in progress PWA with workbox 3. May be worth looking at the implementation there: https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa


<% options.runtimeCaching.forEach(r => {
const strategy = JSON.stringify(r.strategyOptions || {})
%>
workboxSW.router.registerRoute(new RegExp('<%= r.urlPattern %>'), workboxSW.strategies.<%= r.handler %>(<%= strategy %>), '<%= r.method %>')
workbox.routing.registerRoute(new RegExp('<%= r.urlPattern %>'), workboxSW.strategies.<%= r.handler %>(<%= strategy %>), '<%= r.method %>')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should workboxSW.strategies be workbox.strategies?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will fix!

@monotykamary
Copy link

I think it might be related to the path of the workbox-sw asset.

jsdelivr reflects the path for v2:

/build/importScripts/workbox-sw.prod.v2.1.3.min.js

and for v3:

/build/workbox-sw.min.js

@manniL
Copy link
Member Author

manniL commented Jul 22, 2018

Thanks to @XanderLuciano and @monotykamary for helping out ☺️

Looks like the ball is rolling again 🙊

image

@manniL
Copy link
Member Author

manniL commented Jul 22, 2018

This looks somewhat ready. Will do some tests with a real-world project of mine and report back and soon as I have the results ☺️

@manniL
Copy link
Member Author

manniL commented Jul 22, 2018

LGTM so far.

cc @pi0 for cross-validation and review :)

@manniL manniL changed the title [WIP] Update workbox to version 3 Update workbox to version 3 Jul 22, 2018
@XanderLuciano
Copy link

Took me a bit to figure out how to install your changes locally but eventually figured it out and it seems to be working just fine on my project also!

image
image

@manniL
Copy link
Member Author

manniL commented Jul 23, 2018

@XanderLuciano Happy to hear that!

The only thing I'm experiencing is that workbox is still used in dev mode/ on localhost, which results in an endless loop where workbox and the webpack HMR are fighting and reloading the page every few seconds. A hard refresh (CTRL + F5) does stop it though.

It only happens when using Firefox. 🦊 Happens on FF and Chrome, as the sw.js is cached

Possibly related: #75 #63

@XanderLuciano
Copy link

@manniL I swear I had not run into this issue all night, but as soon as I saw your comment it happened.

It seems a bit like an edge case for me though because in dev mode if I remove the service worker a new one isn't registered. So I was only able to reproduce by building and starting the app, then stopping the server and starting a dev instance, and then updating some code that triggers the HMR.

Like you said though, a quick ctrl+shift+r / ctrl + F5 fixed it.

I'm gunna continue development using this version so if I run into additional issues (or a solution to the HMR reloading) I'll let you know.

@XanderLuciano
Copy link

XanderLuciano commented Jul 23, 2018

Struggled to get offline support functional, but eventually figured it out.

workbox: {
    runtimeCaching: [
        // Needed to cache the homepage and manifest file (not 100% sure on that though)
        {
            urlPattern: '/.*',
            handler: 'networkFirst',
            method: 'GET',
        },
        // Cache our CDN libraries
        {
            urlPattern: 'https://cdnjs.cloudflare.com/ajax/libs/.*',
            handler: 'cacheFirst',
            method: 'GET',
        },
        // Cache our fonts
        {
            urlPattern: 'https://fonts.(?:googleapis|gstatic).com/(.*)',
            strategyOptions: {
                cacheName: 'google-fonts',
            },
        },
    ],
},

Would it make sense to add that pattern to the template also? We already cache everything in /_nuxt/, but /.* would try to cache quite a bit more.

Update: Looking good ✨

image

@manniL
Copy link
Member Author

manniL commented Jul 25, 2018

I've investigated the "update issue" and I've likely tracked it down. It is, as I assumed, a caching issue, so #75 should definitely be merged in before updating. After clearing my cache for localhost, everything worked well :)

@XanderLuciano
Copy link

@manniL Oh awesome! So merging #75 into my custom build of this PR should fix the issues with HMR? Have you tested offline usage with the server worker's cache disabled?

@manniL
Copy link
Member Author

manniL commented Aug 4, 2018

There are some caveats left when specifying own precaching but it shouldn't be hard to fix ☺️ (workbox now calls 'plugins', but this is a thing we can setup dynamically quite good)

Really want to add some tests to it too later.

@XanderLuciano
Copy link

XanderLuciano commented Aug 7, 2018

Well it took me 2 weeks to figure out how to create my own personal build of this package with all the PR's I wanted, but now I've got that all setup under my own personal scope (since it's taking so long to get any PR's to this repo).

That said, I included #75 in that build and still get stuck in a reload loop when going from a built instance to a dev instance with hot reloading. So as you said, there are still some caveats to work out.

For example, going from built version to dev, upon triggering an HMR the server console will output a loop of errors such as:

{
  statusCode: 404,
  path: '/_nuxt/55d3a1e8f0e84963b002.hot-update.json',
  message: 'This page could not be found'
}

And upon going from a dev instance to a built server instance, there appears to be an HMR request that continues to try and update, even though it's a production build:

image

So it seems to me that the overly broad URL pattern of /.* may be a little too broad and causing the service worker to cache these files. Potentially might be worth excluding files with hot-update in their name?

Maybe another solution to this would be to disable (or change) precaching on development builds. That way when you you run npm run dev HMR works as expected and workbox doesn't interfere, but running npm run build && npm run start allows you test offline mode and your service worker properly.

I'm still learning a lot about workbox, but so far I've had no issues running this in a production environment. Add to homescreen banners appearing properly too.

Edit: Now workbox isn't loading at all under dev, which is great because now I don't have the HMR issue, but not sure what triggered the change.

@XanderLuciano
Copy link

Alternatively, this button is super handy. It disables the service worker's cache and seems to fix all the reload looping.

image

@galvez
Copy link
Contributor

galvez commented Aug 17, 2018

@manniL @XanderLuciano anything else you'd like to get in before I merge this? I'll give it a round of testing tonight.

@manniL
Copy link
Member Author

manniL commented Aug 17, 2018

@galvez I’d wait until we fixed the plugin thing I mentioned above. Otherwise custom strategies are hard to accomplish. Testing is happily seen! 😋

@galvez
Copy link
Contributor

galvez commented Aug 17, 2018

@manniL I'm gonna dabble at fixing that problem, do you have any WIP updates to this branch?

@manniL
Copy link
Member Author

manniL commented Aug 17, 2018

@galvez Nope, have no WIP there yet :/

@galvez
Copy link
Contributor

galvez commented Aug 17, 2018

@manniL no worries -- picking this up on the feature/workbox-v3 branch :)

@pi0 pi0 changed the title [WIP] Update workbox to version 3 [wip] feat(workbox): workbox 3 + offlinePage Aug 24, 2018
@galvez galvez changed the title [wip] feat(workbox): workbox 3 + offlinePage feat(workbox): workbox 3 + offlinePage Aug 24, 2018
@manniL
Copy link
Member Author

manniL commented Aug 24, 2018

We should adopt the changes for workbox-strategies plugins as well. (see here)

@galvez
Copy link
Contributor

galvez commented Aug 24, 2018

We should adopt the changes for workbox-strategies plugins as well. (see here)

As I have pointed out over Discord, we're not using any of the features that require updating.

@galvez galvez merged commit 51e2938 into nuxt-community:master Aug 24, 2018
@manniL manniL deleted the feature-update-workbox branch August 24, 2018 09:55
pi0 pushed a commit that referenced this pull request Aug 24, 2018
Co-authored-by: manniL <hello@lichter.io>
Co-authored-by: galvez <jonasgalvez@gmail.com>"
pi0 pushed a commit that referenced this pull request Aug 24, 2018
Co-authored-by: manniL <hello@lichter.io>
Co-authored-by: galvez <jonasgalvez@gmail.com>"
@manniL
Copy link
Member Author

manniL commented Aug 24, 2018

@galvez Well, we do use the feature as we enable customization of strategies (fka. as runtime-caching) by the user.

options.runtimeCaching.forEach(r => {
const strategy = JSON.stringify(r.strategyOptions || {})
%>
workbox.routing.registerRoute(new RegExp('<%= r.urlPattern %>'), workbox.strategies.<%= r.handler %>(<%= strategy %>), '<%= r.method %>')
<% }) %>

Formerly you could pass the options as a simple object

{
  cacheExpiration: {maxEntries: 50}
}

but now you have to use plugins where the initial workbox object has to be called.

plugins: [
    new workbox.expiration.Plugin({maxEntries: 50})
  ]

(from the example linked above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants