基本原理

手动分包的总体思路是:

  1. 先单独的打包公共模块

5-5. 手动分包😪 - 图1
单独打包公共模块
公共模块会被打包成为动态链接库(dll Dynamic Link Library),并生成资源清单

  1. 根据入口模块进行正常打包

打包时,如果发现模块中使用了资源清单中描述的模块,则不会形成下面的代码结构:

  1. //源码,入口文件index.js
  2. import $ from "jquery"
  3. import _ from "lodash"
  4. _.isArray($(".red"));

由于资源清单中包含jquery和lodash两个模块,因此打包结果的大致格式是:

  1. (function(modules){
  2. //...
  3. })({
  4. // index.js文件的打包结果并没有变化
  5. "./src/index.js":
  6. function(module, exports, __webpack_require__){
  7. var $ = __webpack_require__("./node_modules/jquery/index.js")
  8. var _ = __webpack_require__("./node_modules/lodash/index.js")
  9. _.isArray($(".red"));
  10. },
  11. // 由于资源清单中存在,jquery的代码并不会出现在这里
  12. "./node_modules/jquery/index.js":
  13. function(module, exports, __webpack_require__){
  14. module.exports = jquery;
  15. },
  16. // 由于资源清单中存在,lodash的代码并不会出现在这里
  17. "./node_modules/lodash/index.js":
  18. function(module, exports, __webpack_require__){
  19. module.exports = lodash;
  20. }
  21. })

打包公共模块

打包公共模块是一个独立的打包过程
首先在package.json中:

  1. "scripts": {
  2. "dev": "webpack",
  3. "dll": "webpack --config webpack.dll.config.js"
  4. },
  1. 单独打包公共模块,暴露变量名

    1. // webpack.dll.config.js
    2. module.exports = {
    3. mode: "production",
    4. entry: {
    5. jquery: ["jquery"], //必须是数组
    6. lodash: ["lodash"]
    7. },
    8. output: {
    9. filename: "dll/[name].js",
    10. library: "[name]" //每个bundle暴露的全局变量名
    11. //或者libraryTarget:"var" 全局形式来暴露
    12. }
    13. };
  2. 利用DllPlugin生成资源清单

    1. // webpack.dll.config.js
    2. module.exports = {
    3. plugins: [
    4. new webpack.DllPlugin({
    5. path: path.resolve(__dirname, "dll", "[name].manifest.json"), //资源清单的保存位置
    6. name: "[name]"//资源清单中,暴露的变量名
    7. })
    8. ]
    9. };

    运行后,即可完成公共模块打包

    使用公共模块

  3. 在页面中手动引入公共模块

    1. <script src="./dll/jquery.js"></script>
    2. <script src="./dll/lodash.js"></script>
  4. 重新设置clean-webpack-plugin

如果使用了插件clean-webpack-plugin,为了避免它把公共模块清除,需要做出以下配置

  1. new CleanWebpackPlugin({
  2. // 要清除的文件或目录
  3. // 排除掉dll目录本身和它里面的文件
  4. cleanOnceBeforeBuildPatterns: ["**/*", '!dll', '!dll/*']
  5. })

目录和文件的匹配规则使用的是globbing patterns

  1. 使用DllReferencePlugin控制打包结果

webpack.config:

  1. module.exports = {
  2. plugins:[
  3. new webpack.DllReferencePlugin({
  4. manifest: require("./dll/jquery.manifest.json")
  5. }),
  6. new webpack.DllReferencePlugin({
  7. manifest: require("./dll/lodash.manifest.json")
  8. })
  9. ]
  10. }

总结

手动打包的过程

  1. 开启output.library暴露公共模块
  2. 用DllPlugin创建资源清单
  3. 用DllReferencePlugin使用资源清单

手动打包的注意事项

  1. 资源清单不参与运行,可以不放到打包目录中
  2. 记得手动引入公共JS,以及避免被删除
  3. 不要对小型的公共JS库使用

优点

  1. 极大提升自身模块的打包速度
  2. 极大的缩小了自身文件体积
  3. 有利于浏览器缓存第三方库的公共代码

缺点

  1. 使用非常繁琐
  2. 如果第三方库中包含重复代码,则效果不太理想