Webpack externals 配置详解:原理、libraryTarget 与多模块规范实践
本文深入解析 Webpack 中 externals 配置的原理与应用。通过配置 externals,可将 jQuery、Lodash 等第三方库排除在 bundle 之外,转而通过 CDN 或全局变量引入。文章详细讲解了 global、commonjs、commonjs2、amd 及 umd 等 libraryTarget 输出规范的区别,并结合实际代码演示如何正确配置以适配 Node.js 和浏览器环境,确保模块正确暴露与引用。
externals 配置基础与三步法
在常规项目开发中,我们通常会将第三方依赖库直接打包进最终的 bundle 文件中。例如,如下所示的打包结果可能包含了大量第三方代码。

若希望避免将第三方库打包进 bundle,以减小主包体积,则可以使用 externals 配置。官方文档对该功能的介绍相对简洁。
externals 配置项
官方文档的解释十分清晰:通过配置 externals,Webpack 可以忽略处理应用中特定的依赖库。配置完成后,代码中仍可通过 CMD、AMD 或 window/global 全局变量的方式访问这些依赖。
实现这一目标只需三个步骤——
1. 在 HTML 文件中通过 CDN 链接引入第三方库。
2. 在 Webpack 配置文件中设置 externals。
externals: {
jquery: "jQuery",
}
3. 在 JavaScript 代码中正常引用模块。
const $ = require("jquery");
$("#content").html("<h1>hello world</h1>");
externals 工作原理分析
完成上述配置后,我们即可自由使用 jQuery 等插件,且确保它们不会被打包进 bundle。那么 externals 是如何实现这一点的?接下来我们将通过分析 bundle 的源码来揭示其原理。

源码中的 /* 0 */ 和 __webpack_require__ 分别对应打包前的模块函数,此处不再赘述。关键可见 module.exports = jQuery,这表明 externals 中的 key 代表 require 的参数,而 value 代表其对应的全局变量。换言之,“当 require 的参数为 jquery 时,使用 jQuery 这个全局变量来引用它”。这种最简洁的 externals 配置方式属于默认的 global 模式,即在 window 对象上挂载一个全局变量,随后代码可直接使用该变量。具体流程为:在源码中使用 require('jquery') 后,将 jquery 加入 externals,生成 trunk.js。但在引入 trunk.js 前,必须先引入 jquery 库文件,该库文件会创建一个全局变量 jQuery。由于 trunk.js 中 externals 的 jquery 配置为 global 模式,因此实际上 trunk.js 在引入 jquery 时,会从全局变量中获取,即 module.export = jQuery。

当然,既然采用了 externals 方式,我们其实无需使用 require 引入,直接使用全局变量也是可行的。
jQuery("#content").html("<h1>hello world</h1>");
libraryTarget 模块化规范详解
如果注意到前文提到的 global 模式,或许你已经猜到,我们可以灵活使用不同的输出方式。若打包文件需在 Node.js 环境下运行,则需遵循 CommonJS 规范,配置方式如下。
externals: {
jquery: "commonjs2 jQuery",
}
打包后的结果将呈现如下形态。

此外,项目中还使用了 Lodash,同样希望将其从 bundle 中移除。此前的代码引用的是 npm 包。


现在的 externals 配置如下所示。
externals: {
jquery: "jQuery",
_: "lodash"
}

此时必须去掉 const 声明,否则会报错“lodash is not defined”。原因何在?因为 Lodash 的输出格式为 global,这里先保留疑问,我们先统一输出格式,添加 libraryTarget 字段。

该字段的作用是什么?
它用于指定输出文件的模块化规范。回顾前文配置的 commonjs jQuery,其运行环境为 Node.js。简而言之,最常用的模块化方案是 commonjs2 和 umd:前者适用于 Node 环境,后者适用于浏览器环境。具体包含以下几种规范:
"var" - 通过设置变量导出:var Library = xxx(默认值)
"this" - 通过设置 this 的属性导出:this["Library"] = xxx "commonjs" - 通过设置 exports 的属性导出:exports["Library"] = xxx "commonjs2" - 通过设置 module.exports 导出:module.exports = xxx "amd" - 导出到 AMD(可选命名,通过 library 选项设置名称) "umd" - 导出到 AMD、CommonJS2 或作为根属性

若出现上述错误,说明模块未正确输出。回到 externals,其核心作用是指定引用包时该包应遵循的模块化方式(common、root、amd 等)。这意味着打包时无需关心其具体输出格式。
externals: {
jquery: "jQuery",
lodash: {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_'
}
},
请注意,需将之前的配置覆盖,替换为以下 require 语句,因为在 externals 中我们将 Lodash 规范为 commonjs 规范。

多库配置与最终实践
这即为我们最初的代码,也就是未使用 externals 时的状态。由此可见,只需配置 externals 和 libraryTarget,其他业务逻辑代码无需任何改动。即便项目中还使用了 Echarts,也完全无需更改。

最终代码是 externals 配合 libraryTarget 共同作用的结果。若去掉 umd 配置,将会报错。

相应的源码如下所示。

这表明若不确定通过何种方式输出,应告知 Webpack 使用 umd 方式输出,即将 Lodash 暴露为在所有模块定义下均可运行的方式。它将在 CommonJS、AMD 环境下运行,或将模块导出到 global 下的变量。加上 umd 的源码如下。

由此可见,通过 require('lodash') 引入模块时,输出遵循 commonjs 规范。以下是最终配置。
entry: {
main: './src/index.js'
},
externals: {
jquery: "jQuery",
lodash: {
commonjs: 'lodash',
commonjs2: 'lodash',
amd: 'lodash',
root: '_'
}
},
output: {
filename: '[name].[chunkhash].js',
path: path.resolve(__dirname,'dist'),
libraryTarget: 'umd'
},
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
JS压缩后代码报错怎么调试?Source Map使用详解
2026-11-05 09:05:04
JS压缩会破坏代码逻辑吗?兼容性风险与测试建议
2026-11-03 17:13:03
Next.js 与 Vite、Create React App 的优缺点对比
2026-11-03 15:27:33
js文件加载失败或404错误的常见原因与排查
2026-11-03 10:38:55
前端项目打包生成 JS 文件的核心步骤完整记录
2026-10-31 21:04:46
