Search code examples
webpackwebpack-2

webpack2: configuring module rules


I'm using webpack@2.6.1

My config is pretty simple:

{
  resolve: {
    modules: [
      SRC_ROOT,
      "node_modules",
    ],
  },

  entry: "index.js",

  output: {
    path: sysPath.join(APP_ROOT, "dist"),
    filename: "index.js",
  },

  module: {
    rules: [
      {
        test: /\.js$/i,
        include: SRC_ROOT,
        use: [
          {
            loader: "eslint-loader",
            enforce: "pre",
            options: {
              failOnError: true,
              failOnWarning: true,
            },
          },

          {
            loader: "babel-loader",
          }
        ],
      }
    ]
  },
}

And when I run it, I got following:

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration.module.rules[0].use should be one of these:
   non-empty string | function | object { loader?, options?, query? } | function | [non-empty string | function | object { loader?, options?, query? }]
   Details:
    * configuration.module.rules[0].use should be a string.
    * configuration.module.rules[0].use should be an instance of function.
    * configuration.module.rules[0].use should be an object.
    * configuration.module.rules[0].use should be one of these:
      non-empty string | function | object { loader?, options?, query? }
    * configuration.module.rules[0].use should be an instance of function.
    * configuration.module.rules[0].use[0] should be a string.
    * configuration.module.rules[0].use[0] should be an instance of function.
    * configuration.module.rules[0].use[0] has an unknown property 'enforce'. These properties are valid:
      object { loader?, options?, query? }
    * configuration.module.rules[0].use[0] should be one of these:
      non-empty string | function | object { loader?, options?, query? }

I'm confused, because these errors are totally contradict to what I see in docs: https://webpack.js.org/configuration/#options.

Arrays in "use" are not supported? "unknown property 'enforce'"? How is it even possible, when doc shows exactly the same usage examples?

Please explain what am I doing wrong here.


Solution

  • The problem is that enforce is not a valid property on a loader. It must be used on a rule, hence it's Rule.enforce in the docs. The following line of the error message tells you that it's not a valid property:

    * configuration.module.rules[0].use[0] has an unknown property 'enforce'. These properties are valid:
      object { loader?, options?, query? }
    

    It doesn't show use to be a valid property, because internally use, loaders and loader are treated as aliases.

    You'd have to put enforce on the entire rule.

    {
      test: /\.js$/i,
      enforce: "pre",
      include: SRC_ROOT,
      use: [
        {
          loader: "eslint-loader",
          options: {
            failOnError: true,
            failOnWarning: true,
          },
        },
        {
          loader: "babel-loader",
        }
      ],
    }
    

    But you don't really want babel-loader to be a pre-loader and that means you need to create two separate rules.

    rules: [
      {
        test: /\.js$/i,
        enforce: "pre",
        include: SRC_ROOT,
        use: [
          {
            loader: "eslint-loader",
            options: {
              failOnError: true,
              failOnWarning: true,
            },
          },
        ]
      },
      {
        test: /\.js$/i,
        include: SRC_ROOT,
        use: [
          {
            loader: "babel-loader"
          }
        ],
      }
    ]
    

    I've purposely kept the explicit version of the rules. You can indeed use some shortcuts, one of them being that if you only use a single loader, you may specify options directly on the rule. The options will be forwarded to the loader, which is probably why you thought that enforce is valid on a loader.