Bundle your javascripts in morden way. - Nerd Platoon Bundle your javascripts in morden way. - Nerd Platoon

In today’s world, javascript is taken as a requirement rather than just a skill in web development. As stated by Wikipedia, 98% of websites use JavaScript on the client side for webpage behaviour, often incorporating third-party libraries in 2022. With introduction of various modular code principles, developers create each file for each module, which are referenced on html file. In traditional way, referencing javascript files on HTML would be something like this:

<!DOCTYPE html>

<html lang=”en”>

<head>

   <title>Document</title>

</head>

<body>

.

.

<script src=”js1.js”></script>

<script src=”js2.js”></script>

<script src=”js3.js”></script>

</body>

</html>

In the above HTML file, when any new javascript file is added, it is referenced at the bottom of the body tag.

Bundle javascript files

To avoid redundant behavior of referencing javascript files, now we will bundle/pack all javascript files into a single one and reference only bundled files in HTML. This is where WEBPACK is used. Webpack is a module bundler with the main purpose of bundling javascript files. It also bundles images and sass files but in this article, we will bundle javascript files only.

To get started, we will create a project folder and inside it we will create two new folders as public and src respectively. Public folder will store our html file and src will store our all javascript files.

  • Create project folder
    • mkdir webpackLearn
  • Create public and src folder
    • cd webpackLearn
    • mkdir public && mkdir src

At this point your folder structure will be something like this:

  • webpackLearn
    • public
    • src

Lets add index.html file inside public folder and index.js inside src folder.

  • Inside your project root path (webpackLearn in this case) enter command
    • cd public && touch index.html
    • cd ..
    • cd src && touch index.js

Folder structure:

  • webpackLearn
    • public
      • index.html
    • src
      • index.js

Paste the following content to public/index.html file:

<!DOCTYPE html>

<html lang=”en”>

<head>

   <meta charset=”UTF-8″>

   <meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

   <meta name=”viewport” content=”width=device-width, initial-scale=1.0″>

   <title>Document</title>

</head>

<body>

   <h1 style=”text-align: center;”>Webpack Learn</h1>

</body>

</html>

Now we are all set to implement webpack. On your project root path, open the terminal and type npm init -y”

The command “npm init” will create a base for node js project generating package.json file. The “-y” flag after “npm init” will skip the node project description and create default description in package.json file

The package.json file will have following content:

{

 “name”: “webpackLearn”,

 “version”: “1.0.0”,

 “description”: “”,

 “main”: “index.js”,

 “scripts”: {

   “test”: “echo \”Error: no test specified\” && exit 1″

 },

 “keywords”: [],

 “author”: “”,

 “license”: “ISC”

}

Now lets create javascript files inside the src folder. We will create js1.js & js2.js as our modular javascript file. On your project root path, open terminal and enter following command:

  • cd src
  • touch js1.js js2.js

Folder structure:

  •  webpackLearn
    • public
      • index.html
    • src
      • index.js
      • js1.js
      • js2.js
    • package.json

In src/js1.js, paste the following code.

export default function testFunction1() {

   console.log(“Test function1 called”)

}

 

export const testFunction2 = () => {

   console.log(“Test function2 called”)

}

In src/js2.js, paste the following code

const values = [

   {

       name: “John Doe”,

       address: “New york”

   },

   {

       name: “William Roberts”,

       address: “Toronto”

   },

   {

       name: “Ram Sharma”,

       address: “Bhaktapur”

   },

   {

       name: “Jean Doe”,

       address: “Seattle”

   },

]

 

export default values

In src/index.js, paste the following code

import function1, {testFunction2} from ‘./js1’

import values from ‘./js2’

 

function1()

testFunction2()

console.table(values)

Right now if we reference src/index.js file in public/index.html, it will throw error as we are importing and exporting functions and variables with es6 syntax import module from ‘filename’ without mentioning type: ‘module’ in package.json file. But this will be taken care of by webpack.

Now we will install webpack in our project. On your project root path, open terminal and enter following command:

  • npm i -D webpack webpack-cli

“-D” flag after “npm i” is used to install packages as a dev dependency. “Webpack” is used for webpack configuration and “webpack-cli” is used to run commands for bundling files under webpack configuration rules.

After successful installation, package.json file will look like this.

{

 “name”: “webpackLearn”,

 “version”: “1.0.0”,

 “description”: “”,

 “main”: “index.js”,

 “scripts”: {

   “test”: “echo \”Error: no test specified\” && exit 1″

 },

 “keywords”: [],

 “author”: “”,

 “license”: “ISC”,

 “devDependencies”: {

   “webpack”: “^5.74.0”,

   “webpack-cli”: “^4.10.0”

 }

}

To write rules for bundling our javascript files of src folder, lets create a configuration file as webpack.config.js on our project root path and paste following code.

const path = require(‘path’)

 

module.exports = {

   mode: ‘development’,

   entry: path.resolve(__dirname, ‘src/index.js’),

   output: {

       path: path.resolve(__dirname, ‘public’),

       filename: ‘bundle.js’,

   }

}

Here we are importing the built in node js path module on variable “path”. We will be using this for all tasks related to file pathname. As we are not using es6 syntax, module.exports is a common js syntax to export modules from a js file.

We are exporting the webpack configuration rules as a javascript object.

  • “ mode: ‘development’ ” defines the compile environment which is set to “development”.
  • “entry” key defines the path to the file that is to be minified or packed. Here we have set the entry file be src/index.js
  • “output” key is an object that has a “path” key that defines the location of the minified/packed file and the “filename” key defines the name of the file that will be created by webpack as a bundled file. If the “filename” key is not provided, webpack will create “main.js” as a default.

Lets reference the bundle file on html

Inside public/index.html, paste the following content.

<!DOCTYPE html>

<html lang=”en”>

<head>

   <meta charset=”UTF-8″>

   <meta http-equiv=”X-UA-Compatible” content=”IE=edge”>

   <meta name=”viewport” content=”width=device-width, initial-scale=1.0″>

   <title>Document</title>

</head>

<body>

   <h1 style=”text-align: center;”>Webpack Learn</h1>

   <script src=”./bundle.js”></script>

</body>

</html>

Now let’s add a command to run our webpack. On package.json file paste the following code.

{

 “name”: “webpackLearn”,

 “version”: “1.0.0”,

 “description”: “”,

 “scripts”: {

   “build”: “webpack”

 },

 “keywords”: [],

 “author”: “”,

 “license”: “ISC”,

 “devDependencies”: {

   “webpack”: “^5.74.0”,

   “webpack-cli”: “^4.10.0”

 }

}

We have removed “main”: “index.js” as we don’t need it and added “build”: “webpack” inside the scripts object to run webpack as command.

Up to this point, our folder structure will look like this.

  • webpackLearn
    •  node_modules
    • public
      • index.html
    • src
      • index.js
      • js1.js
      • js2.js
    • package.json
    • package-lock.json
    • webpack.config.js

Lets bundle with webpack. On project root path open the terminal and enter the command “npm run build”

New file is created as “bundle.js” inside the public folder. Open that file in any text editor and you’ll see the compiled javascript file under development environment as we had set “mode”: “development” inside module.export object of webpack.config.js file. Now open the public/index.html file on browser and open developer tools by pressing f12. There check the console section. Everything is running perfectly.

Dynamic bundle filename:

Right now, we have explicitly defined our bundle file as “bundle.js” as “filename” value inside the “output” object of module.exports object in webpack.config.js file. We can make it dynamic by defining the “entry” value as a javascript “object”. Replace all with following code to webpack.config.js file.

const path = require(‘path’)

module.exports = {

   mode: ‘development’,

   entry: {

       bundle: path.resolve(__dirname, ‘src/index.js’),

   },

   output: {

       path: path.resolve(__dirname, ‘public’),

       filename: ‘[name].js’,

   }

}

Here, whatever key name we had provided inside the “entry” object (bundle in this case), webpack will create a bundle file as that key name as we have mapped the name of key of “entry” to the filename of “output” object as ‘[name].js’. 

Separate Development and Production script:

So far we have compiled the files on development mode. Now we will create separate commands for development and production mode. As we are defining commands for production and development, let’s remove the line “mode”: “development” in the webpack.config.js file.

webpack.config.js:

const path = require(‘path’)

module.exports = {

   entry: {

       bundle: path.resolve(__dirname, ‘src/index.js’),

   },

   output: {

       path: path.resolve(__dirname, ‘public’),

       filename: ‘[name].js’,

   }

}

On package.json file, add two commands(values) inside “scripts” object as “dev”:  “webpack –mode development”, “prod”: “webpack –mode production”

Package.json file:

{

 “name”: “webpackLearn”,

 “version”: “1.0.0”,

 “description”: “”,

 “scripts”: {

   “dev”: “webpack –mode development”,

   “prod”: “webpack –mode production”

 },

 “keywords”: [],

 “author”: “”,

 “license”: “ISC”,

 “devDependencies”: {

   “webpack”: “^5.74.0”,

   “webpack-cli”: “^4.10.0”

 }

}

On the project root path open the terminal and enter the command “npm run dev” and “npm run prod” in an alternate way and watch the changes on the public/bundle.js file on each command. “npm run dev” command compiles the files on development mode and “npm run prod” compiles the files in a minified way on production mode.

Hot reload:

So far we have compiled our javascript files as a single bundle file in both development and production mode. But things get tedious when we need to compile the files every time we make just a small change in them. We had to run commands every time we made changes to any one of the files to reflect the changes. To handle such issues, webpack provides a feature to watch for any changes made to files and compile it automatically.

Lets configure our webpack rules to watch our file content changes. On your webpack.config.js file, replace everything with the following code.

const path = require(‘path’)

module.exports = {

   entry: {

     bundle: path.resolve(__dirname, ‘src/index.js’),

   },

   output: {

       path: path.resolve(__dirname, ‘public’),

       filename: ‘[name].js’,

   },

   devServer: {

     static: {

       directory: path.resolve(__dirname, ‘public’)

     },

     port: 3000,

     open: true,

     hot: true

   }

}

Here, we have added a new rule as “devServer”. Inside it, “static” key is a javascript object that accepts another key “directory” that defines the path to serve the file. Another key “port” defines the port number to serve the project and listens for any file content changes. The “open” key determines the rule to open the web browser and serve the project on port number defined by “port” key. And the “hot” key determines the rule to reload the page when changes occur on file and is saved.

Now let’s add a command to run the project as a dev server on package.json file. We will define the command as “watch” in this project. Replace package.json file contents with following code.

{

 “name”: “webpackLearn”,

 “version”: “1.0.0”,

 “description”: “”,

 “scripts”: {

   “dev”: “webpack –mode development”,

   “prod”: “webpack –mode production”,

   “watch”: “webpack serve”

 },

 “keywords”: [],

 “author”: “”,

 “license”: “ISC”,

 “devDependencies”: {

   “webpack”: “^5.74.0”,

   “webpack-cli”: “^4.10.0”

 }

}

On the project root path open the terminal and enter the command “npm run watch”

OUCH!!!

> webpack serve

[webpack-cli] For using ‘serve’ command you need to install: ‘webpack-dev-server’ package.

[webpack-cli] Would you like to install ‘webpack-dev-server’ package? (That will run ‘npm install -D webpack-dev-server’) (Y/n)

To run webpack serve, we need to install ‘webpack-dev-server’. On your terminal where you were prompted to install to ‘webpack-dev-server’ type ‘y’ and hit enter key. After successful installation of the package, webpack will open the default browser and serve the project on a defined port number.

On default, the server runs on production mode as “mode” is not set on webpack.config.js file.

To check the hot reload feature, open the src/index.js file and replace its contents with the following code.

import function1, {testFunction2} from ‘./js1’

import values from ‘./js2’

document.body.style.background = “black”;

document.body.style.color = “white”;

function1()

testFunction2()

console.table(values)

Save the file and our server will reload automatically and reflect the changes.

Next Steps:

In this article, we compile javascript files as a single file using webpack using only basic rules and configurations. But webpack is capable of bundling scss, png, and other types of files also. Diving deeper, webpack can compile a more complex file system using various plugins and loaders. Top javascript libraries like React, Vue etc. also use webpack to bundle their components and other files.

If you make it to the end, congrats you have learned trending technology. Happy coding.