Using webpack-merge to prepend loaders to a rules `use` array

6.1k views Asked by At

I use webpack-merge to merge my webpack config files for dev and prod environments. To extract CSS in prod mode, I use the mini-css-extract-plugin. According to its documentation, I use it in place of the style-loader, which is only used during development. At this moment, my webpack config for CSS blocks looks like this:

// webpack.common.js
{
  test: /\.(sa|sc|c)ss$/,
  use: [
    process.env.NODE_ENV === `production` ? MiniCssExtractPlugin.loader : `style-loader`,
    `css-loader`,
    `postcss-loader`,
    `sass-loader`
  ]
}

This works, but since I am using webpack-merge, I want to avoid this kind of logic in my common config file. Now, I have tried to split this up like so and have webpack-merge merge the various loaders:

// webpack.common.js
{
  test: /\.(sa|sc|c)ss$/,
  use: [
    `css-loader`,
    `postcss-loader`,
    `sass-loader`
  ]
}

// webpack.dev.js
{
  test: /\.(sa|sc|c)ss$/,
  use: [
    `style-loader`,
    // webpack-merge should prepend all loaders from `webpack.common.js`
  ]
}

// webpack.prod.js
{
  test: /\.(sa|sc|c)ss$/,
  use: [
    MiniCssExtractPlugin.loader,
    // webpack-merge should prepend all loaders from `webpack.common.js`
  ]
}

Using the basic merge fn, the use arrays doesnt get merged, but replaced, which ofc leads to an error: ModuleParseError: Module parse failed: You may need an appropriate loader to handle this file type.

So I tried to use merge.smartStrategy({ 'module.rules.use': 'prepend' })(), but I get an error: TypeError: this[MODULE_TYPE] is not a function. Is there something I am missing or is this simply not possible?

2

There are 2 answers

0
jellySWATy On BEST ANSWER

it's a little update. In modern versions of webpack you should use mergeWithRules. In that case it looks like this

// webpack.common.js
{
  test: /\.(sa|sc|c)ss$/,
  use: [
    `postcss-loader`,
    `sass-loader`
  ]
}

// webpack.dev.js
{
  test: /\.(sa|sc|c)ss$/,
  use: [
    "style-loader"
  ]
}

mergeWithRules({
  module: {
    rules: {
      test: "match",
      use: "prepend",
    },
  },
})(common, dev);
1
r0skar On

While splitting up my webpack config, I have forgotten to include the MiniCssExtractPlugin in the plugins section of my prod. config file.

Everything works as expected using merge.smartStrategy({ 'module.rules.use': 'prepend' })().