当为多个入口时,且每个入口都需要引入jQuery,那吗最后生成的js中会有多个jQuery,这样会导致像jQuery这种公共模块会被多次打包,可也以让这些公共模块分包分出来,形成单独的包,

基本原理

手动分包的总体思路是:

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

image.png

公共模块会被打包成为动态链接库(dll Dynamic Link Library),并生成资源清单

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

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

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

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

  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. })

打包公共模块

打包公共模块是一个独立的打包过程

  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]" // 暴露变量
    11. }
    12. };
  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. };

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

使用公共模块

  1. 在页面中手动引入公共模块 // 之所以导入公共模块是因为打包公共模块的第一步暴露的变量名,而页面引用就是将此变量暴露在全局

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

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

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

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

  1. 使用DllReferencePlugin控制打包结果
    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. }
    清单文件是如何运行的,当webpack读取到导入到jquery时会将其转换为id(id为:./node_modules/jquery/dist/jquery.js),而 DllReferencePlugin的配置项中可以看出将导入清单文件的(当导入json文件时回忆对象的形式导入)这个清单的json中有jQuery的清单信息,webpack就不会打包jQuery
    jQuery的清单信息 如下图jQuery导入id 与清单配置中的jQuery的导入的id一样,webpack会走这个文件
    image.png

总结

手动打包的过程

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

手动打包的注意事项

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

优点

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

缺点

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