该文章默认以 webpack-chain 为基础进行配置

因本文章会默认跳过 webpack-externals 基础部分, 若不了解基础的朋友可以查看此文章

场景 1

我们的项目在本地开发时分别引用了 gsap 与 jquery, 但是在线上环境中, 这些外部依赖的文件是统一使用 script 标签引用 cdnjs 上的, 所以在打包时我们不需要将这俩文件打包, 那么此时我们可以进行以下配置

config.externals([
  {
    jquery: "root jQuery",
    gsap: "root gsap"
  }
]);

配置非常简单, 我们只需要将 jquery 使用 root 关键字指名, 在打包时我们代码中使用的 jquery 是从全局变量中来的. gsap 也是同理

场景 2

我们开发了一个插件 A, 并且该插件同时引用了插件 B, 且此时作为团队开发的一部分, 插件 B 可能在页面中被多次调用, 如果每个插件都把 B 插件打包, 那么将会照成代码的浪费, 因此我们会考虑只打包 A 插件的代码, 而 A 插件所依赖的 B 插件, 着通过 externals 声明其引用位置

config.externals([
  (context, request, callback) => {
    //  我们可以判断如果import的文件来自于 vendor 目录, 那么在打包时候, 我们排除vendor下的这些文件
    //  同时告诉webpack我们代码中使用到的vendor目录下的插件, 将通过commonjs2 方式在其他页面中引用
    if (/\/vendor\//.test(request)) {
      return callback(null, `commonjs2 ${request.replace(/\.+\//, "@src/")}`);
    }
    callback();
  }
]);

这里注意下关键字@src, 这是 webpack 提供的 alias, 因引用的层级各不同, 我们需要按以下配置, 配置@src/对应的 alias

config.resolve.alias.set("@src", path.resolve(path.dirname(__dirname), "src"));

场景 3

在场景 2 的基础上, 我们还想更进一步处理, 如我们只想过滤部分 vendor 下的插件, 而其他 vendor 下的插件, 我们还是想一并打包到项目中.

假设 vendor 目录下, 分别有插件 A,B,C 我们只需要过滤 C 不被打包

那么配置将会是如下

config.externals([
  (context, request, callback) => {
    //  下面这行是用正则判断, import 的文件是来自于 插件C, 若是插件C, 我们将其声明为root(外部library引用)
    if (/\/vendor\/C/.test(request)) {
      //  注意这里的 window.C 一定要跟 C 插件导出时的output.library命名一样, 并且是使用umd方式导出的C插件, 下面会提到
      return callback(null, `root window.C`);
    }
    callback();
  }
]);

若我们这样写有个要求, 就是 C 插件必须是以 umd 方式导出, 这样不管是在开发环境还是线上环境, 通过 import 引用还是通过 script 引用, 都能正常运作

那么插件 C 的 output 配置因如下

//  这行配置一共有两个关键点, 1.是通过umd方式导出, 2.是导出的library名字为C, 这样我们就可以在线上环境中的window.C中使用该插件
config.output.libraryTarget("umd").library("C");

场景 4

我们开发了一个插件 A, 该插件依赖于 jquery 插件, 但是不想让该插件打包时包含 jquery, 并且还同时想让该插件无论是通过 import 引用还是通过 script 引用都能正常使用. 那么我们需要在 A 插件进行以下配置

config.externals({
  jquery: {
    commonjs2: "jquery",
    commonjs: "jquery",
    root: "jQuery"
  }
});

以上配置也比较好理解, 若是 commonjs2 和 commonjs 的环境, 则告诉 webpack 通过 import 引入 jquery, 如果是线上环境则告诉 webpack 使用 window.jQuery, 这样配置能保证我们写的插件 A 同时能在各种环境中运行