Webpack需要外部表达式

时间:2016-08-01 11:09:31

标签: javascript node.js webpack require commonjs

我有一个表达式需要哪个应该在运行时得到解决但是我无法理解这个简单的例子:

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需要导致webpackMissingModule异常,如果我删除exprContextRegExp,则需要使用上下文。

感谢您的帮助

2 个答案:

答案 0 :(得分: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无法解决的任何问题都将保留原样。

答案 1 :(得分:1)

更新:使用 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 调用都保持原样。