最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Webpack cache busting with hashes not working - Stack Overflow

programmeradmin1浏览0评论

I am trying do cache busting using webpack by adding a hash to the end of each javascript file. My webpack configuration file is below:

const AssetsPlugin = require('assets-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
//const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: "./js/main.js",
    output: {
        path: __dirname + '/static/',
        publicPath: '',
        filename: "bundle-[hash].js",
    },
    resolveLoader: {
    moduleExtensions: ['-loader']
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /(node_modules|bower_ponents)/,
                loader: 'babel',
                query: {
                    presets: ['react', 'es2015', 'stage-0']
                }
            },
            {
                test: /\.css$/,
                loader: 'style-loader',
            },
            {
                test: /\.css$/,
                loader: 'css-loader',
                query: {
                    modules: true,
                    localIdentName: '[name]__[local]___[hash:base64:5]'
                }
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(['static/bundle*.js'], {watch: true}),
        new AssetsPlugin({
                filename: 'static/webpack.assets.json',
                prettyPrint: true
        }),
    ]
};

The index.html file which serves the javascript file created by webpack is below:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" >
            $.getJSON('webpack.assets.json', function(data){
                <!--
                var bundleScript = "<script src=" + data['main']['js'] + "></script>";
                var div = document.getElementById('app');
                div.innerHTML = bundleScript;
                $(bundleScript).appendTo('#app');
                //!-->
            });
        </script>
    </head>

    <body>
        <div id="app"></div>
    </body>
</html>

When I make changes to the code, I have to hard refresh the browser in order to see the changes, instead of just plain refreshing, which I would expect if the cache busting were to work. Any help is appreciated; thanks!

I am trying do cache busting using webpack by adding a hash to the end of each javascript file. My webpack configuration file is below:

const AssetsPlugin = require('assets-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
//const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: "./js/main.js",
    output: {
        path: __dirname + '/static/',
        publicPath: '',
        filename: "bundle-[hash].js",
    },
    resolveLoader: {
    moduleExtensions: ['-loader']
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /(node_modules|bower_ponents)/,
                loader: 'babel',
                query: {
                    presets: ['react', 'es2015', 'stage-0']
                }
            },
            {
                test: /\.css$/,
                loader: 'style-loader',
            },
            {
                test: /\.css$/,
                loader: 'css-loader',
                query: {
                    modules: true,
                    localIdentName: '[name]__[local]___[hash:base64:5]'
                }
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(['static/bundle*.js'], {watch: true}),
        new AssetsPlugin({
                filename: 'static/webpack.assets.json',
                prettyPrint: true
        }),
    ]
};

The index.html file which serves the javascript file created by webpack is below:

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" >
            $.getJSON('webpack.assets.json', function(data){
                <!--
                var bundleScript = "<script src=" + data['main']['js'] + "></script>";
                var div = document.getElementById('app');
                div.innerHTML = bundleScript;
                $(bundleScript).appendTo('#app');
                //!-->
            });
        </script>
    </head>

    <body>
        <div id="app"></div>
    </body>
</html>

When I make changes to the code, I have to hard refresh the browser in order to see the changes, instead of just plain refreshing, which I would expect if the cache busting were to work. Any help is appreciated; thanks!

Share Improve this question asked Sep 21, 2017 at 16:09 AlexAlex 4,26411 gold badges43 silver badges67 bronze badges 1
  • I think adding --watch in webpack server running script will help you – Gaurav Paliwal Commented Sep 29, 2017 at 20:59
Add a ment  | 

3 Answers 3

Reset to default 5 +50

Webpack cache busting still working in here. If you change the code, webpack will recreate the file with the different hash (https://webpack.js/guides/caching)

What you want is called hot reload. You can read more about it in https://webpack.js/concepts/hot-module-replacement/

To use hot reload, you should create new config:

const AssetsPlugin = require('assets-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
entry: "./js/main.js",
output: {
    path: __dirname + '/static/',
    publicPath: '',
    filename: "bundle.js", // remove hash
},
resolveLoader: {
moduleExtensions: ['-loader']
},
module: {
    loaders: [
        {
            test: /\.jsx?$/,
            exclude: /(node_modules|bower_ponents)/,
            loader: 'babel',
            query: {
                presets: ['react', 'es2015', 'stage-0']
            }
        },
        {
            test: /\.css$/,
            loader: 'style-loader',
        },
        {
            test: /\.css$/,
            loader: 'css-loader',
            query: {
                modules: true,
                localIdentName: '[name]__[local]___[hash:base64:5]'
            }
        }
    ]
},
plugins: [
    // new CleanWebpackPlugin(['static/bundle*.js'], {watch: true}), ment it
    // new AssetsPlugin({
    //        filename: 'static/webpack.assets.json',
    //        prettyPrint: true
    // }), and this 
],
devServer: {
  contentBase: path.join(__dirname, "static"),
  press: true,
  port: 9000
}
};

And run with: webpack-dev-server -c 'your new config' --hot

The index.html is served only once to the browser. The code written inside this html file to load the assets also runs for the one time only in the browser. Once you make changes in your code, webpack can create new bundle with new hash name but your browser doesn't aware of this and won't download new assets file by itself. This is the reason why your changes are not reflecting in your browser. Cache busting is monly used for production build. For development environment hot module reloading is used. Below is an example of hmr.

webpack.config.dev.js

/**
 * Created by ishan.trivid on 28-06-2016.
 */
import webpack from "webpack";
import path from "path";

export default {
debug: true,
devtool: "cheap-module-eval-source-map",
noInfo: true,
entry: [
    "eventsource-polyfill", // necessary for hot reloading with IE
    "webpack-hot-middleware/client?reload=true", //note that it reloads the page if hot module reloading fails.
    "./src/index"
],
target: "web",
output: {
    path: __dirname + "/dist", // Note: Physical files are only output by the production build task `npm run build`.
    publicPath: "/",
    filename: "bundle.js"
},
devServer: {
    contentBase: "./src"
},
plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
],
module: {
    loaders: [
        {test: /\.js$/, include: path.join(__dirname, "src"), loaders: ["babel"]},
        {test: /(\.css)$/, loaders: ["style", "css"]},
        {test: /\.(png)$/, loader: "url-loader?limit=1000000"},
        {test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file"},
        {test: /\.(woff|woff2)$/, loader: "url?prefix=font/&limit=5000"},
        {test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream"},
        {test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml"}
    ]
}
};

srcServer.js

import express from "express";
import webpack from "webpack";
import path from "path";
import config from "./webpack.config.dev";
import open from "open";

const port = 3000;
const app = express();
const piler = webpack(config);

app.use(require("webpack-dev-middleware")(piler, {
    noInfo: true,
    publicPath: config.output.publicPath
}));

app.use(require("webpack-hot-middleware")(piler));

app.get("*", function(req, res) {
    res.sendFile(path.join( __dirname, "../src/index.html"));
});

app.listen(port, function(err) {
    if (err) {
        console.log(err);
    } else {
        open(`http://localhost:${port}`);
    }
});

Now add below mand in script section of package.json

start: "babel-node srcServer.js"

Now run "npm run start" mand in terminal

here is example from my config file

install babel hmre plugin

npm install --save-dev babel-preset-react-hmre


module.exports = {
  // entry and output options

  module: {
    loaders: [{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: "babel",
      include: __dirname,
      query: {
        presets: [ 'es2015', 'react', 'react-hmre' ]
      }
    }]
  }
}

and edit your start script in package.json to enable the hot option:

"start": "webpack-dev-server --progress --inline --hot",
发布评论

评论列表(0)

  1. 暂无评论