根据具体情况指定 webpack“mainFields”

Sas*_* K. 6 performance webpack tree-shaking webpack-4

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

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

我有一个应用程序可以包含数十个不同的 3rd 方软件包。用例是我想根据包的名称指定要使用的字段。例子:

  • 对于包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']
}
Run Code Online (Sandbox Code Playgroud)

mainFields必须被设置为main当前获取应用程序工作。这导致它总是拉入每个依赖项的 CommonJS 版本,而错过了 treeshaking。希望做这样的事情:

resolve: {
   foo: {
     mainFields: ['main']
   },
   bar: {
     mainFields: ['module'],
}
Run Code Online (Sandbox Code Playgroud)

foo被通过其绑定到我的应用main领域,封装bar被通过其捆绑在module现场。我意识到使用bar包进行 treeshaking 的好处,并且我不会使用foo包破坏应用程序(具有不正确的模块语法的模块字段)。

Tri*_*kar 4

实现此目的的一种方法是,resolve.mainFields您可以使用resolve.plugins选项并编写自己的自定义解析器,请参阅/sf/answers/2090141581/,因为通过使用自定义解析器,您可以以编程方式解析不同路径的不同路径模块

我将答案复制粘贴Ricardo Stuven's到这里

是的,这是可能的。为了避免歧义并更容易实现,我们将使用前缀哈希符号作为约定的标记:

需要(“#./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
      ]
    }
    // ...
};
Run Code Online (Sandbox Code Playgroud)