In this article we are going to give a brief description how to modify your webpack.config.js file to enable hot module replacement.
First off, install all necessary dependencies:
1 2 3 |
npm install --save-dev browser-sync webpack@1 webpack-dev-middleware webpack-hot-middleware monkey-hot-loader rimraf //or yarn add -D browser-sync webpack@1 webpack-dev-middleware webpack-hot-middleware monkey-hot-loader rimraf |
Once the installation is ready, create the file hot.webpack.js that will proxify our local server and will be reassembling the project in case any files are modified and will be updating those files in browser in real time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/** * Require Browsersync along with webpack and middleware for it */ let browserSync = require('browser-sync').create(); let webpack = require('webpack'); let webpackDevMiddleware = require('webpack-dev-middleware'); let webpackHotMiddleware = require('webpack-hot-middleware'); let webpackConfig = require('./webpack.config.js'); /** * Require ./webpack.config.js and make a bundler from it */ const bsPort = 3000; webpackConfig.watch = false; webpackConfig.output.publicPath = `http://localhost:${bsPort}/ps/themes/classic/assets/js/` // url to webpack output path let bundler = webpack(webpackConfig); /** * Run Browsersync and use middleware for Hot Module Replacement */ browserSync.init({ open: true , port: bsPort , proxy: { target: `http://localhost:88` //host your local webserver } , src: [`./templates/**/*.tpl`, `./modules/**/*.tpl`] // full page reload if .tpl file changed , middleware: [ webpackDevMiddleware( bundler, { // IMPORTANT: dev middleware can't access config, so we should // provide publicPath by ourselves publicPath: webpackConfig.output.publicPath , stats: { colors: true , chunck : false} , hot: true } ), webpackHotMiddleware( bundler ) ] }); |
‘browser-sync’ serves as a connecting link to our local server which has prestashop 1.7 and webpack with webpack-dev-middleware and webpack-hot-middleware installed.
An important note: In the webpack config file you should specify output.publicPath, indicate browser-sync server’s host, port number and also disable watch = false!
A browser sends requests to browser-sync server and the server then redirects them to the middleware array. Then webpack-dev-middleware verifies the url of the query and publicPath. If they coincide webpack-dev-middleware searches memory for the file and forwards the file to the browser, otherwise forwards the request further to the local server.
Note: webpack-dev-middleware does not save the project on the hard drive but keeps it in memory (memory-fs).
BrowserSync also has its own wather: browserSync settings let you configure a task to monitor *.tpl templates and reload page every time the templates are modified.
Next you should modify webpack.config.js Create a HOT constant which will provide compatibility with the default webpack. Add an option to disable ExtractTextPlugin when in “hot mode” because we do not need to collect all styles into a single .css file.
1 2 3 4 5 6 |
> new ExtractTextPlugin( path.join('..', 'css', 'theme.css') ,{ disable: HOT // if hot enabled disable ExtractTextPlugin } ) |
Modify entries with the help of the addHOT function. We will be adding scripts that will provide interaction between browser and assembler into the project.
1 2 3 4 5 6 7 8 9 10 11 12 |
let addHOT = (arr, disable) => { if (HOT) { arr.unshift('webpack/hot/dev-server', 'webpack-hot-middleware/client'); } return arr; }; /// module.exports = { entry: { theme: addHOT(['./js/theme.js']) }, /// |
Add HotModuleReplacementPlugin
1 2 3 |
if (HOT) { plugins.push(new webpack.HotModuleReplacementPlugin()) } |
Add a new loader to all .js files : monkey-hot-loader
1 2 3 4 5 6 7 |
module: { loaders: [{ test: /\.js$/, exclude: /node_modules/, loaders: (HOT? ['monkey-hot-loader','babel-loader']: ['babel-loader']) }]} //... |
Everything is ready now, so let’s run the assembler in ‘hot mode’:
1 |
node ./hot.webpack.js |
Once started, the browser will launch our proxified web-server. If you open the developers console you will see how the browser communicates with the webpack module and updates all files in real time.
The code provided in this article is also available in our test repository: https://github.com/retyui/prestashop-1.7-webpack-hot-module-replacement/
This will help you better understand the concept of hot module replacement.
Thank you for answer, for the first I use
path: path.resolve(__dirname + ‘/../assets/js’),
and it builds.
for the hot config I tried:
localhost:${bsPort}/themes/classic/assets/js/
demo.dev:${bsPort}/themes/classic/assets/js/
localhost:3000/themes/classic/assets/js/
demo.dev:3000/themes/classic/assets/js/
Still same problem. When I change something in theme.scss I see this in console: https://gyazo.com/a05847a2d83380259a724eb856064eec but browser not reload any part, and even manual reload not shows new style.
P.S. I use your build for webpack2, just renamed theme and changed it in theme.yml to ‘classic’.
Hi, Roy!
Please, create an issue at GitHub https://github.com/retyui/prestashop-1.7-webpack-2-hot-module-replacement/issues
Hello, Roy!
It’s a common mistake. Usually, it happens because of the incorrect setting of
webpackConfig.output.publicPath
, that is used bywebpackDevMiddleware
to compare the local file and the URL on the web-page.To fix the mistake check if the way is correct:
1) for webpack
https://github.com/retyui/prestashop-1.7-webpack-hot-module-replacement/blob/master/_dev/webpack.config.js#L47
2) and for webpackDevMiddleware. In the example, I use URL for a default
classic
themehttps://github.com/retyui/prestashop-1.7-webpack-hot-module-replacement/blob/master/_dev/hot.webpack.js#L14
I’m sorry, thank you, my bad of course. I changed and it works. But now I have a problem: css file builds when I use npm run build https://gyazo.com/6501859d1775edb6dc77ac84dd78e491 , but not builds if I use npm run hot. https://gyazo.com/3679e07c2fcdeec3b993f219907a74e5
If I change something in files – in cmd I see that webpack run building, then I see succesfull message, but browser not reloads. And if I reload it by hands I see Connected to browsersync message.
Sorry, I’m new to webpack. Appreciate your help.
Hello, Roy!
Check the config of
browsersync
, I mean HOST and port of a local proxy serverhttps://github.com/retyui/prestashop-1.7-webpack-2-hot-module-replacement/blob/master/_dev/hot.webpack.js#L25
Thank you a lot! I used github version for webpack 2. But I have a problem – localhost:3000 which opens after bulid, gives me unlimited loading and then ERR_EMPTY_RESPONSE. Here is what I have in cmd: roythemes.com/z_download/webpack.png
Before it, with classic webpack config – I had normal access to website after build. Maybe you have some ideas?
Is it possible to try this on Prestashop 1.6?
GUYS your ROCK, NO SERIOUSLY.
I have a little knowledge of Webpack and Node.js
I tried to configure myself using the code on the Githab, tried it for about 4 hours, then I decided to ask for help, since I had no chance do it myself.
And now the main thing, I was helped by David from the company Belvg, for FREE, no, seriously, he spent more than 2 hours of his time to set it up.
To be honest, I did not meet such a good impression and attitude anywhere, and I worked with many people.
These manuals, this manual can save your life.
I spent about a month or even more trying to set it up myself, seriously, a month.
No one, no company, and even PrestaShop, did such a manual.
These guys are the best, they are just the best.
The best service you will not find anywhere else.
I’m shocked, seriously, I decided my biggest headache with 1.7, only with Belvg
P.S.
One of the main problems was double slashes //
References to styles and scripts were generated with double slashes, on a local environment, this prevented the HMR
Best Regards,
Alexandr
Thx for great guide, its working!
If not working file watcher, add
plugins.push(
new webpack.OldWatchingPlugin()
);
in webpack.config.js, for webpack 1.12+ version.