Skip to content

mergeWithRules misjudges the rules.test equivalent #212

@RexSkz

Description

@RexSkz

The issue happens on the latest version of webpack-merge.

Brief Description

Assume we have two tests using object:

// match all .less files in Ant Design
{ and: [/\.less$/, /antd/] }

// match all .less files in Material UI
{ and: [/\.less$/, /@mui/] }

They should be converted using less-loader but with different options, the value of use[0].options.lessOptions should be:

// for Ant Design
{ modifyVars: { a: 1 } }

// for Material UI
{ modifyVars: { b: 2 } }

The merge result is not as expected, because webpack-merge uses the toString result to compare the test value:

const matches = rulesToMatch.every(
  (rule) => ao[rule]?.toString() === o[rule]?.toString()
);

The two results are both "[object Object]", causing the latter rule to be missing and its lessOptions to override the former one.

Full Example

Run this script:

const { mergeWithRules } = require('webpack-merge');

const a = {
  module: {
    rules: [
      {
        test: { and: [/\.less$/, /antd/] },
        use: [
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                modifyVars: { a: 1 },
              },
            },
          },
        ],
      },
    ],
  },
};

const b = {
  module: {
    rules: [
      {
        test: { and: [/\.less$/, /@mui/] },
        use: [
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                modifyVars: { b: 2 },
              },
            },
          },
        ],
      },
    ],
  },
};

const result = mergeWithRules({
  module: {
    rules: {
      test: 'match',
      use: {
        loader: 'match',
        options: 'replace',
      },
    },
  },
})(a, b);

console.log(JSON.stringify(result, (_, value) => (
  value instanceof RegExp ? value.toString() : value
), 2));

And we will get:

{
  "module": {
    "rules": [
      {
        "test": {
          "and": [
            "/\\.less$/",
            "/antd/"
          ]
        },
        "use": [
          {
            "loader": "less-loader",
            "options": {
              "lessOptions": {
                "modifyVars": {
                  "b": 2
                }
              }
            }
          }
        ]
      }
    ]
  }
}

Suggestion

Using the deep equal (e.g. _.isEqual in lodash) to compare the test value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions