In previous blog, we have discussed on Cache Busting and plugins, Splitting dev and production.
In this blog, we will learning interesting part of webpack here as:
- Html-loader
- File-loader
- Clean-webpack
- Multiple Entrypoints & Vendor.js
- Extract CSS & Minify HTML/CSS/JS
HTML Loader:
For images, when we use same img file structure for dev and prod. We will get issue as the images are not loading in prod well. To fix that we need HTML loader.
Install Html-loader:
$ npm install —save-dev html-loader
webpack.config.js:
// include in module rules
{
test: /\.html$/,
use: ["html-loader"]
}
When we run npm run prod, we get error as:
unexpected token, you may need an appropriate loader to handle this file type.
Now, Here we need file-loader.
File-loader:
To Install File loader:
$ npm install –save-dev file-loader
webpack.config.js:
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports =
{
entry: "./src/index.js",
plugins: [
new HtmlWebpackPlugin({
template: "./src/main.html"
})
],
module:
{
rules: [
{
// files which ends with .css use the below loader
test: /\.scss$/,
use: [
"style-loader", // 3rd. style loader inject styles into DOM
"css-loader", // 2nd. CSS loader turns css into common JS
"sass-loader" //1st. SASS loader which turns sass into CSS
]},
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath: "images"
}
}}
}}
Now run npm run prod,
It will create images as folder inside dist and all jpg/png/svg.. files will be copied there.
Clean-webpack:
Whenever we do some changes in file, it will create new hash file. We will install clean-webpack plugin which will delete dist directory everytime we build.
$ npm install –save-dev clean-webpack-plugin
Use it in production file, for dev its not needed.
webpack.prod.js:
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = require('./webpack-config');
const merge = require('webpack-merge');
const {CleanWebpackPlugin} = require("clean-webpack-plugin");
module.exports =
merge(common, {
mode : "production",
output:
{
filename: "hello.[contentHash].js",
path.resolve(__dirname, "New_folder_name") } }
},
plugins: [ new CleanWebpackPlugin() ]
})
Multiple Entrypoints & Vendor.js:
If we want to have multiple entry point then we can do it with below following steps:
Create a file in src folder.
Example: vendor.js
Change Output section in both dev and prod.js:
webpack.dev.js:
output: {
filename: "[name].bundle.js"
}
webpack.prod.js:
output: {
filename: "[name].[constentHash].bundle.js"
}
webpack.config.js:
module.exports = {
entry: {
main: "./src/index.js",
vendor: "./src/vendor.js"
}
}
Now check by running npm start and npm run prod. It will create two file name as main.bundle.js and vendor.bundle.js.
Extract CSS & Minify HTML/CSS/JS:
Extract CSS:
It will be great we can have separate js file and css file in production. Currently everything is happening by js only. In production obviously we need CSS to load first. As JS may take some second to load. It can be doable using plugin called mini-css-extract-plugin.
Install mini-css-extract-plugin
$ npm install —save-dev mini-css-extract-plugin
webpack.prod.js:
// Add into the plugins:
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[chunkHash].css"
})
new CleanWebpackPlugin()
],
We have to make sure, that we are using above snippet instead of style loader in webpack.config.js
webpack.dev.js:
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = require('./webpack-config');
const merge = require('webpack-merge');
module.exports =
merge(common ,{
mode : "development",
output:
{
filename: "[name].bundle.js",
path.resolve(__dirname, "New_folder_name") } }
},
module:
{
rules: [
{
// files which ends with .css use the below loader
test: /\.scss$/,
use: [
"style-loader", // 3rd. style loader inject styles into DOM
"css-loader", // 2nd. CSS loader turns css into common JS
"sass-loader" //1st. SASS loader which turns sass into CSS
]}
}
})
webpack.prod.js:
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = require('./webpack-config');
const merge = require('webpack-merge');
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports =
merge(common, {
mode : "production",
output:
{
filename: "[name].[constentHash].bundle.js",
path.resolve(__dirname, "New_folder_name") } }
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[chunkHash].css"
})
new CleanWebpackPlugin()
],
module:
{
rules: [
{
// files which ends with .css use the below loader
test: /\.scss$/,
use: [
"MiniCssExtractPlugin.loader", // 3rd. Move CSS into files
"css-loader", // 2nd. CSS loader turns css into common JS
"sass-loader" //1st. SASS loader which turns sass into CSS
]
}
}
})
webpack.config.js:
const path = require("path")
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports =
{
entry: "./src/index.js",
plugins: [
new HtmlWebpackPlugin({
template: "./src/main.html"
})
],
module:
{
rules: [
{
test: /\.html$/,
use: ["html-loader"]
},
{
test: /\.(svg|png|jpg|gif)$/,
use: {
loader: "file-loader",
options: {
name: "[name].[hash].[ext]",
outputPath: "images"
}
}
}
}
}
Now, by running npm run prod, we will get css file as well in dist folder.
Minify CSS:
To minify the css we used the plugin called optimize-css-assets-webpack-plugin
Install it:
$ npm install —save-dev optimize-css-assets-webpack-plugin
(we just need to minify the CSS in production)
webpack.prod.js:
// (To compile CSS)
const OptimizeCssAssestsPlugin = require('optimize-css-assets-webpack-plugin');
// we add new property here called optimization
optimization: {
minimizer: new OptimizeCssAssestsPlugin()
}
By default the JS will be optimized, but when we run npm run prod here the CSS will get optimised and JS will not be optimised longer. It’s because we are overwriting the optiomization above.
To fix that we have to add optimization for JS as well.
Minify JS:
For JS minifier we are using TerserPlugin, which has installed by default.
To enter this in webpack.prod.js:
const TerserPlugin = require('terser-webpack-plugin');
optimization: {
minimizer: [new OptimizeCssAssestsPlugin(), newTerserPlugin()]
}
Minify HTML:
We are not going to use any new plugin here.
webpack.config.js:
Remove HTMLWebpackPlugin from plugins.
webpack.dev.js:
const HtmlWebpackPlugin = require('html-webpack-plugin');
// add plugins here as:
plugins: [
new HtmlWebpackPlugin ({template: "./src/template.html"})
]
webpack.prod.js:
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const common = require('./webpack-config');
const merge = require('webpack-merge');
const CleanWebpackPlugin = require("clean-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const TerserPlugin = require('terser-webpack-plugin');
module.exports =
merge(common, {
mode : "production",
output:
{
filename: "[name].[constentHash].bundle.js",
path.resolve(__dirname, "New_folder_name") } }
},
optimization: {
minimizer: [new OptimizeCssAssestsPlugin(), newTerserPlugin(),
new HtmlWebpackPlugin ({
template: "./src/template.html",
minify: {
removeAtrributeQuotes: true,
collapseWhiteSpace: true,
removeComments: true
}
})
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].[chunkHash].css"
}),
new CleanWebpackPlugin()
],
module:
{
rules: [
{
// files which ends with .css use the below loader
test: /\.scss$/,
use: [
"MiniCssExtractPlugin.loader", // 3rd. Move CSS into files
"css-loader", // 2nd. CSS loader turns css into common JS
"sass-loader" //1st. SASS loader which turns sass into CSS
]}
}
})
Now, run npm run prod and we can see in dist index.html
, we don’t have any comments and white spaces. The code will get minified.
I hope you found this blog helpful ♥️, If you have any question please reach out to me on @suprabhasupi 😋
👩🏻💻 Suprabha.me |