Prerequisites
- Basic Knowledge of HTML, CSS, and JavaScript
- Node.js and npm installed on your system
Installation
Create a project folder
mkdir my-project && cd my-project
Create a package.json
npm init -y
Install Webpack
npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
Install Bootstrap
npm i --save bootstrap @popperjs/core
Install additional dependencies and Sass
If you want to use the style-loader
, use the following command (optional). See the Build optimization section for more details.
npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader
If you want to use the mini-css-extract-plugin
, use the following command.
npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader
Project structure
Create project folders
mkdir {src,src/js,src/scss}
Create project files
touch src/index.html src/js/main.js src/scss/styles.scss webpack.config.js
Configure webpack
Update webpack.config.js
'use strict'
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/js/main.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
static: path.resolve(__dirname, 'dist'),
port: 8080,
hot: true
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' })
]
}
Update index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap with Webpack</title>
</head>
<body>
<div class="container py-4 px-3 mx-auto">
<div class="alert alert-success text-center shadow" role="alert">
Hello, Bootstrap and Webpack!
</div>
</div>
</body>
</html>
Update package.json
Update scripts property. Add start
and build
scripts.
{
// ...
"scripts": {
"start": "webpack serve",
"build": "webpack build --mode=production",
...
},
// ...
}
Import Bootstrap
This step is optional. It involves configuring the style-loader
plugin to load Bootstrap CSS.
If you want to extract CSS into separate files, you should use the mini-css-extract-plugin
instead of style-loader
. You can omit this step (see Build optimization). The following step adds CSS to the DOM by injecting a <style>
tag, making the CSS part of the index.html file.
Update webpack.config.js (optional)
'use strict'
const path = require('path')
const autoprefixer = require('autoprefixer')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/js/main.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
devServer: {
static: path.resolve(__dirname, 'dist'),
port: 8080,
hot: true
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' })
],
module: {
rules: [
{
test: /\.(scss)$/,
use: [
{
// Adds CSS to the DOM by injecting a `<style>` tag
loader: 'style-loader'
},
{
// Interprets `@import` and `url()` like `import/require()` and will resolve them
loader: 'css-loader'
},
{
// Loader for webpack to process CSS with PostCSS
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
autoprefixer
]
}
}
},
{
// Loads a SASS/SCSS file and compiles it to CSS
loader: 'sass-loader'
}
]
}
]
}
}
Update styles.scss
// Import all of Bootstrap's CSS
@import "bootstrap/scss/bootstrap";
Update main.js
// Import our custom CSS
import '../scss/styles.scss'
// Import all of Bootstrap's JS
import * as bootstrap from 'bootstrap'
Build optimization
This step involves importing Bootstrap into the webpack configuration. If you omitted the step of importing Bootstrap, use the following step.
mini-css-extract-loader instead of style-loader
The style-loader
is a module in webpack that allows you to inject CSS styles into the DOM when they are loaded. When webpack encounters a CSS file, the style-loader
takes the CSS code and injects it into a <head>
section.
The mini-css-extract-plugin
is a plugin for webpack that extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. It’s useful for splitting CSS out of the main bundle, which can help with caching and reducing the initial load time of your application.
Install mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin
Update webpack.config.js
"use strict";
const path = require("path");
const autoprefixer = require("autoprefixer");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const miniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "development",
entry: "./src/js/main.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
devServer: {
static: path.resolve(__dirname, "dist"),
port: 8080,
hot: true,
},
plugins: [
new HtmlWebpackPlugin({ template: "./src/index.html" }),
new miniCssExtractPlugin(),
],
module: {
rules: [
{
test: /\.(scss)$/,
use: [
{
// Adds CSS to the DOM by injecting a `<style>` tag
// loader: "style-loader",
// Extracts CSS for each JS file that includes CSS
loader: miniCssExtractPlugin.loader,
},
{
// Interprets `@import` and `url()` like `import/require()` and will resolve them
loader: "css-loader",
},
{
// Loader for webpack to process CSS with PostCSS
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [autoprefixer],
},
},
},
{
// Loads a SASS/SCSS file and compiles it to CSS
loader: "sass-loader",
},
],
},
],
},
};
Extracting SVG files
Bootstrap’s CSS includes multiple references to SVG files via inline data:
URIs. If you define a Content Security Policy for your project that blocks data:
URIs for images, then these SVG files will not load. You can get around this problem by extracting the inline SVG files using webpack’s asset modules feature.
Add the following object into the rules
property in webpack.config.js
.
{
mimetype: "image/svg+xml",
scheme: "data",
type: "asset/resource",
generator: {
filename: "icons/[hash].svg",
},
}
This object will handle SVG files, outputting them as individual files in the icons directory with a filename based on their content hash.
Example of webpack.config.js
module.exports = {
// Existing webpack configuration...
module: {
rules: [
// Add the object here
{
test: /\.scss$/,
use: [...]
}
]
}
};
Individual SVG files in the icons directory
Configured webpack.config.js
with build optimization
"use strict";
const path = require("path");
const autoprefixer = require("autoprefixer");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const miniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
mode: "development",
entry: "./src/js/main.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
devServer: {
static: path.resolve(__dirname, "dist"),
port: 8080,
hot: true,
},
plugins: [
new HtmlWebpackPlugin({ template: "./src/index.html" }),
new miniCssExtractPlugin(),
],
module: {
rules: [
{
mimetype: "image/svg+xml",
scheme: "data",
type: "asset/resource",
generator: {
filename: "icons/[hash].svg",
},
},
{
test: /\.(scss)$/,
use: [
{
// Adds CSS to the DOM by injecting a `<style>` tag
// loader: "style-loader",
// Extracts CSS for each JS file that includes CSS
loader: miniCssExtractPlugin.loader,
},
{
// Interprets `@import` and `url()` like `import/require()` and will resolve them
loader: "css-loader",
},
{
// Loader for webpack to process CSS with PostCSS
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [autoprefixer],
},
},
},
{
// Loads a SASS/SCSS file and compiles it to CSS
loader: "sass-loader",
},
],
},
],
},
};
Start project
npm start
Open your web browser and enter http://localhost:8080/ into the address bar.
Build project
npm run build
This command will trigger webpack to bundle your JavaScript and SCSS files according to the configuration in your webpack.config.js file
. The bundled files will be outputted to the dist
directory. You can use the Live Server extension to run the index.html
file located in the dist
directory. If you don’t have the Live Server extension installed, install it from the Visual Studio Code marketplace. It’s a convenient tool for quickly serving static files during development.