视情况指定webpack“ mainFields”

时间:2019-07-23 11:04:30

标签: performance webpack webpack-4 tree-shaking

Webpack具有resolve.mainFields配置:https://webpack.js.org/configuration/resolve/#resolvemainfields

这可以控制应将哪个package.json字段用作入口点。

我有一个应用程序,可以提取数十种不同的第三方包装。用例是我想根据包的名称指定要使用的字段。示例:

  • 对于软件包foo,请使用main中的node_modules/foo/package.json字段
  • 对于软件包bar,请使用module中的node_modules/bar/package.json字段

我所依赖的某些软件包未正确捆绑,module字段指向的代码不遵循以下规则:https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md批量将webpack配置更改为:

resolve: {
  mainFields: ['module']
}

mainFields必须设置为main,才能使该应用正常运行。这导致它总是拉入每个依赖项的CommonJS版本,而错过树状交换。希望做这样的事情:

resolve: {
   foo: {
     mainFields: ['main']
   },
   bar: {
     mainFields: ['module'],
}

foo通过其main字段捆绑到我的应用程序中,而包bar通过其module字段捆绑到我的应用程序中。我意识到使用bar软件包进行树状交换的好处,并且我不会使用foo软件包破坏应用程序(因为模块字段的模块语法不正确)。

1 个答案:

答案 0 :(得分:0)

实现此目标的一种方法是,不使用resolve.mainFields,而是可以使用resolve.plugins选项并编写自己的自定义解析器,请参见https://stackoverflow.com/a/29859165/6455628,因为通过使用自定义解析器,您可以以编程方式为不同的模块解决不同的路径

我正在复制粘贴Ricardo Stuven's的答案

是的,有可能。为避免歧义并简化实施, 我们将使用前缀哈希符号作为您的约定的标记:

require(“#。/ components / SettingsPanel”);

然后将其添加到您的配置文件中(当然,您可以重构 稍后):

var webpack = require('webpack');
var path = require('path');

var MyConventionResolver = {
  apply: function(resolver) {
    resolver.plugin('module', function(request, callback) {
      if (request.request[0] === '#') {
        var req = request.request.substr(1);
        var obj = {
          path: request.path,
          request: req + '/' + path.basename(req) + '.js',
          query: request.query,
          directory: request.directory
        };
        this.doResolve(['file'], obj, callback);
      }
      else {
        callback();
      }
    });
  }
};


module.exports = {
    resolve: {
      plugins: [
        MyConventionResolver
      ]
    }
    // ...
};