Webpack allows you to organize your code into small, reusable modules that can be imported and used in other parts of your application. This makes it easier to maintain and update your code, and also helps reduce the size of your final bundle.
To create a production-ready multi-page web application using Webpack and VanillaJS, you need to follow the below steps on your system:-
First, make sure you have installed NodeJS in your system, If not follow the below setup to install NodeJS on a Linux system. If you are working on a Linux system you can install Node by installing a PPA(Personal Package Archive) of NodeJS.
curl -s https://deb.nodesource.com/setup_16.x | sudo bash
Now PPA sources have been added we can install NodeJS using the below command.
sudo apt install nodejs -y
Now in your empty project folder initialized your node application using the following command.
npm init
# Directory Structure:-
The next step is to maintain a directory structure as below. Where the templates folder will contain HTML files, the scripts directory will contain javascript-related code.
If you will see the above directory structure all HTML, CSS, and JavaScript files have a similar name such as (home.html, home.css, and home.js). We will be using different bundle files for each HTML file. This pattern will help us to map CSS and Javascript files with the corresponding HTML file. You can use a single bundle file for all HTML files but such type of pattern is less scalable in long term.
# Dependency Installation:-
Now it’s time to install webpack and its dependencies. Run the following command to install webpack and other required modules.
{
"copy-webpack-plugin": "^11.0.0", // used to copy static files form working directory to build package.
"css-loader": "^6.7.3", // used to load css file in webpack.
"dotenv-webpack": "^8.0.1", // used to access environment variable in webpack vanilla js (proccess.env.VARIABLE)
"html-webpack-plugin": "^5.5.0", // used to build html template
"mini-css-extract-plugin": "^2.7.2", // used to minified css files.
"style-loader": "^3.3.1", // used to load all type of style related files.
"webpack": "^5.75.0",
"webpack-cli": "^5.0.1", // webpack cli to work with webpack using command line
"webpack-dev-server": "^4.11.1" // webpack dev server to run webpack on local machine
}
# Dev and Build Scripts:-
The next step is to create a dev and build command in your NodeJS package.json file and replace the scripts section with the below line in package.json.
"scripts": {
"dev": "webpack-dev-server --mode development", // this mode value will be used in the webpack.config file.
"build": "webpack --mode production"
}
Now it's time to configure the webpack config file. A Webpack config is a JavaScript object that configures one of Webpack's options.
First, import the all required plugins that we have installed above in your webpack config file.
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const webpack = require('webpack');
// path is node js inbuild package which is used to work with directory in your app.
const path = require('path');
# Configure Plugins:-
Add a webpack plugin in your webpack config file to generate HTML templates, minified CSS files, and use environment variables using webpack dotenv.
const adminPages = ["dashboard"]
const homePages = ["home", "login"]
const webpackPlugins = [];
webpackPlugins.push(...adminPages.map(
(page) =>
new HtmlWebpackPlugin({
// telling webpack that inject the js bundle in the body of html file
inject: 'body',
// telling webpack where html file are located
template: `./src/templates/admin/${page}.html`,
// telling webpack that how and where to put html file in dist directory
filename: `admin/${page}.html`, // admin pages will accessible using admin/{page}.html
chunks: [page]
})
)
)
webpackPlugins.push(...homePages.map(
(page) =>
new HtmlWebpackPlugin({
// telling webpack that inject the js bundle in the body of html file
inject: 'body',
// telling webpack where html file are located
template: `./src/templates/${page}.html`,
// telling webpack that how and where to put html file in dist directory
filename: `${page}.html`, // pages will accessible using {page}.html
chunks: [page]
})
)
)
webpackPlugins.concat([
new Dotenv({
path: `./.env.${argv.mode}`
}),
// telling the wepack how to minified the styles files.
new MiniCssExtractPlugin({
filename: "src/styles/[name].bundle.css",
ignoreOrder: false,
chunkFilename: '[name]'
}),
// telling the webpack to copy our assets from src directory to build directory (dist)
// if there is not assets in the below directory it will throw error.
new CopyWebpackPlugin({
patterns: [
{
from: 'src/assets/images/', to : 'assets/images/'
},
{
from: 'src/assets/docs/', to : 'assets/docs/'
}
]
})
])
# Entry And Output:-
Webpack starts its job from a single or multiple JavaScript file, which is called the entry point. Now we will define the entry and output file path for our web app.
const entryPages = [].concat(adminPages, homePages);
module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: entryPages.reduce((config, page) => {
config[page] = `./src/scripts/${page}.js`;
return config;
}, {}),
output: {
filename: 'src/[name].bundle.js',
path: buildPath,
publicPath: '/', // path on which webpack will serve the application.
// allows one to use asset files (fonts, icons, etc) without configuring additional loaders.
assetModuleFilename: 'assets/images/[name][ext][query]'
},
// plugin are used to add additional configuration on top of webpack.
// webpack itself build on the same plugin system.
plugins: webpackPlugins
};
};
# Loaders:-
Next, configure the loader rules and loader in the webpack config file which helps us to use the CSS file in the webpack and tell the webpack where to look for the javascript file. In this option, we will say Webpack how exactly it should transform different types of files. Add the below code after the output section.
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource'
},
// loader are used to load specific type of file which is not by default used by webpack.
{
test: /\.(sa|sc|c)ss$/,
use: [
isProduction ? MiniCssExtractPlugin.loader : 'style-loader',
'css-loader'
]
}
]
}
# Development Server:-
Set up the Webpack dev server to serve your app and specify the port and source file location. Add the below code after the module section.
devServer: {
client: {
overlay: true // Shows a full-screen overlay in the browser when there are compiler errors or warnings.
},
watchFiles: ['src/*'],
port: 3000
}
Note:- To Use CSS in your application you must need to import CSS files in your javascript file as below.
import '../styles/global.css'
import '../styles/login.css'
That's it! A simple Webpack configuration for a production-ready website. We covered the concepts of multiple entry and output points, loaders, and plugins, and how Webpack transforms and bundles your files.
# Conclusion:-
Webpack is a powerful and versatile tool for building modern web applications. It can handle tasks ranging from bundling and transpiring code to optimizing and managing assets. With its wide range of plugins and configurable options, webpack can be tailored to meet the needs of any project. Whether you're starting a new project from scratch or optimizing an existing one, taking the time to learn and integrate webpack into your workflow can greatly improve the efficiency and speed of your development process.