Where to Discuss?

Preface

Goal: Put the whole stuff together using webpack bundler.

Source Examples

You can obtain source examples here:


4: Template - HTML

Objective

Generate dist/index.html, from html/index.html with injected assets.

Directory Tree

Additional file: html/index.html.

.
├── css
│   └── style.css
├── dist
│   ├── bundle.js
│   ├── index.html
│   └── style.js
├── html
│   └── index.html
├── js
│   ├── live.js
│   └── script.js
├── package.json
└── webpack.config.js

The webpack should generate three files:

  • dist/bundle.js, and
  • dist/style.js, and
  • dist/index.html.

HTML View

The html/index.html does not contain either js/script.js, nor css/style.css.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Example Template</title>
    <script src="../js/live.js"></script>
  </head>
  <body>
    ...
  </body>
</html>

package.json

Additional node module html-webpack-plugin.

  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "css-loader": "^3.5.3",
    "style-loader": "^1.2.1",
    "html-webpack-plugin": "^4.3.0"
  },

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: {
    bundle: "./js/script.js",
    style: "./css/style.css"
  },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({template: './html/index.html'})
  ]
};

Command Line Interface

Just run the webpack in terminal

$ webpack
Hash: 20348db9915d290852a2
Version: webpack 4.43.0
Time: 1369ms
Built at: 05/09/2020 1:24:37 AM
     Asset      Size  Chunks             Chunk Names
 bundle.js  4.29 KiB  bundle  [emitted]  bundle
index.html  1.33 KiB          [emitted]  
  style.js  16.9 KiB   style  [emitted]  style
Entrypoint bundle = bundle.js
Entrypoint style = style.js
[./css/style.css] 519 bytes {style} [built]
[./js/script.js] 515 bytes {bundle} [built]
[./node_modules/css-loader/dist/cjs.js!./css/style.css] 1.44 KiB {style} [built]
    + 2 hidden modules
...

Webpack: Generate HTML: Running Webpack in Terminal

View in Browser

Just check if everything goes right.

Also check the source code with Ctrl+U, the assets should be somewhere below the documents.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Example Template</title>
    <script src="../js/live.js"></script>
  </head>
  <body>
    <div class="container">
      ...
    </div>
  <script src="bundle.js"></script><script src="style.js"></script></body>
</html>

Plugin in Configuration

We utilize html-webpack-plugin.

const HtmlWebpackPlugin = require('html-webpack-plugin');

And use the plugin in configuration:

  plugins: [
    new HtmlWebpackPlugin({template: './html/index.html'})
  ]

I know, it looks magical.


5: Template - Pug

Objective

Generate dist/index.html, from pug/alert.pug with injected assets.

Directory Tree

Removed file: html/index.html.

Additional file: pug/alert.pug and pug/partials/body.pug.

.
├── css
│   └── style.css
├── dist
│   ├── bundle.js
│   ├── index.html
│   └── style.js
├── js
│   ├── live.js
│   └── script.js
├── pug
│   ├── alert.pug
│   └── partials
│       └── body.pug
├── package.json
└── webpack.config.js

Pug View

The pug/alert.pug is shown as below:

  • [gitlab.com/…/pug/index.pug][05-pug-index-pug]
doctype html
html(lang="en")

  head
    meta(charset='utf-8')
    title Example Template
    script(src='../js/live.js')

  body
    include partials/body.pug

And the pug/partials/body.pug is shown as below:

.container
  h2 Relationship Alerts
  p To close the alerts, click on the X in the upper right corner:
  
  ...

package.json

Additional node module pug and pug-loader.

  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "css-loader": "^3.5.3",
    "style-loader": "^1.2.1",
    "html-webpack-plugin": "^4.3.0",
    "pug": "^2.0.4",
    "pug-loader": "^2.4.0"
  },

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: {
    bundle: "./js/script.js",
    style: "./css/style.css"
  },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /\.pug$/i,
        use: [
          {
            loader: 'pug-loader',
            options: {
              pretty: true
            }
          }
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({template: './pug/alert.pug'})
  ]
};

Command Line Interface

Just run the webpack in terminal

$ webpack
Hash: 199cfdd8d2bf018d5f42
Version: webpack 4.43.0
Time: 950ms
Built at: 05/09/2020 1:35:34 AM
     Asset      Size  Chunks             Chunk Names
 bundle.js  4.29 KiB  bundle  [emitted]  bundle
index.html  1.27 KiB          [emitted]  
  style.js  16.9 KiB   style  [emitted]  style
Entrypoint bundle = bundle.js
Entrypoint style = style.js
[./css/style.css] 519 bytes {style} [built]
[./js/script.js] 515 bytes {bundle} [built]
[./node_modules/css-loader/dist/cjs.js!./css/style.css] 1.44 KiB {style} [built]
    + 2 hidden modules
...

View in Browser

Change the content of pug files, run webpack again, and see if there is any changes in index.html.

Change in Configuration

The plugin, has been altered into this:

  plugins: [
    new HtmlWebpackPlugin({template: './pug/alert.pug'})
  ]

Remember that the example source name is alert.pug, not index.pug. And the generated file is index.html, not alert.html. You can figure it out yourself, how to translate from alert.pug to alert.html.

Loader in Configuration

Also you need rules in modules that use pug-loader.

        test: /\.pug$/i,
        use: [
          {
            loader: 'pug-loader',
            options: {
              pretty: true
            }
          }
        ],

6: Stylesheet - Extract CSS

Consider go back for a while to split assets. Now we are going to extract the assets from dist/style.js, into dist/style.css.

Objective

Extract stylesheet from dist/style.js to dist/style.css

Directory Tree

Again, we use the manually created dist/example.html.

No additional file. The dist/style.css will be generated.

.
├── css
│   └── style.css
├── dist
│   ├── bundle.js
│   ├── example.html
│   ├── style.css
│   └── style.js
├── js
│   ├── live.js
│   └── script.js
├── package.json
└── webpack.config.js

package.json

Required node module: mini-css-extract-plugin.

  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "css-loader": "^3.5.3",
    "mini-css-extract-plugin": "^0.9.0"
  },

webpack.config.js

const
  path = require('path'),
  MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: 'development',
  entry: {
    bundle: "./js/script.js",
    style: "./css/style.css"
  },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css"
    })
  ],
};

Command Line Interface

Just run the webpack in terminal

$ webpack
Hash: ffe5e4c29cb5de903e63
Version: webpack 4.43.0
Time: 1203ms
Built at: 05/09/2020 1:45:26 AM
    Asset      Size  Chunks             Chunk Names
bundle.js  4.29 KiB  bundle  [emitted]  bundle
style.css  1.15 KiB   style  [emitted]  style
 style.js  3.83 KiB   style  [emitted]  style
Entrypoint bundle = bundle.js
Entrypoint style = style.css style.js
[./css/style.css] 39 bytes {style} [built]
[./js/script.js] 515 bytes {bundle} [built]
    + 1 hidden module

Webpack: Extract Stylesheet: Running Webpack in Terminal

View in Browser

Just check, if the stylesheet loaded.

Plugin in Configuration

We utilize MiniCssExtractPlugin.

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

And use it in configuration:

  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css"
    })
  ],

Nothing magical, here. It just use [name].css, to get the right filename.

Loader in Configuration

Beware of this loader. The rules utilize MiniCssExtractPlugin.loader instead of style-loader. And still using css-loader.

  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
    ],
  },

7: Stylesheet - Render Stylus

Objective

Render from css/stylus.styl, then extract to dist/style.css

Directory Tree

Still using the manually created dist/example.html.

Additional file: css/style.styl. Removed file: css/style.css.

From css/style.styl, the dist/style.css will be generated.

.
├── css
│   └── style.styl
├── dist
│   ├── bundle.js
│   ├── example.html
│   ├── style.css
│   └── style.js
├── js
│   ├── live.js
│   └── script.js
├── package.json
└── webpack.config.js

Stylesheet

...
.red
  color: #fff !important
  background-color: #f44336 !important

.yellow
  color: #000 !important
  background-color: #ffeb3b !important
...

package.json

Additional node module stylus and stylus-loader.

  "devDependencies": {
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "css-loader": "^3.5.3",
    "mini-css-extract-plugin": "^0.9.0",
    "stylus": "^0.54.7",
    "stylus-loader": "^3.0.2"
  },

webpack.config.js

const
  path = require('path'),
  MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  mode: 'development',
  entry: {
    bundle: "./js/script.js",
    style: "./css/style.styl"
  },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, 'dist'),
  },
  module: {
    rules: [
      {
        test: /\.styl$/i,
        use: [
          MiniCssExtractPlugin.loader, 
          'css-loader', 
          'stylus-loader'
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css"
    })
  ],
  
};

Command Line Interface

Just run the webpack in terminal

$ webpack
Hash: f9b55bb4cf2c2b2cd2bc
Version: webpack 4.43.0
Time: 2467ms
Built at: 05/09/2020 2:08:07 AM
    Asset      Size  Chunks             Chunk Names
bundle.js  4.29 KiB  bundle  [emitted]  bundle
style.css  1.15 KiB   style  [emitted]  style
 style.js  3.84 KiB   style  [emitted]  style
Entrypoint bundle = bundle.js
Entrypoint style = style.css style.js
[./css/style.styl] 39 bytes {style} [built]
[./js/script.js] 515 bytes {bundle} [built]
    + 1 hidden module

Webpack: Render Stylus: Running Webpack in Terminal

View in Browser

Just check, if the stylesheet loaded.

Change the stylesheet in css/style.styl a bit, and see if the change reflected in genereted dist/style.css.

Entry Point in Configuration

The entry point, has been altered into this:

  entry: {
    bundle: "./js/script.js",
    style: "./css/style.styl"
  },

instead of this:

  entry: {
    bundle: "./js/script.js",
    style: "./css/style.css"
  },

Loader in Configuration

Also we have three loader in styl rules:

  module: {
    rules: [
      {
        test: /\.styl$/i,
        use: [
          MiniCssExtractPlugin.loader, 
          'css-loader', 
          'stylus-loader'
        ],
      },
    ],
  },

What’s Next?

Consider continue reading [ Bundler - Webpack - Part Three ].