Vanilla Webapp with Webpack
Basic Guide to A Vanilla Javascript App with Webpack
This document will walk through setting up a vanilla javascript, html, and css web app with Webpack.
Contents
- Contents
- Install Node.js
- Configure Node Project
- Installing Webpack
- Project Structure
- Setting up Webpack
- Complete Webpack config
- Package.json and Webpack
- Final Package.json
Install Node.js
Before we get to webpack, we will need to download and install node.js on our machine. Head over to the Node.js website. link
Either download the Latest stable version or the LTS (long term support) version.
If you have a “package manager” installed on your system, you can checkout the supported package managers page here and follow the instructions.
Once done with the installation, confirm that it installed correctly by running node --version
in your terminal, and checking the version output:
node --version
v14.16.1 #<-- Example version output
Configure Node Project
We need to setup out project folder/directory to be managed by Node.
Todo this, simply navagate to your project folder in your terminal, and run npm init
This will run the setup wizard, and ask you some questions. It is fine to just hit Enter untill it is done.
This should create a few files.
There should be a package.json and/or a package.json.lock file in your project root directory.
If you open the package.json file it should look like this:
{
"name": "example-project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Installing Webpack
Once you have verified your Node.js install and configured Node to manage your project folder, we can proceed to install & setup Webpack
In the terminal install the following: webpack, webpack-cli, webpack-dev-server, webpack-merge
npm install --save-dev webpack webpack-cli webpack-dev-server webpack-merge
Note that using --save-dev
saves all the packages as dependencies to your package.json file under the devDependencies
parameter.
it may look somthing similar to this:
{
"name": "My Project",
"version": "1.0.0",
"description": "",
"scripts": {
... Omitted
},
"repository": {
"type": "git",
"url": "..."
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.33.2",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
}
}
Note I have ommitted some config details, we will get to that shortly.
These packages do a few things.
Webpack
is the main package and Webpack-cli
is for using webpack in the terminal/command line.
Webpack-dev-server
helps create and manage, a local deveopment server on port 8080 for viewing our project during development.
Webpack-merge
allows for us to have multiple webpack configuration files, or multiple objects with parameters, for easy to read configuration. Merge, then parses and combines these into one file/object.
Project Structure
We should create our project file structure, with our files and folders next.
- Create
src/
anddist/
folders in the main project directory. - Create
index.html
file in the main directory. - Create
scripts/
andstyles/
in thesrc/
directory. - Create
index.js
file inscripts/
&style.css
instyles/
.
The Structure/Layout of our project should look like this:
dist/ # Create folder
src/ # Create folder
scripts/ # Create subfolder in src/
index.js # Create file in subfolder scripts/
styles/ # Create subfolder in src/
style.css # Create file in subfolder styles/
index.html # Create this file
package.json // Generated by npm init
package-lock.json // Generated by npm init
Setting up Webpack
Now that our files and folders are structured how we like, we can proceed to setting up Webpack for our project.
In the root directory of the project, create a file called webpack.config.js
. You can name it what you want as long as it starts with webpack
and ends in .js
format.
Webpack by default assumes/detects the file name webpack.config.js
.
Note: If you name it somthing else your will need to define the config file name in the
package.json
file with the--config
flag and the file name.
Html loader
Before we edit this file, we need to download a plugin to handle the loading of html
files. We can do this with html-webpack-plugin
.
npm i --save-dev html-webpack-plugin
Once that is installed, the webpack config file and add the following:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
module: {
// Soon
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
CSS/SASS loader
To handle loading CSS/SCSS and SASS into the Webpack bundle we need to download style-loader
, css-loader
and sass-loader
.
npm i --save-dev style-loader css-loader sass-loader
Once these are installed, open the webpack config file again and add in the module
section the following:
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader","sass-loader"]
},
},
Important: Make sure that the
use
line matches the loaders in the above order. Webpack loads from right, to left. It needs to load the file loaders (sass-loader and css-loader) first before it can deal with the styles inside these files.
Image Loader
Now that we have the html and css/sass/scss file loaders, we need to make sure Images
are loaded and bundled as well.
Webpack has a built in Image loader, we just need to specify to look for the files in the config.
Add the following lines in the rules
section we added previous:
}, //Previous rule
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
}
loading ES Modules
ECMAScript loading
Because some newer JS functionality isn’t always supported accross current or older browsers, we need to make sure these new features and compiled/modified to there repective older supported versions.
This tasks can be handled with Babel
.
Install the following:
npm i @babel/core babel-loader @babel/preset-env --save-dev
And add the following into webpack config:
{
"presets": [
"@babel/preset-env"
]
}
We can also specify the webpack entry point and build output with the following code in the modules section:
entry: './src/index.js',
output: {
filename: 'bundle.js', path: path.resolve(__dirname, 'dist'),
}
Complete Webpack config
The complete webpack config file should look like the following:
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js', path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader","sass-loader"]
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ["babel-loader"]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
]
};
Package.json and Webpack
It worth noting before moving on that we should have a nice list of dependancies
in our package.json file now, from installing all thoes extra packages.
"devDependencies": {
"@babel/core": "^7.14.0",
"@babel/preset-env": "^7.14.1",
"babel-loader": "^8.2.2",
"css-loader": "^5.2.4",
"html-webpack-plugin": "^5.3.1",
"sass": "^1.32.12",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"webpack": "^5.36.2",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
}
As indicated before, I ommited some parts of the package.json file. This was spicifically the scripts
section of the file.
In this section is how we tell node
to handle our build/test and other scripts used by packages like Webpack.
It is in this sections that we can define a script to trigger webpack to build/run specific tasks.
Lets configure Webpack to run a live
build of our project by the webpack-dev-server
.
This will allow us to constantly update code, and have Webpack automatically render this to our browser.
Open up package.json
, and go to the scripts
lines. We are going to create a new script called start
which triggers the dev-server to build and deploy to a new tab in our default Web browser.
Edit the scripts section to look like the following:
"scripts": {
"start": "webpack serve --mode development --open --config webpack.config.js"
}
Now you can trigger this scripts by running the npm start
command in the terminal.
To run a build as we develop our project we can add:
"dev": "webpack --mode development --config webpack.config.js",
We can trigger this by running npm run dev
in the terminal.
We can also define a build
script before bundling for production
:
"build": "webpack --mode production --config webpack.config.js"
we can run this with a similar command to the dev script. npm run build
Final Package.json
Just for reference the final package.json
file should look similar to this:
I removed some config code marked /* … */ for brevity. This code is generated when you run npm init.
{
"name": /* ... */,
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"dev": "webpack --mode development --config webpack.config.js",
"start": "webpack serve --mode development --open --config webpack.config.js",
"build": "webpack --mode production --config webpack.config.js"
},
"repository": {
"type": "git",
"url": /* ... */
},
"keywords": [
/* ... */
],
"author": /* ... */,
"license": "ISC",
"bugs": {
/* ... */
},
"homepage": /* ... */,
"devDependencies": {
"@babel/core": "^7.14.0",
"@babel/preset-env": "^7.14.1",
"babel-loader": "^8.2.2",
"css-loader": "^5.2.4",
"html-webpack-plugin": "^5.3.1",
"sass": "^1.32.12",
"sass-loader": "^11.0.1",
"style-loader": "^2.0.0",
"webpack": "^5.36.2",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.7.3"
}
}