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
3 Answers
Reset to default 5 +50Webpack 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",