Front-End Development

Webpack: It Configures part 2 – The Ruler’s Back

Webpack Blog Meme

Module Rules

Previously we went over where webpack will get the instructions of what files to package and where to put the results. Before webpack can do any of this, it has to know how to deal with these files and how to convert that information into a javascript format. This requires us to create rules for each type of file.

In the example structure below we will be modifying the rules array within the module property.

module.exports = {           //  the configuration object wrapper
     entry:{},               //  where we define the location for the index.js file (usually) to read 
     output: {},             //  where we define the filename(s) and location(s) for the final output
     mode: '',               //  what kind of build process should be used?
     module: {               //  general wrapper for how anything pulled into webpack should be processed
         rules: []           //  will contain specific instructions for each type of file we encounter
    },
    plugins: []              //  will list all plugins and any options for each we want to run
}

Common rules properties

Each rule is an object { } inside the rules array. Rules are set up by first creating a Regular Expression (regex) for the filename extension.  The property is called test. This is an example of one that checks if it is a TXT file.  The regex area is between the forward slashes. The first backslash is needed to escape the period so it’s included in the test. Then we add the extension string of txt and end it with a dollar sign to signal this must be the end.  You can also add an after the last forward slash just in case you have any files using anything but lower case letters.  Check out https://regex101.com to find out more ways to use regular expressions.


module{
     rules: [
              {
                test: /\.txt$/,
                type: 'asset/source',
                use: [ some kind of loader ]
              }
     ]
}

 

For simple usage a type must be added. By “simple” I mean you are not going to use anything special to process this file.  We will be going over what this “special” thing is later when we get to loaders which are listed in the use[ ] array.

There are four asset types:

  • ‘asset/resource’                 copies the file and places it in the output directory you specify (large images for example)
  • ‘asset/inline’                      transforms the file into a base64 version so no file is created for it
  • ‘asset/source’                    uses the file as-is with no modification
  • ‘asset’                                general asset, let webpack decide by file size (8KB max by default) if it is either inline or resource

Loaders      https://webpack.js.org/loaders

Very often a file type is going to require some help getting processed by webpack. Loaders are used to do this. Some are already available and some need to be installed. In order to keep track of these as dependencies, they need to be included in package.json so we will be doing installs for them for latest versions and including them in package.json.

Some commonly used loaders are:

  • babel-loader                    used to convert any latest version javascript into ES5 equivalents
  • ts-loader                          for conversion of typescript into js
  • sass-loader                      compiles sass/scss into css
  • css-loader                        pulls css into javascript
  • style-loader                     creates a <style> tag in your html file (usually replaced with some other plugin)

Example Sass / CSS Rule with loaders

Note: when using loaders you don’t need to specify the type unless you have a special situation.

Below we are using a simple configuration where the loaders are called from last to first.
sass-loader runs first and converts any sass/scss into css, then css-loader runs to convert it into javascript, and lastly it’s placed in our html file inside a <style> tag… but we won’t do that.  We’ll swap that out with a plugin in a bit to make a separate css file with a <link> tag like we’d normally do.

module{
     rules: [
              {
                test: /\.(sa|sc|c)ss$/,         // fancy way to target .sass, .scss or .css files
                use: ['style-loader','css-loader','sass-loader'] 
              }
     ]
}

Installing loaders and plugins

We haven’t talked about the terminal in awhile.  Open it to your project folder path, or if using VSCode just hit Ctrl + `.  We are going to install the loaders shown above. We will also include a plugin to use instead of style-loader above.

Let’s install the needed loader for CSS.  Enter the command below and hit enter. In this case we need this loader during local development, so the flag –save-dev is used. There are shorter ways to write the whole command, but for now we will make it more clear what we’re doing.

npm install css-loader --save-dev

Next, let’s install everything Sass needs.  In this case we need both the sass core files and sass-loader.

npm install sass-loader sass --save-dev

Now let’s take a look at our package.json to see what has changed in our devDependencies section. In addition to the previous webpack modules we now have the new loaders and other required files. Your version numbers will vary, of course.

"devDependencies": {
    "css-loader": "^6.7.2",
    "sass": "^1.56.2",
    "sass-loader": "^13.2.0",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
  },

For these loaders that’s all that is needed for the config file to work, but for the next part we’ll be adding a plugin for creating a separate css file after all the other processing is finished.  First we’ll install it like before, but we then have to add it to the top of our config file as a requirement.

Install mini-css-extract-plugin

npm install mini-css-extract-plugin --save-dev

After this is installed you’ll see it added as before to package.json as a dev dependency.

"mini-css-extract-plugin": "^2.7.2",

Now put a require statement at the top of the config file after where we require path. You can call it something else besides MiniCssExtractPlugin if you want. The variable name doesn’t matter as long as you know what it is.

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

The next thing we need to do when using a plugin is to add it to the plugins array in our config file. Here we create a new instance of the plugin, referencing the variable name from before.  Any options a plugin may have are included as an object argument. By default it will use the output property we defined in part 1, which is “./dist/” but we will create our own css folder by adding that to the filename. Notice how adding them together we will get “./dist/css/styles.css” so keep in mind that trailing slash.

plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/styles.css'
        })
    ]

Finally, we will modify our rule we started with to use this plugin instead of style-loader.  Notice now instead of just comma separated list in the use [ ] array we have separate objects with a loader property.  This is assumed if you just list them like before. If any options are needed it’s best to start with the object notation.

The MiniCssExtractPlugin is not using options, but now ‘css-loader’ and ‘sass-loader’ have an options property to create sourcemaps.  When doing front end work, we need this when using Sass to find the location of the file to modify! When we get to prod vs dev builds, sourcemaps will usually not be included.

module{      
     rules: [ 
              { 
                test: /\.(sa|sc|c)ss$/, 
                use: [
                      {
                        loader: MiniCssExtractPlugin.loader
                      },
                      {
                        loader: 'css-loader',
                        options: {
                           sourceMap: true
                        }
                      },
                        loader: 'sass-loader',
                        options: {
                           sourceMap: true
                        }
                      }
                ] 
              }      
            ] 
}

 

Next Webpack: Plug it In

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Ed Murphy

Ed Murphy is a Front End development veteran with over 20 years of experience. He’s constantly investigating the newest technologies available for the front-end developer and enjoys teaching others, as that’s the best way to teach yourself.

More from this Author

Follow Us
TwitterLinkedinFacebookYoutubeInstagram