记录几种在webpack中使用第三方库文件的不同方法。
entry+CommonChunk
在进行webpack优化时,经常的一个操作是,将一些不会经常改动的第三方库文件从入口文件中分离出来,一方面是减少单个文件大小,另一方面是想充分利用浏览器缓存。在具体使用时会遇到这样4种情况:
在入口处新增一个vendor,并且使用CommonChunk打包一个vendor,这样会将vendor中的chunk从其他入口文件中分离出来。这也是最常见的处理办法。
entry: Object.assign({}, {'vendor': ['d3', 'd3-selection-multi']}, configEntry), new CommonsChunkPlugin({ name: 'vendor', filename: `js/vendor.js`, minChunks: Infinity }),
如果仅在入口增加vendor,而不是用CommonChunk进行提取,那么也会产生一个vendor.js,但是其他入口文件还是原样打包,就是依然是包含了vendor的js.
entry: Object.assign({}, {'vendor': ['d3', 'd3- selection-multi']}, configEntry),
另外我们经常的一个需求是,在入口文件中提取出公共文件common。此时如果有vendor是公用的,那么会被包含在common中,而不会成为单独的一个文件。这时情况是这样的。
entry: Object.assign({}, configEntry), new CommonsChunkPlugin({ name: 'common', filename: `js/common.js`, chunks: [...Object.keys(configEntry)], minChunks: 2 })
最后一种是,既需要有独立的vendor,又需要提取出其他入口文件中的公用代码common。如果加上了new ExtractTextPlugin(
css/[name].css
), 那么还会生成css/common.css
, 但是不会生成css/vendor.css
。entry: Object.assign({}, {'vendor': ['d3', 'd3- selection-multi']}, configEntry), new CommonsChunkPlugin({ name: 'vendor', filename: `js/vendor.js`, minChunks: Infinity }), new CommonsChunkPlugin({ name: 'common', filename: `js/common.js`, chunks: [...Object.keys(configEntry)], minChunks: 2 }), new ExtractTextPlugin(`css/[name].css`),
externals(外部的)
externals的使用场景是:“防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖”。
externals会与下面提到的libraryTarget
配合使用。它定义了,当我们通过script外链的形式引入资源时,我们在模块中引入这个包的方式。
webpack的output有一个选项是libraryTarget
,它定义了通过webpack打包之后输出的包是哪种形式的,通常用在我们对外提供模块时使用,比如umd,commonjs,amd等等。其中默认的是'var',var Library = xxx
,也就是说输出的包是以全局变量的形式被输出,像是被挂在window或者global下的。
[2018.03.16 update] 需要注意的是,libraryTarget
会影响不仅仅externals
的文件,其他chunks也会被影响。所以浏览器端推荐libraryTarget
用umd
或var
或默认。
output: {
libraryTarget: 'commonjs2',
},
externals:{
$: 'jQuery',
jquery: 'jQuery'
}
就会将page.js也以module.exports
输出整个代码。
module.exports =
webpackJsonp([3],{
/***/ 164:
/***/ (function(module, exports, __webpack_require__) {
"use strict";
__webpack_require__(165);
__webpack_require__(166);
....省略很多。。。
$.D3Map = function (options) {
return new D3Map(options);
};
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(167), __webpack_require__(10)], __WEBPACK_AMD_DEFINE_RESULT__ = (function (require, exports, module) {
return D3Map;
}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else {
window.D3Map = D3Map;
}
})(jQuery, d3);
/***/ }),
/***/ 167:
/***/ (function(module, exports) {
module.exports = require("window.jQuery");
/***/ }),
其中不同的libraryTarget
选项如下:
影响生成的bundle.js如下:
providePlugin(提供,供应)
是webpack官方的插件。它会将包暴露给所有模块,不会在其它多处模块中单独引入,当使用到的时候会自动load。
load的路径是相对于node_modules
中的。被引入的资源会被打入到bundle中。
$('item');
jQuery('item')
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
小结
总结起来就是externals 为了把库文件分离出去,providePlugin是为了在引入库文件时更方便简单。而CommonChunk也是为了分离文件。
参考
webpack中library和libraryTarget与externals的使用 webpack externals详解
Comments
注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。