Run npm init -y in an empty project directory to generate a base package.json manfiest.
Install Webpack core and CLI as local development dependencies:
pnpm add -D webpack webpack-cli
Create a webpack.config.js file in the project root. This configuration file runs in a Node.js environment, so it uses CommonJS module syntax for exports:
const path = require('path')
module.exports = {
entry: '',
output: {}
}
Create a src folder to hold source code, then add two test files to validate module bundling:
src/utils/validation.js
const initCheckText = "webpack pipeline operational"
export default initCheckText
src/index.js (entry file)
import checkText from './utils/validation.js'
console.log(checkText)
Update the entry and output fields in webpack.config.js to point to the entry file and define the bundled output location:
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
Add a build script to package.json to invoke the locally installed Webpack binary instead of a global installation:
{
"name": "custom-video-player",
"version": "1.0.0",
"scripts": {
"build": "webpack --config webpack.config.js"
},
"devDependencies": {
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1"
}
}
Running pnpm build will generate a bundled file at dist/bundle.js. By default, Webpack uses production mode which minifies output, making it hard to debug. Add a mode field to the configuration to use unminified development output:
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'development'
}
To test the bundled code in a browser, create a dist/index.html file and reference the bundled script:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom Video Player</title>
</head>
<body>
<script src="./bundle.js"></script>
</body>
</html>
Add CSS support by first creating a stylesheet at src/styles/global.css:
body {
background: #e0f7fa;
margin: 0;
padding: 2rem;
}
Import the stylesheet in src/index.js:
import checkText from './utils/validation.js'
import './styles/global.css'
console.log(checkText)
Running pnpm build at this stage will throw an error, as Webpack requires loaders to process non-JavaScript assets. Install the required CSS processing loaders:
pnpm add -D style-loader css-loader
Add a module rule to webpack.config.js to handle CSS files. Loaders run from right to left, so css-loader (which parses CSS files) is listed after style-loader (which injects parsed styles into the browser DOM):
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
To avoid manually creating and updating the dist/index.html file, use the html-webpack-plugin to auto-generate the HTML file with injected bundled assets. Install the plugin first:
pnpm add -D html-webpack-plugin
Create a template HTML file at src/template.html for the plugin to use as a base:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Custom Video Player</title>
</head>
<body>
<div id="player-root"></div>
</body>
</html>
Update the Webpack configuration to register the plugin:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html'
})
]
}
Add the clean-webpack-plugin to automatically clear the dist directory before each build, removing old unused assets:
pnpm add -D clean-webpack-plugin
Register the plugin in the Webpack configuration:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/template.html'
})
]
}
Enable hot reload for local development by installing webpack-dev-server:
pnpm add -D webpack-dev-server
Add a devServer configuration block to webpack.config.js, and add a new script to package.json to start the development server:
Webpack config update:
// ...existing config
module.exports = {
// ...existing fields
devServer: {
static: './dist',
open: true,
hot: true
}
}
Updated package.json scripts:
{
"name": "custom-video-player",
"version": "1.0.0",
"scripts": {
"build": "webpack --config webpack.config.js",
"dev": "webpack-dev-server"
},
"devDependencies": {
"clean-webpack-plugin": "^4.0.0",
"css-loader": "^6.8.1",
"html-webpack-plugin": "^5.5.1",
"style-loader": "^3.3.3",
"webpack": "^5.84.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0"
}
}