Monday, 16 July, 2018 UTC


Summary

Today we continue our webpack 4 tutorial.  After walking through the basic concepts of webpack, it is time to go deeper. This time we will cover something that is a great strength of webpack: loaders. First, we will learn how to use loaders that are available. This will include handling css, scss, image files and transpiling JavaScript to the older versions of the language. Let’s go!
Webpack 4 tutorial continued – what are loaders?
In the previous part of the course, I’ve said that webpack is a module bundler. But this is not its only purpose. Even though webpack understands only JavaScript files out of the box, it can be changed with the usage of loaders. Aside from just handling many types of files, it can modify them.
Adding loaders
The best way to use loaders is to specify them in the
webpack.config.js
  file. To do that, you need to add a
module.rules
 property.

css-loader

The
css-loader
 interprets imported css files.
npm install css-loader
Consider the configuration below:
webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: 'css-loader'
      }
    ]
  }
}

rules

The property rules is an array of all of your loaders. These rules will be applied to every file, that matches the test property of the rule. This is, in fact, a regular expression.
If you would like to know more about regular expressions, check out my regex course.

use

The property use is an indicator of which loader should be used for matching files.
Chaining loaders
With the code above, you are able to import css files through your JavaScript code (for example using ES6 modules that we covered in the previous part of the course).
But this is not enough to actually put that css to work. We need a way to serve that code to the browser. Here, the
style-loader
 will be useful.
npm install style-loader
But that would mean using two loaders for the css files. You can do that by chaining loaders.
webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  },
}
As you can see, now we are assigning an array to the use property. A very important thing to note is that the chain is executed in reverse order.
style.css
body {
  background-color:black;
}
index.js
import './style.css';
Using the configuration above will work like that:
  1. Webpack will try to resolve the style.css file
  2. The filename will match the 
    /\.css$/
     regular expression
  3. The file will be interpreted by the css-loader
  4. The result of the css-loader will be passed to the style-loader
  5. Finally, the style-loader will return a JavaScript code
By default, the output bundle is 
./dist/bundle.js
. Now, this file will contain code that will attach all the styles into the
<style>
 tag. If you link the bundle.js file in the HTML, the output after running the script will be like that:
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Webpack App</title>
  <style type="text/css">body {
    background-color:black;
  }</style></head>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

sass-loader

With all that knowledge, you can easily add sass/scss support to your project. We will use sass-loader here.
npm install sass-loader
You just need to add it to the loader chain:
webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      }
    ]
  },
}
And there you go, now you can import scss files! Files, before being interpreted by the css-loader, will be transpiled from the scss to pure css.
Passing options to loaders
Loaders can, in fact, accept additional options. Let’s explain it with the example of url-loader
npm install url-loader file-loader
webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader','sass-loader']
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 5000
            }
          }
        ]
      }
    ]
  }
};
Note, that if you wish to pass options to the loader, you no longer add loaders to the use property as a string. Now it is an object with two properties: loader (the name of the loader) and options.
The url-loader will transform your images into base64 URIs. If your images are very small, it might be better for your performance to include them straight into your code. This will cause your browser to make fewer requests. If your images are big though, it might be beneficial to include them as separate files so that the browser might fetch them in parallel.
This is why the url-loader has the limit property. It is a size (in bytes) that will determine, that the file is too big to serve it as a base64 URI. Instead, the file-loader will be used that will just copy your files.
body {
  background-image: url('./big-background.png');
}
.icon {
  background-image: url('./icon.png');
}
The above configuration will result in:
<style type="text/css">body {
  background-image: url(ca3ebe0891c7823ff1e137d8eb5b4609.png); }

.icon {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAALElEQVR4AWMYIWAU1FPLoP9AXEFI0QEi8H+YYdQyqIEaXuumRhh1DZdUMwoATlYWfwh9eYkAAAAASUVORK5CYII=); }
</style>
Since the
big-background.png
 was bigger than the defined limit, it was copied to the
dist
 directory with a random filename. The
icon.png
 file was converted to the base64 URI instead.
Using babel to transpile JavaScript
Another popular loader is babel-loader. It allows transpiling JavaScript files using Babel. It is a solution for writing code in the latest versions of JavaScript. This might be useful if you want to support older browsers, or if you want to use some feature that even modern browsers don’t implement yet.
npm install babel-loader babel-core babel-preset-env
webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
};
Note, that we used exclude property here, which is also a regular expression. If the path of any file will match this expression, the file will not be transpiled.
There are many presets that you can use to fit your needs. Read the official babel documentation for a list of them and try to experiment with an online transpiler.
Summary
This time we’ve learned a very useful feature of webpack: loaders. We’ve covered some of the loaders that are available to us. Using them, we’ve managed to add a scss support to our project. Besides that, we’ve learned how to handle images using url-loader. Another common usage of loaders that we’ve discussed is transpiling JavaScript using Babel. In the future parts of the course, we will dig deeper into loaders, including writing our own loader.
The post Webpack 4 course – part two. Using loaders to handle scss, image files and transpile JS appeared first on Marcin Wanago Blog - JavaScript, both frontend and backend.