Today we will cover the development value of the mode property. It will automatically set the webpack configuration for you to make the development easier. Aside from that, we will also cover the wepback-dev-server and webpack-serve – Hot Module Replacement included. Let’s go!
Webpack 4 course: a development server
A one step forward to a better development experience is running webpack in the
watch mode. Try running
webpack --watch
. Now, every time you make some changes, Webpack will rebuild your project and outputs he code.
Webpack-dev-server does that and more. Instead of writing files to the destination directory, it handles them in memory. After building, the output is served locally.
Running webpack-dev-server
The first thing to do is to install it.
npm install webpack-dev-server
The second one is to add it to the scripts in your package.json
"scripts": {
"build": "webpack",
"start": "webpack-dev-sever"
}
Now to run it, just type
npm start
. You will be greeted with a message such as:
「wds」: Project is running at http://localhost:8080/
The only thing left is to open http://localhost:8080/ in your browser.
Every time you make a change to your code, the site gets updated and after refreshing the page, you can see your changes.
Hot Module Replacement
To make your development experience even better, you can skip the need to refresh the page with the Hot Module Replacement. For example, when you make a change to some of your styles, you don’t need to reload the whole application to see the changes.
In the fourth part of the course we’ve used MiniCssExtractPlugin. Please note, that in the moment of writing this article, Hot Module Reload support for MiniCssExtractPlugin is still yet to come. For more information visit this GitHub issue. For now you might want to stick for the style-loader while in the development environment.
When you run webpack-dev-server it uses the same configuration file as a regular build. There is a parameter that you can add to your webpack.config.js that allows you some additional options. It is called devServer. We need it to enable the Hot Module Replacement.
devServer: {
hot: true,
}
The last thing left to do is to add
webpack.HotModuleReplacementPlugin
to your plugins.
webpack.config.js
const webpack = require('webpack');
module.exports = {
devServer: {
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
Note that running webpack-dev-server with the –hot flag would also add HotModuleReplacementPlugin to your plugins. Doing it twice could give you problems.
Works like a charm with our CSS, but when it comes to the JavaScript, it needs one additional step.
index.js
import { divide } from "./divide";
console.log(`6 / 2 = ${divide(6,2)}`);
if(module.hot) {
module.hot.accept();
}
divide.js
export function divide(a, b) {
return a/b;
}
Running
module.hot.accept()
will make the module replaceable. This also applies to all other modules that it imports. With the code above it means that running
accept()
in
index.js makes the
divide module replaceable also.
The function
module.hot.accept()
can be ran with additional configuration. If you are interested, check out the documentation.
You will encounter some problems when using chunkhash in your output filename while using HotModuleReplacementPlugin. It might be a good idea to use HotModuleReplacementPlugin only with the development server (and not using chunkhash then).
webpack.config.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const isDevServer = require.main.filename.includes('webpack-dev-server');
const plugins = [
new HtmlWebpackPlugin({ template: './src/index.html' }),
];
if(isDevServer) {
plugins.push(new webpack.HotModuleReplacementPlugin());
}
module.exports = {
output: {
filename: isDevServer ? '[name].bundle.js' : '[name].[chunkhash].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins,
devServer: {
hot: true
}
}
webpack-serve
Even though webpack-dev-server was used for quite some time, now it is maintenance-only mode and will not be accepting any additional features anytime soon. Because of that, it might be a good idea to check out its successor: the webpack-serve. A thing to keep in mind is that it uses WebSockets. If you are wondering if the browsers that you want to test the project on are compatible, check the compatibility table.
npm install webpack-serve
package.json
"scripts": {
"build": "webpack",
"start": "webpack-serve"
}
A very important note is that it uses
Hot Module Replacement by default, so adding
webpack.HotModuleReplacementPlugin
would result in an error.
The webpack-serve is relatively new compared to webpack-dev-server, but it is definitely worth checking out.
mode: “development”
In the previous part of the course, we’ve covered the production value of the mode parameter. This is the time for the development. Let’s go through what it does for us.
DefinePlugin
As said previously, this plugin allows you to create global constants resolved at compile time.
Since this plugin is used also in the
mode:production
, for a more detailed explanation check out Webpack 4 course – part five. Built-in optimization for production
This time the value is
"process.env.NODE_ENV": JSON.stringify("development")
:
module.exports = {
mode: "development",
// using mode: "development" attaches the following configuration:
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("development")
}),
]
}
NamedModulesPlugin
This is another plugin that is added when using
mode: "development"
. It is useful while using
Hot Module Replacement. Thanks to
NamedModulesPlugin we can see the relative path of the replaced module.
[WDS] App updated. Recompiling...
[WDS] App hot update...
[HMR] Checking for updates on the server...
[HMR] Updated modules:
[HMR] - ./src/style.css
[HMR] App is up to date
Otherwise, we would just see an id of the module instead of, for example,
./src/style.css
.
NamedChunksPlugin
It serves a little similar purpose to the
NamedModulesPlugin. Thanks to
NamedChunksPlugin, not only your modules will have a name, but also chunks. You can look them up in the
window.webpackJsonp
property when your application runs in the browser.
An additional advantage to NamedModulesPlugin and NamedChunksPlugin is that you no longer use ids that can change with adding and removing dependencies. Since ids or names are used in actual output files, changing them will change the hash of the file, even if the content of the module did not change. Using NamedModulesPlugin and NamedChunksPlugin will help you deal with caching in browsers. Let’s compare some output code.
Without NamedModulesPlugin and NamedChunksPlugin:
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[2],{
/***/ 6:
(...) // divide.js module output code
/***/ 7:
(...) // substract.js module output code
]);
Using NamedModulesPlugin and NamedChunksPlugin:
(window["webpackJsonp"] = window["webpackJsonp"] || []).push([["utilities~main"],{
/***/ "./src/utilities/divide.js":
(...) // divide.js module output code
/***/ "./src/utilities/substract.js":
(...) // substract.js module output code
]);
Devtool
Aside from adding some plugins, setting
mode: "production"
does one more thing. It enables Source Maps by setting the value of
devtool to
eval.
module.exports = {
mode: "development",
// using mode: "development" attaches the following configuration:
devtool: "eval"
}
Transpiling, uglifying and bundling your code can make the life of your users easier. After this process, the code is smaller and performs better. Debugging such code would be really difficult though. Because of that, the Source Maps were introduced. They map your output code with their source files. Thanks to that, you can use the debugger easier and set breakpoints while looking in the actual code and not the one that was served to the browsers. We will dig deeper into source maps in the upcoming parts of the course, but if you feel the need to customize it now, check out the documentation.
Summary
Webpack is a great tool for developing modern web applications. It not only lets you optimize your code for production but also can be customized in a way that makes your development experience better. This time we’ve covered running a development server and the development value of the mode property. We’ve also learned how to use Hot Module Replacement. All of these things combined can greatly help you develop your applications easier and faster.
The post Webpack 4 course – part six. Increasing development experience appeared first on Marcin Wanago Blog - JavaScript, both frontend and backend.