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

workbox-webpack-plugin doesn't add an entry in the array for my index.html #1692

Closed
Richienb opened this issue Oct 10, 2018 · 13 comments
Closed
Labels
Needs More Info Waiting on additional information from the community.

Comments

@Richienb
Copy link

Library Affected:
workbox-webpack-plugin

Browser & Platform:
irrelevant

Issue or Feature Request Description:
When I use workbox-webpack-plugin's injectmanifest command in Webpack 3 and inspect the generated file, the output looks something like this:

self.__precacheManifest = [
  {
    "revision": "c6de43433d90181622aa",
    "url": "bundle.js"
  },
  {
    "revision": "33299ea0bd8e99ac4c4def3e01ee859a",
    "url": "bundle.css"
  }
];

The problem is that webpack doesn't cache my index.html despite being specified in the webpack.config.js file.

Reproduction steps:
Step 1: Cloning

The source code is here on GitHub but you can reproduce it locally by running:

git clone https://github.com/Richienb/richienb.github.io.git
git checkout 89bf8314fee14a8f994915d26db3a80b6df0589a .

Step 2: Navigate to directory

Fairly simple:

cd richienb.github.io
cd src

Step 3: Installation

This repository uses yarn so for this step, install yarn then install all the packages in a development environment

npm install -g yarn
yarn install --production false

Step 4: Locally host the site

In this step, tell webpack-dev-server to host a local server of the site

npm start

Step 5: Find the generated file

Inspect the command line output and find the file starting with precache-manifest. An example is pointed out below:

Project is running at http://localhost:8080/
webpack output is served from /
Hash: 47d2479a673bec7d5643
Version: webpack 3.12.0
Time: 34762ms
                                                Asset       Size  Chunks             Chunk Names
                                           bundle.css     118 kB          [emitted]
                                            bundle.js     245 kB       0  [emitted]  main
precache-manifest.15dc3d014eed9db2538054395c7d9c0b.js  186 bytes          [emitted]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                    service-worker.js       1 kB          [emitted]
   [7] ./node_modules/@material/ripple/index.js 20.2 kB {0} [built]

Step 6: Navigate to the site

Navigate to the generated file. For the example above, you would navigate to 127.0.0.1/precache-manifest.15dc3d014eed9db2538054395c7d9c0b.js.

Step 7: View the resulting file

The file will look similar to this:

self.__precacheManifest = [
  {
    "revision": "c6de43433d90181622aa",
    "url": "bundle.js"
  },
  {
    "revision": "33299ea0bd8e99ac4c4def3e01ee859a",
    "url": "bundle.css"
  }
];

As you can see, an entry for index.html clearly does not exist but in the webpack.config.js it is clearly declared. That is the problem.

@SamStonehouse
Copy link

I also have this issue, I have no index.html in my generated manifest but I use webpack to generate one. Did you get anywhere with this?

@Richienb
Copy link
Author

No, I haven't. Had to resort to using the Workbox CLI after running Webpack.

@SamStonehouse
Copy link

I've resolved my issue, it was to do with the ordering of webpack plugins, it seems the Workbox plugin must be last for it to pick up on some files. Hope this helps with your issue.

@jadjoubran
Copy link
Collaborator

Hey @Richienb
can you please show your webpack configuration?

@Richienb
Copy link
Author

Richienb commented Nov 16, 2018

All of the code including the Webpack configuration was given in the original comment in step 1 of reproducing the problem.

@jadjoubran
Copy link
Collaborator

Oh true I didn't see the GitHub repo
I'll take a look soon and let you know

@jadjoubran
Copy link
Collaborator

git checkout 89bf8314fee14a8f994915d26db3a80b6df0589a .
is the . (dot) at the end intentional?
I've tried with it, ended up with a state that has a webpack.config.js but running npm run build shows that index.html is part of the precache manifest
screen shot 2018-11-16 at 22 13 37

and I've tried running:
git checkout 89bf8314fee14a8f994915d26db3a80b6df0589a (without the .) which brought me to an older version of the project with no webpack.config.js

Can you please double check step 1 and let me know?
Thanks!

@jadjoubran jadjoubran added the Needs More Info Waiting on additional information from the community. label Nov 26, 2018
@jeffposnick
Copy link
Contributor

Given that the steps in #1692 (comment) were not able to reproduce the issue, I'm going to close this for now.

If there are a different set of steps that can reproduce the issue, please let us know and I'll reopen.

@blephy
Copy link

blephy commented Feb 22, 2019

Yes this is painfull.

I worked out previously in the same issue. I'm not even sure, but i remember this is a html-webpack-plugin problem. But whatever, i found a solution to this.

This will add index.html to the precache-manifest with a revision hash that only change when your sources change.

try this

Inject a HTML balise <meta name="hash" content="<%= webpack.hash %>" /> in your template.

Work with webpack 4.29.0and html-webpack-plugin 3.2.0.

This will force your template to change every build and workbox.injectManifest() to trigger it with correct revision hash change in the precache-manifest.

You should also use new webpack.HashedModuleIdsPlugin(),in your webpack plugins config.

I confirm that your plugins array list order is important.

// htmlWebpackPlugin options used
{
  template: 'src/index.ejs',
  filename: 'index.html',
  minify: true,
  xhtml: true,
  ...
}

To make your template with other template engine : https://github.com/jantimon/html-webpack-plugin/blob/master/docs/template-option.md

My production webpack plugins array config :

...
plugins: [
    new CleanWebpackPlugin([configInstance.path.relativeFolderBuild], {
      root: configInstance.path.root
    }),
    new CircularDependencyPlugin({
      exclude: /node_modules/,
      failOnError: true,
      allowAsyncCycles: true,
      cwd: process.cwd()
    }),
    new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en|fr/),
    new webpack.DefinePlugin(configInstance.exported_variables),
    new webpack.optimize.MinChunkSizePlugin({
      minChunkSize: 20000
    }),
    new webpack.HashedModuleIdsPlugin(),
    new HtmlWebPackPlugin({
      meta: configInstance.config.html.meta,
      title: configInstance.config.html.title,
      template: configInstance.path.html,
      filename: 'index.html',
      favicon: configInstance.favicon,
      minify: true,
      xhtml: true
    }),
    new WebpackPwaManifest({
      name: configInstance.config.pwa.name,
      short_name: configInstance.config.pwa.short_name,
      description: configInstance.config.html.meta.description,
      display: configInstance.config.pwa.display,
      theme_color: configInstance.config.pwa.theme_color,
      background_color: configInstance.config.pwa.background_color,
      inject: true,
      fingerprints: true,
      start_url: '.',
      ios: true,
      icons: configInstance.pwaIcons
    }),
    new MiniCssExtractPlugin({
      filename: configInstance.path.cssFileName,
      chunkFilename: configInstance.path.cssChunkFileName,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true
      }
    }),
    new webpack.BannerPlugin({
      banner: configInstance.banner
    }),
    new CopyWebpackPlugin(
      [
        {
          from: path.join(configInstance.path.public, 'humans.txt'),
          to: configInstance.path.toServe,
          transform: content => `${content}  Last update: ${configInstance.startBuildTime}`,
          cache: true
        }
      ],
      { debug: 'warning' }
    ),
    new ResourceHintWebpackPlugin(),
    new WebpackMonitor(configInstance.monitor),
    new BundleAnalyzerPlugin(configInstance.analyzer),
    new WorkboxPlugin.InjectManifest({
      swSrc: path.join(configInstance.path.public, 'service-worker.js'),
      swDest: 'service-worker.js',
      importWorkboxFrom: 'cdn'
    })
  ]
...

My .ejstemplate :

<!DOCTYPE html>
<html lang="fr" prefix="og: http://ogp.me/ns#">
  <head>
    <base href="/" />
    <meta charset="utf-8" />
    <title><%= htmlWebpackPlugin.options.title %></title>
    <link rel="author" href="/humans.txt" />
    <meta name="hash" content="<%= webpack.hash %>" />
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run the application : 
      <a src="https://www.enable-javascript.com/">https://www.enable-javascript.com/</a>
    </noscript>
    <div id="app"></div>
  </body>
</html>

The resulting precache-manifest build by workbox.injectManifest()

Capture-d-e-cran-2019-02-22-a-19-27-12

@claymation296
Copy link

claymation296 commented Dec 12, 2019

Thanks @blephy , I've been searching for days to find a solution!

Adding the meta tag to my index.html fixed my problem with workbox v4 serving outdated precached files.

For anyone else running into this issue, I'm using GenerateSW with webpack v4 and workbox 4.3.1.

@govizlora
Copy link

I have the same issue with html-webpack-plugin. There is a naiver solution using the additionalManifestEntries parameter. Though, I don't know how to generate the hash, so I used the current time for the revision.

@blephy
Copy link

blephy commented Apr 28, 2021

Yep, you can use this #2299 (comment)

@gavinbarron
Copy link

@blephy thank you, that was the missing link for me. I had to adjust for webpack5, but you got me close enough I could connect the dots from there.

For anyone visiting this using webpack5 and htmlWebpackPlugin 5.x the setup is a little different to access the hash in your template now as the options have changed a fair bit and you need to inject the hash using customized templateParameters:

new HtmlWebpackPlugin({
    template: `${sourcePath}/index.html`,
    filename: 'index.html',
    title: siteTitle,
    templateParameters: (
        compilation,
        assets,
        assetTags,
        options
    ) => {
        return {
            compilation,
            webpackConfig: compilation.options,
            htmlWebpackPlugin: {
                tags: assetTags,
                files: assets,
                options,
            },
            hash: compilation.getStats().hash,
        };
    },
    inject: true,
    hash: true,
    minimize: true,
}
    <meta name="hash" content="<%= hash %>" />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Info Waiting on additional information from the community.
Projects
None yet
Development

No branches or pull requests

8 participants