12月18, 2017

关于webpack打包第三方库文件

记录几种在webpack中使用第三方库文件的不同方法。

entry+CommonChunk

在进行webpack优化时,经常的一个操作是,将一些不会经常改动的第三方库文件从入口文件中分离出来,一方面是减少单个文件大小,另一方面是想充分利用浏览器缓存。在具体使用时会遇到这样4种情况:

  • 在入口处新增一个vendor,并且使用CommonChunk打包一个vendor,这样会将vendor中的chunk从其他入口文件中分离出来。这也是最常见的处理办法。

    img

      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.

    img

      entry: Object.assign({}, {'vendor': ['d3', 'd3-    selection-multi']}, configEntry),
    
  • 另外我们经常的一个需求是,在入口文件中提取出公共文件common。此时如果有vendor是公用的,那么会被包含在common中,而不会成为单独的一个文件。这时情况是这样的。

    img

    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

    img

    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也会被影响。所以浏览器端推荐libraryTargetumdvar 或默认。

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选项如下:

img

影响生成的bundle.js如下:

img

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详解

本文链接:https://imjiaolong.cn/post/webpack-third-js.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。