【问题标题】:Webpack require expression externalWebpack 需要外部表达式
【发布时间】:2016-12-06 10:39:05
【问题描述】:

我有一个表达式 require 应该在运行时解决,但是对于这个简单的示例,我无法理解 webpack 配置:

import something from 'module';
import pkg from './package.json';
let a;

if (pkg.main) {
   a = require(pkg.main);
}

生成的构建应该包含 module,但在运行时还需要 ./package.jsonpkg.main 作为 commonjs 模块 - 换句话说,将它们从构建中排除。

到目前为止我的webpack.config.js

var webpack = require('webpack');

module.exports = {
  entry: './src/main.js',
  output: {
    filename: '[name].js',
    path: './build'
  },
  target: 'node-webkit',
  plugins: [
    new webpack.ExternalsPlugin('commonjs', './package.json')
  ],
  module: {
    noParse: /\.min\.js/,
    exprContextRegExp: /$^/,
    exprContextCritical: false,
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      }
    ]
  }
};

现在发生的是 pkg.main 的 require 导致 webpackMissingModule 异常,如果我删除 exprContextRegExp,则 require 将使用上下文。

感谢您的帮助

【问题讨论】:

    标签: javascript node.js webpack require commonjs


    【解决方案1】:

    对于任何想知道的人:您可以使用此插件解决它:

    function() {
      this.parser.plugin('call require', function(expr) {
        if (expr.arguments.length !== 1) {
          return;
        }
    
        const param = this.evaluateExpression(expr.arguments[0]);
        if (!param.isString() && !param.isConditional()) {
          return true;
        }
      });
    }
    

    webpack 无法解决的任何问题都将保持原样。

    【讨论】:

    • 好主意。你有一个关于如何实现上述功能的例子吗?
    【解决方案2】:

    更新:使用 NPM 包

    安装它:yarn add webpack-ignore-dynamic-require

    启用它

    // webpack.config.js
    
    const IgnoreDynamicRequire = require('webpack-ignore-dynamic-require');
    
    module.exports = {
      // ...
      plugins: [
        new IgnoreDynamicRequire()
      ]
    }
    

    原答案:自制

    为了捆绑服务器应用程序,我需要它,因为它使用require 来加载本地 JSON 文件。

    基于self answer from Patrik Holčák,我能够为 Webpack 4 创建一个插件。它可能适用于 Webpack 5。

    class IgnoreDynamicRequire {
      apply(compiler) {
        compiler.hooks.normalModuleFactory.tap('IgnoreDynamicRequire', factory => {
          factory.hooks.parser.for('javascript/auto').tap('IgnoreDynamicRequire', (parser, options) => {
            parser.hooks.call.for('require').tap('IgnoreDynamicRequire', expression => {
              // This is a SyncBailHook, so returning anything stops the parser, and nothing allows to continue
              if (expression.arguments.length !== 1 || expression.arguments[0].type === 'Literal') {
                return
              }
              const arg = parser.evaluateExpression(expression.arguments[0])
              if (!arg.isString() && !arg.isConditional()) {
                return true;
              }
            });
          });
        });
      }
    }
    

    这比上一个答案要复杂得多,但我们需要访问parser object。之后,只需将其包含在您的 plugins 数组中:

    plugins: [
        new IgnoreDynamicRequire()
      ]
    

    所有未解析为字符串的require 调用都保持原样。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多