Webpack is a module bundler. Its main purpose is to bundle JavaScript, SCSS, CSS, Image, and other file types together for transforming, bundling, or packaging.
We are going to see:
- Create a Project
- Install Webpack
- Install Webpack-cli
- Create index.js
- Webpack Configuration
- WebPack + HTML
- Install
npm i webpack-dev-server --save-dev
- webpack's loaders
- Working with CSS
- Working with SASS
- Working with modern JavaScript
- JS Import & Export
- development mode vs production mode
- Optimization
- BrowserSync
Create a Project Create a Project
First create a directory webpack-tutorial and execute npm init -y
to create a package.json file.
E.g.
c:\xampp\htdocs\tutorials
? mkdir webpack-tutorial
c:\xampp\htdocs\tutorials
? cd webpack-tutorial\
c:\xampp\htdocs\tutorials\webpack-tutorial
? npm init -y
Wrote to c:\xampp\htdocs\tutorials\webpack-tutorial\package.json:
{
"name": "webpack-tutorial",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
See creating a sample project for webpack.
Install Webpack Install Webpack
To use the webpack, we need NPM and Node.js pre-installed. If you don’t have them then see Installing NPM and Node.js
c:\xampp\htdocs\tutorials\webpack-tutorial (webpack-tutorial@1.0.0)
? npm i webpack --save-dev
...
+ webpack@4.44.1
added 572 packages from 358 contributors and audited 575 packages in 176.855s
21 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
See installing webpack with npm command.
Install Webpack-cli Install Webpack-cli
Install webpack-cli with command:
npm install webpack-cli --save-dev
E.g.
c:\xampp\htdocs\tutorials\webpack-tutorial (webpack-tutorial@1.0.0)
? npm i webpack-cli --save-dev
...
+ webpack-cli@3.3.12
added 572 packages from 358 contributors and audited 575 packages in 176.855s
21 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
See installing webpack-cli with npm command.
Create index.js Create index.js
- Create a
src
directory, and create a fileindex.js
within it. - Add below code into our
src/index.js
file:
console.log("Hello webpack!")
- Open package.json and replace:
"test": "echo \"Error: no test specified\" && exit 1",
with:"dev": "webpack --mode development"
- Then execute npm run dev
E.g.
? npm run dev
> webpack-tutorial@1.0.0 dev c:\xampp\htdocs\tutorials\webpack-tutorial
> webpack --mode development
Hash: c51c08e1dfa5845fe276
Version: webpack 4.44.1
Time: 110ms
Built at: 09/01/2020 11:01:36 AM
Asset Size Chunks Chunk Names
main.js 3.81 KiB main [emitted] main
Entrypoint main = main.js
[./src/index.js] 34 bytes {main} [built]
You can see the new file main.js generated into the dist directory.
Here, We can see the un-minified JS bundle file.
Webpack Configuration Webpack Configuration
Create file webpack.config.js and add below code within it.
const path = require('path'); module.exports = { … },
WebPack + HTML WebPack + HTML
Setup the plugin html-webpack-plugin
with npm i html-webpack-plugin --save-dev
.
c:\xampp\htdocs\tutorials\webpack-tutorial (webpack-tutorial@1.0.0)
? npm i html-webpack-plugin --save-dev
npm WARN webpack-tutorial@1.0.0 No description
npm WARN webpack-tutorial@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ html-webpack-plugin@4.4.1
added 44 packages from 77 contributors and audited 619 packages in 23.857s
22 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Create file src/index.html
and add below code within it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webpack tutorial</title>
</head>
<body>
</body>
</html>
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
Install npm i webpack-dev-server --save-dev
Install npm i webpack-dev-server --save-dev
c:\xampp\htdocs\tutorials\webpack-tutorial\src
? npm i webpack-dev-server --save-dev
npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated fsevents@1.2.13: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules\webpack-dev-server\node_modules\chokidar\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN webpack-tutorial@1.0.0 No description
npm WARN webpack-tutorial@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ webpack-dev-server@3.11.0
updated 1 package and audited 619 packages in 15.884s
17 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Open the package.json
.
You can see the webpack-dev-server
with latest version in devDependencies
as below:
"devDependencies": {
..
"webpack-dev-server": "^3.11.0"
..
}
Now add "start": "webpack-dev-server --mode development --open",
into the scripts
.
See:
"scripts": {
"dev": "webpack --mode development",
"start": "webpack-dev-server --mode development --open"
},
Type command npm start
you can see in console – https://i.imgur.com/1u6f8tV.png
The chrome open the tab with URL: http://localhost:8080/
.
If not then you can open the chrome and tyep the http://localhost:8080/.
you can see something https://i.imgur.com/B0DUZXp.png
webpack’s loaders webpack’s loaders
Loaders are third-party extensions that help webpack deal with various file extensions. For example there are loaders for CSS, for images, or for txt files.
module.exports = {
module: {
rules: [
{
test: /\.filename$/,
use: ["loader-b", "loader-a"]
}
]
},
//
};
Working with CSS Working with CSS
Install npm i css-loader style-loader --save-dev
c:\xampp\htdocs\tutorials\webpack-tutorial\src
? npm i css-loader style-loader --save-dev
npm WARN webpack-tutorial@1.0.0 No description
npm WARN webpack-tutorial@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ style-loader@1.2.1
+ css-loader@4.2.2
added 23 packages from 57 contributors and audited 642 packages in 12.919s
27 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Open the package.json
.
You can see the css-loader
and style-loader
with their latest version in devDependencies
as below:
"devDependencies": {
..
"css-loader": "^4.2.2",
"style-loader": "^1.2.1",
..
}
Create src/style.css
and add below code:
body {
background: #161928;
padding: 100px 0;
}
h1 {
color: #ffffff;
text-align: center;
font-size: 50px;
}
Add the <h1>Webpack is Awesome!</h1>
into the HTML file as below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Webpack</title>
</head>
<body>
<h1>Webpack is Awesome!</h1>
</body>
</html>
Add import "./style.css";
in our src/index.js
file as below:
import "./style.css";
console.log("Hello webpack!");
Add our CSS Loader in Webpack module as below:
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
See complete webpack.config.js
file code as below:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
Now type the npm start
.
You can see something like https://i.imgur.com/obrkot6.png
NOTE: If you already started the server with npm start
then you can close it by pressing keys CTRL + C
.
Working with SASS Working with SASS
Install npm i css-loader style-loader sass-loader sass --save-dev
as:
c:\xampp\htdocs\tutorials\webpack-tutorial\src
? npm i css-loader style-loader sass-loader sass --save-dev
npm WARN webpack-tutorial@1.0.0 No description
npm WARN webpack-tutorial@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ css-loader@4.2.2
+ sass@1.26.10
+ style-loader@1.2.1
+ sass-loader@10.0.1
added 7 packages from 9 contributors, updated 2 packages and audited 649 packages in 11.456s
25 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Create src/style.scss
file and add below code within it.
$body-bg-color: #158bad;
$h1-color: #fff;
body {
background: $body-bg-color;
padding: 100px 0;
}
h1 {
color: $h1-color;
text-align: center;
font-size: 50px;
}
Open the file /src/index.js
Remove :
import "./style.css";
console.log("Hello webpack!");
And add
import "./style.scss";
console.log("Hello webpack!");
Open the webpack.config.js
file and add remove our old code.
module: {
rules: [{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}]
},
And add new code
module: {
rules: [
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}
]
},
Complete code webpack.config.js
file as below:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
module: {
rules: [{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
}]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
Type npm start
to see the changes.
You can see somehting like https://i.imgur.com/rLlw7g8.png
NOTE: If you already started the server with npm start
then you can close it by pressing keys CTRL + C
.
Working with modern JavaScript Working with modern JavaScript
webpack doesn’t know on its own how to transform JavaScript code. This task is outsourced to a third-party loader, specifically babel-loader, with babel.
Install npm i @babel/core babel-loader @babel/preset-env --save-dev
c:\xampp\htdocs\tutorials\webpack-tutorial\src
? npm i @babel/core babel-loader @babel/preset-env --save-dev
npm WARN webpack-tutorial@1.0.0 No description
npm WARN webpack-tutorial@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ @babel/core@7.11.5
+ babel-loader@8.1.0
+ @babel/preset-env@7.11.5
added 135 packages from 68 contributors and audited 784 packages in 44.232s
32 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Babel need some configuration file babel.config.json
. So create it and add blow code within it.
{
"presets": [
"@babel/preset-env"
]
}
Add webpack module as below:
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
}
Compelte code
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
module: {
rules: [{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
Open the src/index.js
file add add below code:
import "./style.scss";
console.log("Hello World!");
const sum = () => {
console.log( 'Called!' );
};
sum();
Type npm start
to see the changes.
You can see somehting like https://i.imgur.com/UGihwMu.png
NOTE: If you already started the server with npm start
then you can close it by pressing keys CTRL + C
.
JS Import & Export JS Import & Export
We have a below code:
import "./style.scss";
console.log("Hello World!");
const sum = () => {
console.log( 'Called!' );
};
sum();
Create new file scr/sum.js
and add below code within it.
const sum = () => {
console.log( 'Called!' );
};
export default sum;
Open the src/index.js
and add below code:
// Import function sum from sum.js.
import sum from "./sum";
import "./style.scss";
console.log("Hello World!");
// Call sum.
sum();
There is no deference in old ocde. We have just create a sepereate JS file and export the sum() funciton.
And import it into the index.js file.
Type npm start
to see the changes.
You can see somehting like https://i.imgur.com/UGihwMu.png
NOTE: If you already started the server with npm start
then you can close it by pressing keys CTRL + C
.
development mode vs production mode development mode vs production mode
As introduced earlier, webpack has two modes of operation: development and production. So far we worked only in development mode.
In development mode, webpack takes all the JavaScript code we write, almost pristine, and loads it in the browser.
No minification is applied. This makes reloading the application in development faster.
In production mode instead, webpack applies a number of optimizations:
- minification with
TerserWebpackPlugin
to reduce the bundle size - scope hoisting with
ModuleConcatenationPlugin
Add build
command "build": "webpack --mode production"
"scripts": {
"dev": "webpack --mode development",
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
},
Run npm run build
c:\xampp\htdocs\tutorials\webpack-tutorial (webpack-tutorial@1.0.0)
? npm run build
> webpack-tutorial@1.0.0 build c:\xampp\htdocs\tutorials\webpack-tutorial
> webpack --mode production
Hash: 9a02e1c3917fac845f1b
Version: webpack 4.44.1
Time: 2753ms
Built at: 09/01/2020 12:18:57 PM
Asset Size Chunks Chunk Names
index.html 167 bytes [emitted]
main.js 4.76 KiB 0 [emitted] main
Entrypoint main = main.js
[1] ./src/style.scss 560 bytes {0} [built]
[3] ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/style.scss 366 bytes {0} [built]
[4] ./src/index.js + 1 modules 207 bytes {0} [built]
| ./src/index.js 133 bytes [built]
| ./src/sum.js 69 bytes [built]
+ 2 hidden modules
Child HtmlWebpackCompiler:
1 asset
Entrypoint HtmlWebpackPlugin_0 = __child-HtmlWebpackPlugin_0
[0] ./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html 435 bytes {0} [built]
We can see the HTML and JS files are created in dist directory
/dist/index.html
/dist/main.js
Open the /dist/index.html
file. You can see something as https://i.imgur.com/FUbsQ8f.png
Also If we see the /dist/main.js the file is genereated as minified file as https://i.imgur.com/uy0XHCb.png
Optimization Optimization
splitChunks splitChunks
Consider a JavaScript application using Moment.js, the popular JS library for times and dates. There are better alternatives to it, but for a moment (no pun intended) let’s prove my point.
Install the library in your project folder:
npm i moment
Now wipe out the content of src/index.js
and import the library there:
import moment from "moment";
Run a build with npm run build and look at the output:
main.js 350 KiB 0 [emitted] [big] main
The whole library is bundled in the main entry point of our app. Not good. With optimization.splitChunks we can move out moment.js from the main bundle.
To configure code splitting open up webpack.config.js and add the optimization key to your configuration, configured as follows:
module.exports = {
...
optimization: {
splitChunks: { chunks: "all" }
},
...
};
`
Run a build with npm run build
and look at the output:
main.js 5.05 KiB 0 [emitted] main
vendors~main.js 346 KiB 1 [emitted] [big] vendors~main
BrowserSync BrowserSync
npm install --save-dev browser-sync-webpack-plugin
npm i -D browser-sync browser-sync-webpack-plugin webpack-dev-server
ADMIN@ADMIN-PC MINGW64 /c/xampp/htdocs/dev/wp-content/plugins/astra-pro-sites/admin/uag-templates (next-release)
$ npm install --save-dev browser-sync-webpack-plugin
npm WARN browser-sync-webpack-plugin@2.2.2 requires a peer of browser-sync@^2 but none is installed. You must install peer dependencies yourself.
npm WARN uag-templates@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\webpack-dev-server\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
+ browser-sync-webpack-plugin@2.2.2
added 1 package from 1 contributor and audited 785 packages in 12.296s
32 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
JSX JSX
Install:
npm install --save-dev @babel/preset-react
Updated babel.config.json
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
webpack.config.js
// const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
module: {
rules: [{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"]
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx']
}/*,
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]*/
};