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

How to use Workbox with a Bundler (Webpack etc.) #2207

Closed
sinemacula opened this issue Aug 30, 2019 · 6 comments
Closed

How to use Workbox with a Bundler (Webpack etc.) #2207

sinemacula opened this issue Aug 30, 2019 · 6 comments

Comments

@sinemacula
Copy link

sinemacula commented Aug 30, 2019

I have also posted this question on Stackoverflow but wanted to post it here to ensure others can find the answer easily in the future. Please see my SO question here: https://stackoverflow.com/questions/57726659/how-to-use-workbox-with-a-bundler-webpack-etc

I have read every line of the extensive, and brilliant, documentation that accompanies Workbox. However, I have been unable to find sufficient guidance on the best practices when building a project using a bundler such as Webpack.

The documentation on Google states:

When using a JavaScript bundler, you don't need (and actually shouldn't use) the workbox global or the workbox-sw module, as you can import the individual package files directly.

However, there are various problems that occur when using a bundler on the service worker file:

  • If you are using one configuration file, then the service worker itself will be included in the bundled manifest, thus will also be included in the precache manifest
  • If you are using versioning in production, then your service worker file will end up being hashed like so service-worker.123abc.js

In the documentation for the workbox-webpack-plugin, it does, kind of, hint that multiple configuration files may be required in the following statement:

This can be problematic if you're using the same webpack configuration to generate your service worker file, since it may not exist by the time the workbox-webpack-plugin code runs.

Therefore, I have the following questions:

  1. Is it, in fact, a requirement that you have two seperate bundler configurations set up? One to bundle the service worker (first one to run), and then one to bundle the application (second to run)?
  2. Secondly, if the answer to the above question is yes, then surely the swSrc option for InjectManifest is going to be in the public directory? e.g. dist/service-worker.js. Will InjectManifest cope with source file being the same as the destination file?
  3. And finally, assuming the assumptions on both 1. and 2. are correct, will InjectManifest succeed at injecting the manifest into a 'built' service worker file? What I mean is that will it be able to navigate the webpack modules, and insert the manifest in the correct place?

I actually use the Laravel Mix wrapper for webpack which makes multiple configuration files slightly more difficult than just pure webpack, thus I want to ensure I am doing this correctly, before I go ahead and actually do it...

@philipwalton
Copy link
Member

@sinemacula Are you using the v5 beta version of workbox-webpack-plugin? You should be able to bundle your service worker and your application with a single webpack config in v5, so please give that a try and let us know if it solves your issue.

@sinemacula
Copy link
Author

Hi @philipwalton , thank you very much for your prompt response, I really appreciate your time and effort on this!

I am actually using version 4.3.1 at present but I am more than happy to change to a different version if you believe this will solve the problem. However, I fear that I may run into several issues if I do:

  • Due to an acknowledged bug to do with Dynamic Importing, it is essential that I use Laravel Mix 3 (webpack 3) instead of Laravel Mix 4 (webpack 4). I noticed that this version of workbox requires Webpack 4.19.1. That said, so does Workbox 4.3.1 but it seems to work fine with webpack 3 so far.
  • Using Laravel Mix, as far as I am aware, there is no way for me to split the chunks and prevent service-worker.js from being hashed in my production environment. The only solution is to manually rename the file after the build completion (ewwww), thus it is almost certain that I will have to use multiple webpack configurations.

I absolutely appreciate that Laravel Mix is a third-party library so obviously I am not expecting you to be able to support that. However, what I would really appreciate more than anything, is if you could take a moment to just answer the following questions for me as this will allow me to then proceed in the correct way with Laravel Mix:

  • Would you consider it 'bad practice' to use the build process I outlined in my original post? i.e. two configurations, one to build the service worker, and then one to build the app, and inject the precache manifest into the built service worker in my dist directory? Specifically, do you foresee any issues with injecting the precache manifest into an already bundled file? I have actually tested this and it does work...
  • In the link you posted, I noticed that one of the fixes that the beta version provides is to remove any non-js files from the precache manifest. Does this mean it is bad practice to precache css files and image files? If not, why are they removed?
  • As advised in the documentation when utilising a bundler, I am importing the specific workbox modules as opposed to injecting the whole workbox-sw import provided by InjectManifest. I have it working perfectly but I just want to ensure that I am doing it correctly by setting importWorkboxFrom: 'disabled'?

I apologise if this is not the right place to ask these questions but I am trying to get as much information as possible, so I can share with others how best to work with Workbox when using Laravel Mix.

@philipwalton
Copy link
Member

@jeffposnick maintains the webpack plugins, so I'll defer to him for the definitive answers (he's on vacation until mid next week), but here are my thoughts on your questions:

Would you consider it 'bad practice' to use the build process I outlined in my original post? i.e. two configurations, one to build the service worker, and then one to build the app, and inject the precache manifest into the built service worker in my dist directory? Specifically, do you foresee any issues with injecting the precache manifest into an already bundled file? I have actually tested this and it does work...

I don't use webpack, but this is exactly why I do on my site to build my service worker. I use Rollup and run to builds: (1) to build my window bundles and generate a manifest of all JS files created, and then (2) to build the service worker file, which I do based on the manifest generated in 1. I also put that manifest in my build folder, and doing so has given me no issues.

In the link you posted, I noticed that one of the fixes that the beta version provides is to remove any non-js files from the precache manifest. Does this mean it is bad practice to precache css files and image files? If not, why are they removed?

Can you point me to where you're reading that? I'm not sure where that's stated. In general it's not a bad practice to precache non-JS assets, but if you have a lot of large assets, doing so can increases the likelihood of the SW installation failing, so it's best to only precache what is absolutely critical and then use runtime caching for everything else.

As advised in the documentation when utilising a bundler, I am importing the specific workbox modules as opposed to injecting the whole workbox-sw import provided by InjectManifest. I have it working perfectly but I just want to ensure that I am doing it correctly by setting importWorkboxFrom: 'disabled'?

The importWorkboxFrom option has been removed in v5 as the new build step bundles the Workbox source code into your final service worker output file.

@sinemacula
Copy link
Author

This is brilliant, thank you very much @philipwalton - I am new to the PWA World so am trying to read up on, and absorb, as much information as possible so this is a real help to me!

I think I have probably misunderstood the link I read; upon re-reading it I noticed it is only referring to 'chunks' i.e. JS, so it is nothing to do with the CSS and image assets I think. See the link here: #2164

I have been working more on this today, and as is the norm, have run into a few more questions. Feel free to ignore me as I know this isn't the right place but if you have time, could you answer the following for me:

Unfortunately the v5 release requires webpack v4 or higher which means I need to stick with the version I am currently using (4.3.1).

  1. Do you precache your PWA icons? Or are these better placed in runtime caching?
  2. This may be better suited for @jeffposnick as it is relevant to Webpack, but is there a way to apply transformations to the manifest using version 4.3.1. The manifestTransforms option does not work with assets from the webpack compilation manifest (as referenced here: [workbox-webpack-plugin] Apply manifestTransforms to Webpack assets #1339 (comment)).

I need to make various transformations such as:

  • Removing revisions for files with hashes (dontCacheBustURLsMatching has the same issue i.e. ignoring webpack compilation assets)
  • I am using the copy-webpack-plugin to move all of my static files (images) to my dist directory. The problem with this is that it is adding a whole bunch of images to the precache manifest that I don't want there. I tried to move the InjectManifest call above the CopyWebpackPlugin call and use GlobPatterns but then the files don't exist in the dist directory by the time the manifest is generated.

I believe my only solution is to read the precache manifest after it has been generated, and then just modify the contents but this seems a tad dirty.

@jeffposnick
Copy link
Contributor

I think you're going to be happier once you find a way to use Workbox v5. Things like being able to automatically transform the manifest really only work in the way you describe in v5 (see https://github.com/GoogleChrome/workbox/releases/tag/v5.0.0-alpha.0 for more context).

In the meantime, if you can't use Workbox v5, something you can do is just treat your service worker code like any other entry in your webpack configuration in terms of your main compilation, and make sure that you don't include a hash in its filename. Don't use the actual workbox-webpack-plugin, but instead, call workbox-cli with your desired configuration in injectManifest mode as a second step after your webpack build process has completed. (I.e. if you're using npm scripts, do something like "build": "webpack && workbox injectManifest") As long as all of the assets you want to precache are written to disk as part of your webpack build, workbox-cli should be able to pick up on them for you.

@sinemacula
Copy link
Author

Hi @jeffposnick - thank you so much for your response and your support here! I really appreciate it!

Having read the Workbox v5 changelog and docs thoroughly, I absolutely agree that my life would be substantially easier if I was able to upgrade. Unfortunately, until Laravel Mix fixes it's issue with dynamic importing (not going to happen until webpack 5), there is literally nothing I can do (too late in the project for me to drop Laravel Mix and go pure webpack).

In the meantime, I have actually managed to get Workbox v4 to work in the way that I require. For instance, for the manifest transformations, I simply read the file after the compilation has completed and then apply any necessary transformations before saving the file again. Not the cleanest of solutions but it does what I need it to do whilst I wait for the new version of LM. You can see the way I have done this in the answer posted here (feel free to leave any feedback):

I do have another question that I am hoping you might be able to shed a little light on but as it isn't related to this, I have posted it on SO. Take a look if you have time:

https://stackoverflow.com/questions/57763393/localising-a-pwa-web-manifest

Thank you so much!

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

No branches or pull requests

2 participants