Composing Webpack Loaders into Rules

Last week I told you that Webpack Loaders are functions that take in some resource and return JavaScript.

That was a bit of an oversimplification.

A loader is a function that receives a resource (generally the contents of a file) and applies a transformation to it. Loaders can be chained together and we use them to compose rules in our Webpack config. The loader itself can return any arbitrary transformation, but it's the rules that have to ultimately return JavaScript. A very simple rule would look like this:

// webpack.config.js

module.exports = {
  module: {
    rules: [
        test: /\.json$/,
        loader: "json-loader"

Our single rule here says that when Webpack encounters a module whose name ends in ".json", it will apply the json-loader which turns the file contents into executable JavaScript code that can be included in our bundle. Because the rule uses only a single loader, the two are basically synonymous here, and the json-loader is expected to return JavaScript code.

But as I mentioned, we can chain Webpack loaders together to form a rule. In that case, it's only the last loader that is expected to return JavaScript. "Last" is a bit confusing here, because loaders are executed in the reverse order in which they are specified. When I say last, I mean the last loader to execute, which will actually be the first loader in the list.

Remember this rule from last week:

  test: /\.css$/,
  use: [ 'style-loader', 'css-loader' ]

In this case, when Webpack encounters a CSS module it will apply the loaders from right to left. First, css-loader tells Webpack how to resolve css modules. Remember, importing CSS into js files is not standard to the JavaScript language. It's the css-loader that tells Webpack what to do when it encounters an import statement that points to a CSS file. css-loader doesn't do anything with the files though. It simply resolves them and turns them into some kind of object that other loaders can deal with. In this case, the style-loader then takes that object and adds logic into our generated bundle which will inject those styles into the DOM at runtime.

So at its most basic, a rule has a test attribute which says what kind of modules it should apply to, and composes a chain of one or more loaders which resolve that module and transform it into JavaScript that can be executed in the final bundle.

This is a good working definition to keep in your head when working with Webpack. But like everything with Webpack, it's not always that simple. Tomorrow we'll talk about other side effects that rules can have, and I'll give you a little more detail into how they interact with Plugins.

Did you like this?

I send a daily email with tips and ideas like this one. Join the party!