代码之家  ›  专栏  ›  技术社区  ›  axel

PeerDepsExternalsPlugin在Webpack5升级后破坏了构建,如何修复?

  •  0
  • axel  · 技术社区  · 4 年前

    我将我的react应用程序项目升级到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] }
    

    有什么想法吗?谢谢

    0 回复  |  直到 4 年前
        1
  •  1
  •   Zaxvo    4 年前

    我遇到了同样的问题,事实证明 an open 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');