Tutorial for webpack 4 - part 05 - CSS

webpackTutorial for webpack 4 - part 05 - CSS

 

What would be a web application without styles? Even a small application used on production has defined colors, margins, fonts etc. I have to take them into consideration when bundling it with webpack. This time I will add CSS file to the package.

 

 

Table of contents

If you want to jump to other parts of the tutorial, use table of contents.

 

Styles in my sample application

Earlier, the application contained only HTML and JS files. This time I add a sample CSS file to show you how it can be handled by webpack. Code changes can be reviewed on GitHub. Here, I will focus only on the most important aspect - I created main.css with colors and other visual changes and added it to styles directory. Normally, I would also add a link tag to the HTML files to include the CSS file but I will not do that as I remember that the HTML files are only templates. The final files should be generated by webpack. I expect webpack to add proper dependencies as well.

 

Install css-loader and mini-css-extract-plugin

I need two frontend components for what I want to do. The first one is css-loader which is responsible for reading styles from CSS files. The second one is mini-css-extract-plugin which can create CSS file with styles that was read by the previous loader.

The installation is as easy as in the previous parts of the tutorial.

D:\Git\multi-page-webpack-example\src>npm install css-loader --save-dev
npm WARN multi-page-webpack-example@1.0.0 No description
npm WARN multi-page-webpack-example@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ css-loader@2.1.0
added 26 packages from 53 contributors and audited 4442 packages in 21.391s
found 0 vulnerabilities
D:\Git\multi-page-webpack-example\src>npm install mini-css-extract-plugin --save-dev
npm WARN multi-page-webpack-example@1.0.0 No description
npm WARN multi-page-webpack-example@1.0.0 No repository field.
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.4 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.4: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

+ mini-css-extract-plugin@0.5.0
added 2 packages from 2 contributors and audited 4459 packages in 11.185s
found 0 vulnerabilities

If everything goes well (as above), you should see two new entries in package.json.

package.json
------------
{
 
"name": "multi-page-webpack-example",
 
"version": "1.0.0",
 
"description": "",
 
"scripts": {
   
"test": "echo \"Error: no test specified\" && exit 1"
 
},
 
"keywords": [],
 
"author": "",
 
"license": "ISC",
 
"devDependencies": {
   
"css-loader": "^2.1.0",
   
"html-webpack-plugin": "^3.2.0",
   
"mini-css-extract-plugin": "^0.5.0",
   
"webpack": "^4.27.1",
   
"webpack-cli": "^3.1.2"
 
}
}

 

css-loader and mini-css-extract-plugin configuration

webpack.config.js
-----------------
...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
   
entry: {
       
races: "./main/webapp/scripts/races.js",
       
results: "./main/webapp/scripts/results.js",
    },
   
output: {
       
path: __dirname + "/main/webapp/dist/",
       
filename: "scripts/[name].bundle.js"
   
},
   
plugins: [
       
...
       
new MiniCssExtractPlugin({
           
filename: "css/[name].css",
           
chunkFilename: "[id].css"
       
})
    ],
   
module: {
       
rules: [
            {
               
test: /\.css$/,
               
use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
        ],
    },
};

css-loader plugin does not require special configuration. The case is different with mini-css-extract-plugin. I use two options:

  • filename - specifies the path and name of CSS files to be generated; in my case, it is css directory and the name is the name of the entry point; I have two entry points: races and results so there should be two CSS files generated,
  • chunkFilename - defines a pattern for naming chunks; I have only one chunk so it does not do anything complex.

 

Bundling CSS

Everything is ready for a test. I build a package as usual.

D:\Git\multi-page-webpack-example\src>npx webpack --mode=development
npx: installed 1 in 13.494s
The "path" argument must be of type string
D:\Git\multi-page-webpack-example\src\node_modules\webpack\bin\webpack.js
Hash: b41f0a9b3d7bf61d1d51
Version: webpack 4.27.1
Time: 3442ms
Built at: 2019-01-26 20:47:02
Asset Size Chunks Chunk Names
css/races.css 205 bytes races [emitted] races
css/results.css 205 bytes results [emitted] results
races.html 463 bytes [emitted]
results.html 691 bytes [emitted]
scripts/races.bundle.js 5.16 KiB races [emitted] races
scripts/results.bundle.js 6.07 KiB results [emitted] results
Entrypoint races = css/races.css scripts/races.bundle.js
Entrypoint results = css/results.css scripts/results.bundle.js
[./main/webapp/scripts/races.js] 534 bytes {races} [built]
[./main/webapp/scripts/results.js] 1.36 KiB {results} [built]
[./main/webapp/styles/main.css] 39 bytes {races} {results} [built]
+ 1 hidden module
Child html-webpack-plugin for "races.html":
1 asset
Entrypoint undefined = races.html
[./node_modules/html-webpack-plugin/lib/loader.js!./main/webapp/races.html] 578 bytes {0} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]
+ 1 hidden module
Child html-webpack-plugin for "results.html":
1 asset
Entrypoint undefined = results.html
[./node_modules/html-webpack-plugin/lib/loader.js!./main/webapp/results.html] 824 bytes {0} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {0} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]
+ 1 hidden module
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!main/webapp/styles/main.css:
Entrypoint mini-css-extract-plugin = *
[./node_modules/css-loader/dist/cjs.js!./main/webapp/styles/main.css] 375 bytes {mini-css-extract-plugin} [built]
+ 1 hidden module

Of course, I can also use the production mode:

 npx webpack --mode=production

Whatever mode I use, two CSS files are generated: races.css and results.css.

bundle 

It is worth to notice that one original file - main.css was transformed to two files. In this case might seem strange but it is a good approach when CSS files differ between pages.

One last item is left - do the generated HTML files have a reference to the generated CSS files?

races.html
----------
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Previous races</title>
<link href="css/races.css" rel="stylesheet"><script type="text/javascript" src="scripts/races.bundle.js"></script></head>
<body>
...

Yes, they do.

When I open races.html in the browser, the page is styled and everything works well.

 

Summary

In this article, I added a simple CSS files to the project and bundled it with webpack.

Source code created in this part is on tutorial/part05-css branch on GitHub.

 

Next part

Tutorial for webpack 4 - part 06 - SCSS.

We use cookies

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.