外部扩展(Externals)配置
什么是外部扩展(Externals)
Webpack的外部扩展(Externals)配置允许开发者从输出的bundle中排除某些依赖,这些依赖会在运行时(runtime)从外部获取。这种方式特别适合处理那些通过CDN引入的库,或者那些已经被其他方式引入到运行环境的依赖。
// webpack.config.js
module.exports = {
externals: {
jquery: 'jQuery'
}
};
外部扩展的基本用法
配置externals最常见的方式是使用对象语法。键(key)表示要排除的模块名称,值(value)表示在运行时应该使用的全局变量。
externals: {
lodash: '_',
react: 'React',
'react-dom': 'ReactDOM'
}
当代码中require或import这些模块时,webpack不会将它们打包,而是保留为外部依赖:
import _ from 'lodash'; // 实际会使用全局的_变量
外部扩展的多种配置形式
字符串形式
最简单的形式是直接指定全局变量名:
externals: {
jquery: 'jQuery'
}
数组形式
当需要同时指定模块名称和全局变量时:
externals: {
subtract: ['./math', 'subtract']
}
对象形式
提供更细粒度的控制:
externals: {
react: {
root: 'React',
commonjs: 'react',
commonjs2: 'react',
amd: 'react'
}
}
函数形式
最灵活的方式,可以自定义处理逻辑:
externals: [
function(context, request, callback) {
if (/^yourregex$/.test(request)) {
return callback(null, 'commonjs ' + request);
}
callback();
}
]
不同模块系统中的外部扩展
CommonJS外部扩展
externals: {
fs: 'commonjs fs',
path: 'commonjs path'
}
AMD外部扩展
externals: {
jquery: {
amd: 'jQuery'
}
}
UMD外部扩展
externals: {
moment: {
root: 'moment',
commonjs: 'moment',
commonjs2: 'moment',
amd: 'moment'
}
}
实际应用场景
排除CDN引入的库
<!-- index.html -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
// webpack.config.js
externals: {
jquery: 'jQuery'
}
微前端架构中的共享依赖
在微前端架构中,主应用和子应用可以共享某些库:
// 子应用的webpack配置
externals: {
react: 'react',
'react-dom': 'reactDOM'
}
Node.js环境中的内置模块
构建Node.js应用时,可以排除内置模块:
externals: {
fs: 'commonjs fs',
path: 'commonjs path'
}
高级配置技巧
正则表达式匹配
externals: [
/^[a-z\-0-9]+$/ // 排除所有符合该模式的模块
]
条件排除
externals: [
function({ context, request }, callback) {
if (request.includes('node_modules')) {
return callback(null, `commonjs ${request}`);
}
callback();
}
]
动态生成外部扩展
const nodeExternals = require('webpack-node-externals');
module.exports = {
externals: [nodeExternals()],
// 其他配置...
};
常见问题与解决方案
全局变量未定义错误
确保外部依赖确实在运行时可用:
externals: {
jquery: {
root: 'jQuery',
commonjs: 'jquery',
commonjs2: 'jquery',
amd: 'jquery'
}
}
与DLLPlugin的配合使用
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
},
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./manifest.json')
})
]
TypeScript中的类型定义
需要同时安装类型定义包:
npm install --save-dev @types/jquery
性能优化考虑
合理使用externals可以显著减少打包体积:
// 使用前
asset main.js 1.5 MiB [emitted] (name: main)
// 使用后
asset main.js 350 KiB [emitted] (name: main)
与其他配置的协同
与output.libraryTarget配合
output: {
libraryTarget: 'umd'
},
externals: {
react: 'react'
}
与SplitChunksPlugin的关系
externals配置的模块不会进入split chunks的优化流程。
测试与验证
验证externals配置是否生效:
// 打包后检查bundle
// 应该看不到被排除模块的代码
使用webpack-bundle-analyzer进行分析:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [new BundleAnalyzerPlugin()]
};
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:动态导入与懒加载实现