— Web Development, Webpack — 3 min read
Hello everyone, let’s get started working with webpack. I would recommend that you read the previous post Introduction to Webpack if you haven’t already. It is expected that you have Node js and npm installed, if you don’t please visit Node.js. We’ll be using webpack 4, the latest version available while writing this post.
First we’ll create the required folders to save our files. Open the terminal, and execute the following commands in it :
1mkdir [folder-name] && cd [folder-name]2mkdir src src/assets src/assets/js src/assets/media src/assets/scss config
Execute the following commands in the terminal to create required files :
1touch .babelrc .gitignore README.md config/webpack.common.js config/webpack.dev.js config/webpack.prod.js src/index.html src/assets/js/app.js src/assets/scss/app.scss
Directory Structure
Execute the following commands in the terminal :
1git init2npm init
The second command initiates npm in the project. While doing so it asks few questions regarding the project, then it creates a package.json file in the repository. This file holds the details of the project and the packages required.
Let’s now install webpack and other modules that we’ll need. Execute the following command in the terminal :
1npm install -D webpack-dev-server webpack webpack-merge webpack-cli
It’s obvious why we installed webpack. but why the other two? webpack basically bundles all the modules and emits them into a file. but during development, we cannot afford to repetitively bundle the modules after every small change, webpack-dev-server comes for rescue. This package sets up a development server with hot reloading and other cool features. Also if you noticed we have 3 webpack config files. webpack.common.js contains the configuration common to development and production. webpack.dev.js contains configurations specific to the development stage, and similarly webpack.prod.js for Production specific configurations. We use webpack-merge to merge webpack.common.js with the other two.
Add the following scripts to the scripts section in the package.json :
package.json
1"scripts": {2 "start": "webpack-dev-server --inline --hot --open --config config/webpack.dev.js",3 "build": "webpack --config config/webpack.common.js",4 "build:prod": "webpack -p --config config/webpack.prod.js"5 },
start : starts the webpack dev server.
build : builds the project and outputs the files in developer mode.
build:prod : builds the project and outputs the files in production mode.
--config : it is used to specify the path to the configuration file.
Now let’s started off with writing the configuration files. First, we define a constant object inside the webpack.common.js and export it :
1const config = {2 // Here goes the configuration3 };4 module.exports = config;
Context refers to the base directory. It is an absolute path, it resolves entry points and loaders from the configuration. By default, the current directory is used, but it’s recommended to pass a value in your configuration. This makes your configuration independent from the current working directory.
1const config = {2 context: path.resolve(__dirname, "../src"),3 // Rest of the configuration4 }
We are referencing it by ‘../src’ rather than ‘src/’ because the path is defined with respect to the current directory, which is config.
Let’s define the entry point for the application :
1const config = {2 entry: './src/app.js',3}
Let us assume a case where we need to specify different entry points. In that case we define entry as an object, then specify the entry path with a name to it. For example, here below we are calling it ‘app’ :
1const config = {2 entry: {3 app: './assets/js/app.js'4 },5}
This is the path where the bundled files will be saved. we shall define the output point as an object with 2 attributes, path, and filename :
path : Its the absolute path to the prefered output directory.
filename : it determines the name of each output bundle.
Now, we cannot define path variable with a definite string. As the path would change if the repository is copied to another directory or to another computer. Hence we use Node js Path module which gives us the absolute path to the project root directory.
1const path = require('path');2const config = {3 entry: {4 app: './assets/js/app.js'5 },6 output: {7 path: path.resolve(__dirname, '../dist'),8 filename: 'assets/js/bundle.js'9 }10}
Note that when configuring multiple output paths, i.e when multiple output files are expected; you should use one of the following substitutions to give each bundle a unique name. For example:
1filename: "assets/js/[name].bundle.js"
for other naming options click here.
The dev server package sets up a local development server, hence you won’t be accessing the application using file path. i.e if you want to view your project on the browser you can access it via http://localhost:portNumber/. Also if you look at the npm start script : webpack-dev-server --inline --hot --open --config webpack.dev.js.
--hot :enables hot-reloading which means the code will be re-bundled as soon as webpack notices changes in the files.
--open :opens the application in the browser.
The development configurations will be written in the webpack.dev.js file. first, we import webpack-merge and webpack.common.js, and the Node js path package.
1const path = require('path');2const merge = require('webpack-merge');3const common = require('./webpack.common.js');
First let’s write the configuration, then we’ll try to understand what it means :
1module.exports = merge(common, {2 devtool: 'inline-source-map',3 devServer: {4 contentBase: path.resolve(__dirname, "./dist/assets/media"),5 compress: true,6 port: 8004,7 stats: 'errors-only',8 open: true9 }10});
devtool : It refers to the style of source mapping, its value can affect the build and rebuild speed dramatically. to learn more
devServer.contentBase : It refers to the path from where all media/static files will be served. to learn more
devServer.compress : Enables gzip compression for everything served. to learn more
devServer.port : The port no. you want your application to be deployed to. to learn more
devServer.stats : It lets you precisely control what bundle information gets displayed. to learn more
devServer.open : If set true, the sever opens the browser. to learn more
So this is what we have so far :
1{2 "name": "webpack-config",3 "version": "1.0.0",4 "description": "",5 "main": "webpack.common.js",6 "scripts": {7 "start": "webpack-dev-server --inline --hot --open --config config/webpack.dev.js",8 "build": "webpack --config config/webpack.common.js",9 "build:prod": "webpack --optimize-minimize --config config/webpack.prod.js"10 },11 "author": "",12 "license": "ISC",13 "devDependencies": {14 "webpack": "^4.4.1",15 "webpack-cli": "^2.0.13",16 "webpack-dev-server": "^3.1.1",17 "webpack-merge": "^4.1.2"18 }19}
1const path = require('path')23const config = {4 context: path.resolve(__dirname, "../src"),5 entry: {6 app: './assets/js/app.js'7 },8 output: {9 path: path.resolve(__dirname, '../dist'),10 filename: 'assets/js/[name].bundle.js'11 }12};1314module.exports = config;
1const path = require('path')2const merge = require('webpack-merge');3const common = require('./webpack.common.js');45module.exports = merge(common, {6 devtool: 'inline-source-map',7 devServer: {8 contentBase: path.resolve(__dirname, "./dist/assets/media"),9 compress: true,10 port: 8004,11 stats: 'errors-only',12 open: true13 }14});
The complete repository can be viewed here.
Let’s test our Configuration. Open the terminal and navigate to the project directory and then execute npm run start. Everything should work fine. An instance of the browser will start saying “CANNOT GET /”, that is because we have not defined any HTML file.
Now let’s move on and enable webpack to load HTML, Sass files and ES6 Javascript.