16

I am working on a web application developed using reactjs and webpack. After every deployment, we have to ask users to clear the browser cache and restart their browsers. I think the javascript bundle file and css file both are getting cached on user browser.

How can we force browser not to cache these files or make it download the latest files from the server.

<html>
  <head>
    <meta charset="utf-8">
    <title>My App</title>
            <link rel="stylesheet" href="styles.css" media="screen" charset="utf-8">
  </head>
  <body>
    <div id="app"></div>
    <script src="bundle.js"></script>
  </body>
</html>
OpenStack
  • 5,048
  • 9
  • 34
  • 69

3 Answers3

11

You can use html-webpack-plugin

plugins: [
    new HtmlWebpackPlugin({
        hash: true
    })
]

hash: true | false if true then append a unique webpack compilation hash to all included scripts and css files. This is useful for cache busting.

Jack
  • 8,851
  • 3
  • 21
  • 26
  • Thank you for quick reply. I am getting following error `Failed to load resource: the server responded with a status of 404 (Not found)` for file `bundle.js?1c03629db68f03ac936e` & similar error is coming for `styles.css?1c03629db68f03ac936e` file. I installed the npm package and simple added the code shown by you in webapck config file. after building and deploying I am getting error. when I run the application locally I get following error `ncaught Invariant Violation: _registerComponent(...): Target container is not a DOM element.` – OpenStack Apr 07 '16 at 17:08
  • Make sure the html file generated from `HtmlWebpackPlugin` is referencing the files correctly. I don't know how you're project is set up so it might think your distribution directory structure is different than it is. – Jack Apr 07 '16 at 18:12
  • I think the problem is, the query string is not in correct format. instead of key value pair, the file is just value. by that I mean instead of `bundle.js?v=1c03629db68f03ac936e` its coming as `bundle.js?1c03629db68f03ac936e`. the `key` is missing. Did I miss a configuration option. – OpenStack Apr 07 '16 at 21:25
  • this work with 'webpack' or need 'webpack-dev-server' ? – stackdave Aug 08 '17 at 19:56
  • @stackdave I think it should work with just webpack, it would do the hashing during the build process. – Jack Aug 10 '17 at 14:14
4

you should use html-webpack-plugin with an template html and put hash configuration in output. So your webpack config will look something like this:

    output: {
        filename: "[name].[hash].js",
        path: <path to your bundle folder>
      }
     new HTMLWebpackPlugin({
          hash: true,
          template: paths.resolveFromRoot("src/index.html") //where you want the sample template to be
        })

And your index.html will be something like this:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="expires" content="0">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
</body>
</html>

The HTML webpack plugin will automatically insert the revised script in the index.html created in your bundle folder. Hope this helps. For caching fix you can refer to https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching where versioning and server response header configurations is mentioned for effective caching solutions.

Pranay Tripathi
  • 1,614
  • 1
  • 16
  • 24
2

There is an easy way to avoid this problem without any extra stuff. Use webpack's built-in hashing ability.

You can read about adding hash to your bundle here. While the title of this is "Long term caching" it's only true in case when your files doesn't change. But if you rebuild your bundle it get new unique hash, so browser would think it is new file and download it.

gyzerok
  • 1,338
  • 2
  • 11
  • 26
  • 1
    assuming I am using `filename: '[hash].bundle.js',` in my webpack.config file. which generates a file like this `3d161aa1fedaca1ca95b.bundle`. Now how do I update my index.html file which is still including bundle.js file like ``. The article also says `Note that you need to reference the entry chunk with its hash in your HTML. You may want to extract the hash or the filename from the stats.` Am I missing something here ? – OpenStack Apr 07 '16 at 17:32
  • You can find answer to this in the last chapter https://webpack.github.io/docs/long-term-caching.html#get-filenames-from-stats. After build you can look in the stats.json to see actual bundle name and then pass it to your html template. – gyzerok Apr 07 '16 at 17:51
  • Thank you for the reply. I looked at the `assets-webpack-plugin`, they say `This plug-in outputs a json file with the paths of the generated assets so you can find them from somewhere else.` but I don't see an example which explains how they are updating the reference file name in `index.html` – OpenStack Apr 07 '16 at 21:15
  • 1
    Oh, they do not update index.html. You should probably use some template engine to generate index.html and pass generated assets to it as variables. Your flow: 1. build with webpack and get stats.json 2. read stats.json while starting the server 3. pass right paths from stats.json to your html – gyzerok Apr 08 '16 at 07:44