Popular Tags

Webpack: A Simplified Guide

Here is a simple guide on installing and configuring Webpack for those who design a static web page which doesn’t require backend code.

Webpack: A Simplified Guide

Contents

  1. Create a Project
  2. Create a JSON File
  3. Install
  4. Package.json
  5. Configuration
  6. Commands

Webpack is a module bundler for JavaScript, HTML, CSS, and images. It allows including various plugins and loaders. When Webpack processes your project, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles.

Webpack is in many ways similar to Gulp, although the latter is intended for smaller frontend projects and Webpack offers more options for complex web development. 

1. Create a Project

For example, your project may contain the following:

    
        
webpack-project/
└── dist/
└── src/
│    └── css/
│        └── global.scss // or global.less
│        └── main.scss // or main.less
│        └── ...
│    └── img/
│    └── js/
│        └── script.js
│    └── template.html
    

The src folder will contain the original files, and dist will include the files compiled by Webpack.

There is no need to embed CSS and JS files in template.html: your compiled CSS file will be imported in a JS file (script.js), and your JS file will be embedded in an HTML file generated by Webpack in the dist folder.

2. Create a JSON File

Open a CMD. Type the path to your project, for example:

    
        
cd C:\Users\Shark\Documents\Projects\webpack-project
    

Next, run the command:

    
        
npm init
    

You will see some text, and the CMD will offer you to add some information about your project. Fill out the fields or press Enter to leave them blank. Below is an example of partially filled-out notes:

    
        
package name: (webpack-project)
version: (1.0.0)
description: This is a sample project
entry point: (index.js) script.js
test command:
git repository: 
keywords:
author: Shark
license: (ISC)
About to write
to C:\Users\Shark\Documents\Projects\webpack-project\package.json:
    

Press Enter and you will see that the package.json has been created in the root of your project:

    
        
webpack-project/
└── dist/
└── src/
│    └── css/
│        └── global.scss // or global.less
│        └── main.scss // or main.less
│        └── ...
│    └── img/
│    └── js/
│        └── script.js
│    └── template.html
└── package.json
    

Here is the content of the package.json file so far:

    
        
{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "This is a sample project",
  "main": "script.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Shark",
  "license": "ISC"
}
    

3. Install

You need to install a minimum of loaders and plugins to use Webpack properly. Loaders operate transforms on single files, and plugins operate across larger chunks of code.

Run the command below:

    
        
npm i -D webpack webpack-cli style-loader css-loader postcss-loader sass-loader node-sass mini-css-extract-plugin clean-webpack-plugin html-webpack-plugin html-beautify-webpack-plugin webpack-dev-server
    

This will install the following:

  • webpack and webpack-cli: install Webpack files and a Command Line Interface (CLI) to configure and interact with your build
  • style-loader: injects styles into the DOM
  • css-loader: interprets @import and @url() and resolves any dependencies
  • postcss-loader: adds vendor prefixes to CSS rules (Autoprefixer)
  • sass-loader: transforms Sass into CSS
  • mini-css-extract-plugin: extracts CSS into separate files, creates a CSS file per JS file which contains CSS
  • clean-webpack-plugin: cleans up the dist folder automatically before each build
  • html-webpack-plugin: automatically updates template.html to reference the new file paths each time outputs change (useful when you use hash names for your css files to generate in the dist folder)
  • html-beautify-webpack-plugin: beautifies HTML
  • webpack-dev-server: provides you with a simple web server and live reloading, so you don’t need to manually refresh the page to see changes

If you use Less instead of Sass, run less-loader instead of sass-loader node-sass.

You may also need to install jQuery in your project:

    
        
npm i -S jquery
    

4. Package.json

After installing loaders and plugins, your package.json should look like the one below. Delete "test" from scripts and add three lines instead: "build", "watch", and "dev". 

    
        
{
  "name": "webpack-project",
  "version": "1.0.0",
  "description": "",
  "main": "script.js",
  "scripts": {
	"build": "webpack --config webpack.config.js",
	"watch": "webpack --watch --config webpack.config.js",
	"dev": "webpack-dev-server --config webpack.config.js"
  },
  "author": "Shark",
  "license": "ISC",
  "devDependencies": {
	"clean-webpack-plugin": "^3.0.0",
	"css-loader": "^3.1.0",
	"html-beautify-webpack-plugin": "^1.0.5",
	"html-webpack-plugin": "^3.2.0",
	"mini-css-extract-plugin": "^0.8.0",
	"node-sass": "^4.12.0",
	"postcss-loader": "^3.0.0",
	"sass-loader": "^7.1.0",
	"style-loader": "^0.23.1",
	"webpack": "^4.36.1",
	"webpack-cli": "^3.3.6",
	"webpack-dev-server": "^3.7.2"
  },
  "dependencies": {
	"jquery": "^3.4.1"
  }
}
    

5. Configuration

Create a webpack.config.js file in the root of your project and add the following configuration for installed loaders and plugins:

    
        
const path = require('path'),
      isDevelopment = process.env.NODE_ENV === 'development',
      MiniCssExtractPlugin = require('mini-css-extract-plugin'),
      { CleanWebpackPlugin } = require('clean-webpack-plugin'),
      HtmlWebpackPlugin = require('html-webpack-plugin'),
      HtmlBeautifyPlugin = require('html-beautify-webpack-plugin');
      webpack = require('webpack');

module.exports = {
    mode: isDevelopment ? 'development' : 'production',
    entry: './src/js/script.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist',
        publicPath: '/',
    },
    devServer: {
        contentBase: __dirname + '/src',
        publicPath: '/',
        inline: true,
        hot: true,
        watchContentBase: true
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: isDevelopment ? '[name].[hash].css' : '[name].[hash].css',
            chunkFilename: isDevelopment ? '[id].[hash].css' : '[id].[hash].css'
        }),
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: 'src/template.html',
            filename: 'index.html'
        }),
        new HtmlBeautifyPlugin({
            config: {
                html: {
                    end_with_newline: true,
                    indent_size: 2,
                    indent_with_tabs: true,
                    indent_inner_html: true,
                    preserve_newlines: true,
                    unformatted: ['p', 'i', 'b', 'span']
                }
            },
            replace: [' type="text/javascript"']
        }),
        new webpack.HotModuleReplacementPlugin(),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery'
        })
    ],
    module: {
        rules: [
            {
                test: /\.s(a|c)ss$/,
                loader: [
                    isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: isDevelopment
                        }
                    },
                ]
            },
        ]
    },
    resolve: {
        extensions: ['.js', '.jsx', '.scss']
    }
};
    

Here are a few comments to the configuration file:

  • mode: it’s a configuration option that tells Webpack to use its built-in optimizations accordingly. 
  • entry: as an entry, indicate the path to your main JS file in the src folder (script.js).
  • output: as an output, indicate the name of the output JS file (for example, bundle.js) and the name of the folder it will be contained in (dist). While script.js is the file where you’ll be doing things, bundle.js is a compiled file you don’t have to worry about.
  • devServer: this set of options is picked up by webpack-dev-server.
  • plugins: contains sets of options picked up by various plugins installed earlier. Using [hash] for files names will generate hash names for .css files for each build.
  • module.rules: can apply loaders to the module which is a chunk of functionality. Pay attention: loaders should be configured in this order: 1) css-loader, 2) postcss-loader, 3) sass-loader.
  • resolve.extensions: attempts to resolve the indicated extensions in order. If multiple files share the same name but have different extensions, Webpack will resolve the one with the extension listed first in the array and skip the rest.

Next, create postcss.config.js with:

    
        
module.exports = {
  plugins: [
	require('autoprefixer')
  ]
}
    

This file is useful for the correct work of Autoprefixer.

Finally, add the following statements in your script.js file:

    
        
import '../css/main';

import $ from 'jquery';
window.jQuery = $;
window.$ = $;
 
if (module.hot) {
    module.hot.accept()
}
    
  • import: You need to import your SCSS file in the JS file because Webpack will take styles from the point of entry, which is ./src/js/script.js. You don’t need to include the file extension because you’ve already told Webpack to look for files with .scss file extensions automatically in the extensions array. So you can delete the extension in the import statement in the script.js file: import '../css/main';.
  • model.hot.accept is required to automatically reload your HTML page. 

6. Commands

You need to run two commands in the CMD:

  • npm run watch: to run scripts from package.json when files change. After running this command, you should see the line saying “webpack is watching the files…”. It means that all changes in the SCSS and JS files will be detected and the files will be compiled.
  • nmp run dev: to run in the development mode. As webpack-dev-server provides you with a simple web server, your HTML page will be available in the browser at localhost:8080. 

The final file structure:

    
        
webpack-project
└── dist/
└── node_modules/
└── src/
│    └── css/
│        └── global.scss // or global.less
│        └── main.scss // or main.less
│        └── ...
│    └── img/
│    └── js/
│        └── script.js
│    └── template.html
└── package-lock.json
└── package.json
└── postcss.config.js
└── webpack.config.js