Webpack bundle all different files in a single structure inside a dist folder with js, css, and html files
npm install --save-dev webpack webpack-cli
Folder structure
root
|__ dist
|__ src
| |__ index.js
|__ index.html
By default without a webpack config file webpack will :
- Create dist folder at /dist index.js bundled /dist/index.js
- default entry point is at /src/index.js
- mode option is not provided then webpack will fallback to production mode.
- as webpack fallback to production mode the dist/index.js is minified.
- Inside /index.html a script tag should point to src="/dist/index.js"
module.exports ={
entry: "./src/index.js"
}
Default path but another path can be confirgured
const path = require("path");
module.exports ={
output: {
filename: "index.js",
path: path.resolve(__dirname, dist )
}
}
path.resolve will retrieve the absolute path with the folder name where output filname should be stored.
module.exports ={
mode: "development
}
mode:"development" will bundle /src/index.js in /dist/index.js unminified
module.exports = {
devtool: false
}
devtool: false, will remove the eval function and show the code from /src/index.js unchanged. this option helps to see our code in the /dist/index.js
css-loader and style-loader :
npm install --save-dev css-loader style-loader
module.exports = {
module: {
rules : [
test: /\.css$/,
use: [ "style-loader", // 2. inject style into dom ( header in index.html )
"css-loader" // 1. turn css into commonjs
]
]
}
}
css-loader will check for all the css file imported in js and load/transform them into javascript inside /dist/index.js at this stage our app is not showing any styling. We need style-loader to create a style tag with all css and automatically in /index.html header tag.
html-loader :
npm install --save-dev html-loader
module.exports = {
{
test: /\.html$/,
use: ["html-loader"],
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]
}
}
}
html-loader will check in the /src/index.html every img tag src and will require it in js But we need to add file-loader so webpack can load the file
file-loader: allow to import all the assets like images (svg, png, jpg, ...) by checking the src attr of img tag
{
test: /\.(svg|png|jpg)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath: "img",
},
},
},
npm install --save-dev html-webpack-plugin
HtmlWebpackplugin will automatically update the srcipt with the new hash in the filename. Also if not specified, it will create the /dist/index.html from /index.html
const HtmlWebpackplugin = require("html-webpack-plugin");
module.exports = {
plugins: [
new HtmlWebpackplugin({
template: "./src/template.html",
}),
],
}
we can tell the plugin to create the /dist/index.html from a template so if we set up for example the favicon.ico in a template.html we will have it in /dist/index.html
remove the /index.html and create a html template in /src/template.html
npm install --save-dev clean-webpack-plugin
clean-webpack-plugin: this plugin will automatically remove the dist folder so a clean dist folder will be created. During the production build all file with a hash will be generated so the new dist folder won't have any previous hash file unused.
mini-css-extract-plugin:
npm install --save-dev mini-css-extract-plugin
module.exports = {
plugins: [
new CleanwebpackPlugin(),
new MiniCssExtractPlugin({ filename: "[name].[contentHash].css" }),
],
module: {
rules: {
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
},
}
npm install --save-dev optimize-css-assets-webpack-plugin
This plugin will extract the css from index.js and instead of creating a style tag in the index.html it will create its own css file. This is a best to do in production because we won't have a first dom displayed without styling.
Cache busting is useful because it allows the visitors to receive the most recently updated files without having to perform a hard refresh or clear their browser cach
on macOs : cmd + shift + R : hard refresh cmd + R : refresh With a hard refresh it will force the browser to download all the files even if it's already have them all cached. A normal refresh will download only the file that have changed ( only if the filename has changed is considered a change )
module.exports = {
output: {
filename: "main.[contenthash].js",
path: path.resolve(__dirname, "dist"),
},
}
Anytime a change has been saved in any of the bundled file js, css the contenthash will change then it will force the browser to download the new version of the file with the new hash. contenthash is a hash generated base on its content.