neutrinojs / neutrino

Create and build modern JavaScript projects with zero initial configuration.
https://neutrinojs.org
Mozilla Public License 2.0
3.95k stars 214 forks source link

Cannot use same babel plugin multiple times #1646

Closed BenJeau closed 7 months ago

BenJeau commented 3 years ago

Bug

Ex: .neutrinorc.js

const react = require("@neutrinojs/react");

module.exports = {
  options: {
    root: __dirname,
  },
  use: [
    react({
      babel: {
        plugins: [
          [
            "import",
            {
              libraryName: "antd",
              libraryDirectory: "es",
              style: true,
            },
            "antd",
          ],
          [
            "import",
            {
              libraryName: "validator",
              libraryDirectory: "es/lib",
              camel2DashComponentName: false,
            },
            "validator",
          ],
        ],
      },
    }),
  ],
};

and the output from neutrino --inspect --mode development (only the relevant babel part):

{
  module: {
    rules: [
      {
        use: [
          {
            options: {
              cacheDirectory: true,
              babelrc: false,
              configFile: false,
              plugins: [
                '/frontend/node_modules/@babel/plugin-syntax-dynamic-import/lib/index.js',
                '/frontend/node_modules/react-hot-loader/babel.js',
                [
                  '/frontend/node_modules/babel-plugin-import/lib/index.js',
                  {
                    libraryName: 'validator',
                    libraryDirectory: 'es/lib',
                    camel2DashComponentName: false
                  }
                ]
              ]
            }
          }
        ]
      }
    ]
  }
}

It seems like its ignoring the third element in the plugins array? How would someone using neutrinojs use the same babel plugin multiple times?

elpddev commented 3 years ago

From what it looks like, the react preset uses babelMerge https://github.com/neutrinojs/neutrino/blob/cdb08011793d4a6eb4509655a1fab2906a7c4356/packages/react/index.js#L21

babelMerge specifically looks for duplicates in the plugins array https://github.com/neutrinojs/babel-merge/blob/d24260a025d6416a4cd52e72a8a024f4f403de2f/src/index.js#L13

 return [...source, ...overrides].reduce((reduction, override) => {
    const overrideName = resolve(Array.isArray(override) ? override[0] : override);
    const overrideOptions = Array.isArray(override) ? override[1] : {};
    const base = reduction.find((base) => {
      const baseName = resolve(Array.isArray(base) ? base[0] : base);
      return baseName === overrideName || baseName.includes(overrideName);
    });

    const index = reduction.includes(base) ? reduction.indexOf(base) : reduction.length;
    const baseName = base ? resolve(Array.isArray(base) ? base[0] : base) : overrideName;
    const baseOptions = Array.isArray(base) ? base[1] : {};
    const options = merge(baseOptions, overrideOptions, {
      arrayMerge,
      isMergeableObject: value => Array.isArray(value),
      ...deepmergeOpts
    });

    reduction[index] = Object.keys(options).length ? [baseName, options] : baseName;

It seems there is already an open issue to support the name third parameter in @neutrinojs/babel-merge https://github.com/neutrinojs/babel-merge/issues/35 Maybe the logic to identify the baseName could be adapted to support the third parameter form

BenJeau commented 3 years ago

Oh sorry, wasn't sure where this originated from. Thanks for the info and quick code explanation! I'll look at potentially making a fix/PR for @neutrinojs/babel-merge if I have time and it's only related to this section