Workbox: Correct setup with Webpack 4 + workbox

Created on 14 Nov 2018  Â·  3Comments  Â·  Source: GoogleChrome/workbox

I’m trying to create a webpack builder with workbox, as i can see Vue CLI 3 is using. In my package.json file, i’ve made a “build” script to build and compile the files and a “dev” script to run it with nodemon.

"build": "webpack --mode development",
"dev": "nodemon --inspect --watch webpack.config.js main.js"

I've tried both using GenerateSW, SWPrecacheWebpackPlugin and InjectManifest in order to create a dist folder with all the compiled files in it. When i'm running "npm run dev", i don't get any errors and the service worker is registered and running + using the cached files, but no manifest.json file. If i build the project and run this with "serve ./dist", i get multiple errors with both it can't find the manifest.json and Manifest: Line: 1, column: 1, Unexpected token. The service worker is registrered and installed.

The reason for this is because of my setup with Workbox in webpack.config.js.

webpack.config.js

const path = require('path')
const webpack = require('webpack')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin')
const {GenerateSW} = require('workbox-webpack-plugin')

module.exports = {
    mode: 'production',
    entry: {
        app: [
            '@babel/polyfill',
            './src/main.js'
        ]
    },
    output: {
        path: path.resolve(__dirname, 'dist/'),
        filename: '[name]-[hash].js',
        publicPath: '/'
    },
    devServer: {
        inline: false,
        contentBase: "./dist",
        overlay: true,
        hot: true,
        stats: {
            colors: true
        }
    },
    module: {
        rules: [
            {
                test: /\.html$/,
                use: {
                    loader: 'html-loader'
                }
            },
            {
                test: /\.js?$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
                query: {
                    presets: ['@babel/preset-env']
                }
            },
            {
                test: /\.css$/,
                loader: [
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: "style-loader"
                    },
                    {
                        loader: "css-loader", options: {
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-loader", options: {
                            sourceMap: true
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HTMLWebpackPlugin({
            template: './public/index.html'
        }),
        new GenerateSW({
            // include: [/\.html$/, /\.js$/, /\.css$/],
            // exclude: '/node_modules'
            swDest: 'service-worker.js',
            cacheId: 'sp-admin',
            importWorkboxFrom: 'local',
            clientsClaim: true,
            skipWaiting: true
        })
        // service worker caching
        // new SWPrecacheWebpackPlugin(
        //     {
        //         cacheId: 'webpack-project',
        //         filename: 'service-worker.js',
        //         staticFileGlobs: [
        //             'dist/**/*.{js,css}',
        //             '/'
        //         ],
        //         minify: true,
        //         stripPrefix: 'dist/',
        //         dontCacheBustUrlsMatching: /\.\w{6}\./
        //     }
        // )
    ]
}

This creates a dist folder which contains:

Workbox-v3.6.3 (folder)
app-5a8c3....js (file)
index.html (file)
precache-manifest.667272....js (file)
service-worker.js (file)

The index.html adds a script to the file which includes the app.5a8c3....js file (4262 lines of eval webpack require and stuff). It seems like it doesn't add the precache-manifest.667272....js file and therefore doesn't work properly.

My default index.html file (not in the dist folder) looks like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Webpack project</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="theme-color" content="#317EFB"/>
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <link rel="manifest" href="./manifest.json">
    <!-- Add to home screen for Safari on iOS -->
    <link rel="apple-touch-icon" href="./public/img/icons/apple-touch-icon-152x152.png">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-title" content="Webpack Project">
    <meta name="msapplication-TileImage" content="./public/img/icons/msapplication-icon-144x144.png">
    <meta name="msapplication-TileColor" content="#2F3BA2">
</head>
<body>
    <noscript>
        <strong>We're sorry but the website doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app">
        <main>
            <h1>Works</h1>
        </main>
    </div>
</body>
</html>

I guess the problem here is that i try to link the manifest.json file, which isn't available in the /dist folder.

The default manifest.json file looks like this:

{
    "name": "webpack-project",
    "short_name": "project",
    "icons": [
      {
        "src": "./img/icons/android-chrome-192x192.png",
        "sizes": "192x192",
        "type": "image/png"
      },
      {
        "src": "./img/icons/android-chrome-512x512.png",
        "sizes": "512x512",
        "type": "image/png"
      }
    ],
    "start_url": "http://localhost:8080/",
    "display": "standalone",
    "scope": "/",
    "background_color": "#3E4EB8",
    "theme_color": "#2F3BA2"
  }

The compiled (in the dist folder) looks like this:

self.__precacheManifest = [
  {
    "revision": "09b2f477206c07e780bfbbb7cc7203d7",
    "url": "/index.html"
  },
  {
    "url": "/app-5a8c38bd594811381d81.js"
  }
];

As i can see with Vue Cli 3, it also creates a lot of sub-files (i guess because of the file size), that are being added in the dist folder.

How do i make Workbox add the manifest.json file properly, so it also works for offline purposes + create a subfolder with subfiles with /css, /js, /img and /fonts?

Hope this makes sense and the project can be found here:

https://github.com/Fillah/webpack-project

Thanks in advance

Needs More Info workbox-webpack-plugin

Most helpful comment

I don't think the question you're asking is related to the Workbox configuration—it sounds more like a webpack-specific question, and you will likely have better luck asking in the webpack issue tracker, or on Stack Overflow. Apologies!

All 3 comments

Hello!

manifest.json normally refers to a web app manifest file, containing metadata about your web app that is used as part of an Add to Homescreen scenario. This file is not something that Workbox creates. If you've got a pre-existing manifest.json file in your source directory, and you want it copied over by webpack into your build directory, then using a plugin like webpack-copyfiles-plugin, which can move existing files from one location to the other is a good idea.

precache-manifest.<hash>.js is generated by Workbox, and contains a list of URLs to precache. This file is imported automatically by your Workbox-built service worker. In Workbox v3, it will explicitly not include a manifest.json file in the list of URLs to precache, even if manifest.json is included as part of your webpack assets, but that default changed in Workbox v4 (https://github.com/GoogleChrome/workbox/pull/1679). (And you can manually override the default in Workbox v3 if you so desire.)

Does that clear things up?

Ah that makes sense, thanks @jeffposnick. I will try looking into webpack-copyfiles-plugin.
But how do i, as like Vue Cli 3 is doing, create a subset of multiple javascript and css (code splitting) files when building the project instead of it just creates a app..js which contains it all? I guess it must be some kind of setting for Workbox in webpack config.

I don't think the question you're asking is related to the Workbox configuration—it sounds more like a webpack-specific question, and you will likely have better luck asking in the webpack issue tracker, or on Stack Overflow. Apologies!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

niveditaece picture niveditaece  Â·  3Comments

nevaan9 picture nevaan9  Â·  4Comments

alexander-theijs picture alexander-theijs  Â·  3Comments

truescotian picture truescotian  Â·  4Comments

kaycebasques picture kaycebasques  Â·  4Comments