PeerDepsExternalsPlugin прерывает сборку после обновления Webpack5, как это исправить?

#javascript #node.js #reactjs #webpack #plugins

#javascript #node.js #reactjs #webpack #Плагины

Вопрос:

Я обновил свой проект react app до Webpack5. При обновлении я занимался не только Webpack, но и всеми его плагинами, пытаясь проверять их один за другим, чтобы сталкиваться с меньшим количеством проблем, насколько это возможно. Дело в том, что у меня почти сразу возникла эта проблема (которая не возникает, если я удаляю new PeerDepsExternalsPlugin(), из списка плагинов Webpack. Но любое обновление было выполнено в библиотеке peer-deps-externals-webpack-plugin все еще на версии «^ 1.0.4»

Это основная конфигурация webpack:

 module: {
    rules: [
      {
        test: /.(js|jsx|tsx)(?.*)?$/,
        exclude: [/node_modules/],
        use: 'babel-loader'
      },
      {
        test: /.tsx?$/,
        exclude: [/node_modules/],
        use: 'ts-loader'
      },
      {
        include: path.resolve(__dirname, assetsPath),
        use: [
          {
            loader: 'file-loader',
            options: {
              context: path.resolve(__dirname, 'PRIVATE_PATH'),
              name: '[path][name].[ext]?hash=[hash:base64:5]'
            }
          }
        ]
      }
    ].filter(Boolean)
  },
  optimization: {
    minimizer: [
      new TerserPlugin({
        test: /.min.js$/
      })
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      ASSETS_PATH_PREFIX: `"${getFullAssetPathPrefix()}"`
    }),
    new PeerDepsExternalsPlugin(),
    ...extraPlugins,
    new LintFilename(
      /^(?!(icon|bg|img)-(?!(.*[_A-Z]|[s]))).*(jpe?g|png|svg)$/,
      path.resolve(__dirname, 'assets/img'),
      'image'
    ),
    new CopyPlugin({
      patterns: [
        {
          from: path.resolve(__dirname, 'lib/**/*.d.ts'),
          to: 'types'
        }
      ]
    })
  ]
 

И это ошибка сборки:

 $ webpack --mode production
$ cross-env BABEL_ENV=es babel lib --extensions .js,.jsx,.ts,.tsx --out-dir dist/es
[build:js:frontend-es] Successfully compiled 125 files with Babel (4423ms).
[build:js:frontend-es] yarn run build:js:frontend-es exited with code 0
[build:js:frontend] internal/crypto/hash.js:84
[build:js:frontend]     throw new ERR_INVALID_ARG_TYPE(
[build:js:frontend]     ^
[build:js:frontend]
[build:js:frontend] TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received undefined
[build:js:frontend]     at Hash.update (internal/crypto/hash.js:84:11)
[build:js:frontend]     at BulkUpdateDecorator.update (/project/node_modules/webpack/lib/util/createHash.js:49:14)
[build:js:frontend]     at ExternalModule.updateHash (/project/node_modules/webpack/lib/ExternalModule.js:465:8)
[build:js:frontend]     at Compilation.createModuleHashes (/project/node_modules/webpack/lib/Compilation.js:2726:12)
[build:js:frontend]     at /project/node_modules/webpack/lib/Compilation.js:2064:11
[build:js:frontend]     at eval (eval at create (/project/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
[build:js:frontend]     at /project/node_modules/webpack/lib/optimize/ModuleConcatenationPlugin.js:449:32
[build:js:frontend]     at processTicksAndRejections (internal/process/task_queues.js:75:11) {
[build:js:frontend]   code: 'ERR_INVALID_ARG_TYPE'
[build:js:frontend] }
 

Есть идеи? Спасибо

Ответ №1:

Я столкнулся с той же проблемой, оказывается, в репозитории плагина есть открытый PR.

Тем временем я стащил код из этого PR и сохранил его как external-plugin.js в корневом каталоге моего проекта.

 'use strict';

const ExternalModuleFactoryPlugin = require('webpack/lib/ExternalModuleFactoryPlugin');

class PeerDepsExternalsPlugin {
  apply(compiler) {
    const peerDependencies = getPeerDependencies();

    // webpack 5 
    if (typeof compiler.options.output.library === 'object') {
      compiler.hooks.compile.tap('PeerDepsExternalsPlugin', ({ normalModuleFactory }) => {
        new ExternalModuleFactoryPlugin(
          compiler.options.output.library.type,
          peerDependencies
        ).apply(normalModuleFactory);
      });
    }
    // webpack 4 
    else {
      compiler.hooks.compile.tap('compile', params => {
        new ExternalModuleFactoryPlugin(
          compiler.options.output.libraryTarget,
          peerDependencies
        ).apply(params.normalModuleFactory);
      });
    }
  }
}

function getPeerDependencies() {
  try {
    const { resolve } = require('path');
    const pkg = require(resolve(process.cwd(), 'package.json'));
    return Object.keys(pkg.peerDependencies);
  } catch(err) {
    return [];
  }
}

module.exports = PeerDepsExternalsPlugin;
 

а затем в моей конфигурации webpack я изменил импорт, чтобы использовать этот файл вместо пакета из npm:

 const PeerDepsExternalsPlugin = require('./external-plugin');
 

Комментарии:

1. красавица, спасибо, что поделилась!