Webpack is one of most commonly used module bundlers available now. It eases the developer's job and provides blazing fast performance coupled with amazing features. From the days of task runners like Grunt and Gulp to Module Bundlers , front-end application development has never been so easier and engaging as today.
"Webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles"
Read the core concepts from here
Please note that the sole purpose of this article is to help to quickly build a neat webpack build configuration for a webapps. If you are more interested in learning the basics/core concepts of webpack please refer the above mentioned link to get to know about core concepts of webpack.
Let's Dive in
- Create a directory
mkdir webpack101 && cd webpack101
- Use NPM or Yarn for package management
npm init
ORyarn init
It will generate thepackage.json
file. Yarn is my favorite , so throughout in this guide yarn will be used. - Install webpack locally(recommended)
yarn add --dev webpack webpack-cli
You can see the webpack being added as dev dependencies in package. - Now lets create a sample project with our usual stuffs.You can find the source files here
Now the project structure is ready let's bring in the main player
webpack.config.js
. Create the webpack.config.js
in the root.
- Now that the initial configuration is ready,lets modify our
package.json
to add the build command. - Now let's run the build command
yarn build
- We now have a
bundle.js
inside the dist folder.For the sake of cache busting , include[chunkhash]
in the output js file configuration of webpack. So each time the generated js file will be in the formatbundle.[chunkhash].js
.
Naturally our dist
folder will be cluttered with many files. So we need to add
clean-webpack-plugin
.
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
......
plugins: [
new CleanWebpackPlugin(),
....
]
But that does not the serve the whole purpose. So let's add more to the webpack.config.js
.
Working with ES6
Let's modify our index.js
and add some behaviour using ES6. Since the code is in ES6 we need to transpile it so that the browser can understand. Here loaders come for the rescue, and do the code transformation for us.
- Adding Babel to the project. We specify the rules in the module section to add
the each loaders in
webpack.config.js
. Thetest
property identifies which file or files should be transformed. Theuse
property indicates which loader should be used to do the transforming.yarn add --dev babel-loader @babel/core @babel/preset-env
Modify the ourwebpack.config.js
as below.
module:{
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: {
presets: ["@babel/preset-env"]
}
}
}
]
}
- Add a
.babelrc
file with contents as below.
{
"presets": [
"@babel/preset-env"
]
}
But how do we see the magic happening? So let's add the webpack-dev-server
to run the project locally.
yarn add --dev webpack-dev-server
Also modify the package.json the script to run the dev server and then run
yarn serve
. "serve": "webpack-dev-server --open --config webpack.config.js"
- With the css preprocessors taking the significant role in the web development
these days , lets create sass files and add loaders to transform and bundle
it.
yarn add --dev style-loader css-loader node-sass sass-loader
Themini-css-extract-plugin
helps us to extract all styles and bundle it in our dist directory. UseMiniCssExtractPlugin.loader
instead of style-loader if you need a separatebundle.css
file as the style-loader injects all the styles in thehead
element of your html.yarn add --dev mini-css-extract-plugin
Add the loaders to ourwebpack.config.js
as below.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
......
plugins: [
new MiniCssExtractPlugin({
filename:"bundle.[chunkhash].css"
}),
....
]
.....
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: "css-loader"
},
{
loader: "sass-loader"
}
]
}
Now comes the role of plugins. We need to modify our HTML files, copy some of the assets to build folder and so on and to do that we need to add certain webpack plugins.
- Adding
HtmlWebpackPlugin
, it generates an HTML file with generated bundle files,both js & css, integrated in thescript
andlink
tags. We can even specify the template as well.yarn add --dev html-webpack-plugin
Now modify ourwebpack.config.js
to add the plugin.
var HtmlWebpackPlugin = require('html-webpack-plugin');
.............
plugins: [new HtmlWebpackPlugin(
{
title: 'My App',
template:'./src/index.html',
'meta': {
'viewport': 'width=device-width, initial-scale=1, user-scalable=no'
}
}
)]
What about assets like fonts, images..Let's add copy-webpack-plugin
. The
reason why file-loader
was not used because it loads on those assets
referenced in our modules.
yarn add --dev copy-webpack-plugin
Add the configurations for the plugin as well inside
webpack.config.js
. const CopyPlugin = require('copy-webpack-plugin');
new CopyPlugin([
{ from:'./src/assets', to:'assets' }
])
And finally all our assets
are copied to build directory.
Preparing for Different environments
We could actually maintain separate webpack comfiguration files for
development and production deployment, with production files having
production configurations included.
Let's create webpack.common.config.js
. Remove all the contents from the
current webpack.config.js
and paste it in the new file.Change the output path
options as path:path.resolve(__dirname, '../dist'),
Add the below script in the webpack.config.js
to configure different
environments.
const webpackMerge = require('webpack-merge');
const commonConfig = require('./webpack.common.config.js');
module.exports = ({ env }) => {
const envConfig = require(`./webpack.${env}.config.js`);
return webpackMerge(commonConfig, envConfig);
};
Make sure you have the webpack-merge
yarn added as dev-dependency.
Now we can to create webpack.dev.config.js
and webpack.prod.config.js
.
Include the development specific feature config in the webpack.dev.config.js
as below.If they existed in your webpack.common.config
remove it to avoid
unexpected results.
module.exports={
mode:"development",
devServer:{
port:3000,
hot: true,
contentBase:'./dist'
},
devtool:"inline-source-map"
}
Same for the webpack.prod.config.js
. I leave up to you if you require source-
map in prod mode.
module.exports={
mode:"production",
devtool:"source-map"
}
Modify the scripts to run for different environment in package.json
to look
more meaningful.
"scripts": {
"serve": "webpack-dev-server --open --config build-config/webpack.config.js
--env.env=dev",
"build:dev": "webpack --config build-config/webpack.config.js
--env.env=dev",
"build:prod": "webpack --config build-config/webpack.config.js
--env.env=prod"
}
You can again go for optimization techniques available with other webpack
plugins in the production mode. Since v4 webpack does the optimization for
you based on the mode
. But you can override those with your own
configurations. uglify-js
, optimise-css-assets
are most popular.
Thanks for reading.I hope that was informative .If you have any corrections or
suggestion, please let me know in the comments section. Happy Coding !!
Top comments (0)