Workbox's precache manifest file contains invalid URL strings in Laravel Mix setting
Asked Answered
G

1

5

I'm using Workbox 3.0 (webpack-plugin) and Laravel Mix (5.6) to auto-generate a ServiceWorker file.

When running the webpack compiler, the manifest file generated by Workbox for pre-cached assets looks like this:

self.__precacheManifest = [
  {
    "revision": "89c25ce71806a695a25e",
    "url": "//js/app.js"
  },
  {
    "revision": "89c25ce71806a695a25e",
    "url": "//css/app.css"
  }
];

Obviously, the URL strings are wrong and cause errors on the actual web page.

Here is my webpack.mix.js: (relevant parts)

const {InjectManifest} = require('workbox-webpack-plugin')
mix.webpackConfig({
  plugins: [
    new InjectManifest({
      swSrc: './resources/assets/js/sw.js'
    })
  ]
})

While InjectManifest is used here to have precaching as well as my own dynamic caching, the same happens when using the GenerateSW plugin instead.

and my source sw.js:

workbox.precaching.precacheAndRoute(self.__precacheManifest || [])

Any idea how to solve this? If I manually modify the precacheManifest, it works fine:

self.__precacheManifest = [
  {
    "revision": "89c25ce71806a695a25e",
    "url": "./js/app.js"
  },
  {
    "revision": "89c25ce71806a695a25e",
    "url": "./css/app.css"
  }
];

Steps to reproduce this:

  1. Create a new Laravel Project: Laravel new <proj_name>
  2. cd <proj_name>
  3. npm install
  4. npm install --save-dev workbox-webpack-plugin
  5. Add these lines to webpack.mix.js to configure it for Workbox:

const { GenerateSW } = require('workbox-webpack-plugin');

mix.webpackConfig({ plugins: [new GenerateSW()] });

  1. run php artisan make:auth and php artisan migrate to complete the frontend scaffolding
  2. Edit bootstrap.js in the \resources\assets\js folder to include the usual code to register the new ServiceWorker
  3. run npm run dev

The compiled precache-manifest file looks like this:

self.__precacheManifest = [
  {
    "revision": "b922e094256b9404e705",
    "url": "//js/app.js"
  },
  {
    "revision": "b922e094256b9404e705",
    "url": "//css/app.css"
  }
];
Gao answered 8/6, 2018 at 12:32 Comment(6)
I tried adding e.g. importsDirectory: './public' to the webpackConfig object but to no avail.Gao
What is your output.publicPath value in your webpack config?Miamiami
I'm actually not modifying the webpack.config.js file directly - this is all handled by Laravel Mix. But looking at the webpack.config.js file in the node_modules directory (node_modules/laravel-mix/setup), the publicPath is not defined there either.Gao
The code that generates those URLs is github.com/GoogleChrome/workbox/blob/v3.0.0/packages/… It effectively concatenates publicPath and the implicit URL that webpack creates for an asset. Can you provide a link to your full project that we could clone and try locally to reproduce?Miamiami
I have added steps to reproduce the problem from scratch using a standard Laravel installation with WorkboxGao
Project to demonstrate this problem: github.com/matthiku/laravelAndWorkboxGao
G
7

I found the solution:

As Laravel is using the "Laravel Mix" API to configure and run WebPack, the way to configure WebPack is to modify the file webpack.mix.js.

Jeff Posnick pointed me into the right direction. If I add the following lines into webpack.mix.js, the compiler produces a correct precache manifest file -

const { GenerateSW } = require('workbox-webpack-plugin');
mix.webpackConfig({
  plugins: [new GenerateSW()],
  output: {
    publicPath: ''
  }
});

The solution is to provide simply an empty string for the output.publicPath configuration option of webpack.

However, if you need to provide an actual path for the publicPath option, this workaround will fail. See bug report here: https://github.com/GoogleChrome/workbox/issues/1534

Gao answered 11/6, 2018 at 9:41 Comment(1)
This works fine unless I load a page with a path. For example on my page /goals/add/ it tries to load /goals/js/44.94b7a16456b6a9589b3f.js which obviously doesn't exist. Any ideas?Mobster

© 2022 - 2024 — McMap. All rights reserved.