当前位置: 首页>前端>正文

55 npm run serve 和 npm run build 的分包策略

前言

这里我们来看一下 vue 这边 打包的时候的一些 拆分包的一些策略

我们经常会使用到 npm run build 进行服务的打包

然后 打包出来的情况, 可能如下, 可以看到 chunk-vendors 是进行了包的拆分, 我们这里就是 来看一下 这里 npm run build 的时候的, 一个分包的策略

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包,第1张

 

 

测试配置

在 vue.config.js 中配置 webpack 打包配置如下

对于 node_modules 下面的所有的依赖, 限定分包策略为 最小10kb, 最大10kb

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    optimization: {
      splitChunks: {
        cacheGroups: {
          defaultVendors: {
            test: /[\/]node_modules[\/]/,
            priority: 10,
            minSize: 10000,
            maxSize: 10000,
          },
          default: {
            chunks: "all",
            minSize: 10000,
            maxSize: 10000,
          },
        }
      }
    }
  }
})

 

 

chunk-vendors 分组的分包策略

首先超过 maxSize 的包会被单独拧出来形成一个单独的包, 不管他的大小多大

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_02,第2张

 

然后其次就是 具体的分包的处理了

如果当前 js 添加到当前包未超过 maxSize, 继续迭代下一个

如果当前 js 太小了, 则重新放回队列, 继续迭代下一个

接下来就是 这里定义的一个拆包的算法了,  这里不细说, 我们也不关注具体的拆分的细节

循环结束, 拆分包的过程就结束了, 拆分成了 n 个小包

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_03,第3张

 

 

拆分的过程调试如下

比如这里 vue.runtime.esm.js 包 268kb, 超过了配置的 10kb 的大小, 直接拧出来形成一个单独的 chunk

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_04,第4张

 

接下来 32 个 js, 合计 15kb, 形成一个 chunk

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_05,第5张

 

接下来也是 32 个 js 形成一个 chunk

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包_06,第6张

 

接下来是 剩余的 14 个 js 形成一个 chunk

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包_07,第7张

 

当前 chunk 的命名方式是获取 第一个元素的名称 和 最后一个元素名称 的最大公共部分

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_08,第8张

 

然后这里是在 compilation 中新增各个 chunk 的地方

chunk 的的名称后缀是根据 group 的名称进行 hash 生成的

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_09,第9张

 

然后 如图, 就是编译结果的 chunk-vendors-7a6313df 文件, 里面包含了 32 个 js 文件, 然后 minify 压缩之后, 只有 6kb

要看各个 chunk-vendors 中包含了那些 js, 只能通过运行时调试查看

然后 chunk-vendors-2afcb3e6 这个显然就是 vue.runtime.esm.js 文件, minifiy 压缩之后, 只有 70kb

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_10,第10张

 

示例项目中各个 module 大小, 以及各个 chunk 对应的 module 列表如下 excel

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_11,第11张

 

 

npm run serve 中的 app.js 中默认情况下的 chunk 的拆分

app.js 的拆分分了很多种情况, 这里 我们先来看下 默认的行为

vue.config.js 配置如下

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    optimization: {
      splitChunks: {
        cacheGroups: {
          defaultVendors: {
            test: /[\/]node_modules[\/]/,
            name(module) {
              return "defaultVendors"
            },
            // chunks: "all",
            // minChunks: 3,
            priority: 10,
            // minSize: 10000,
            maxSize: 10000,
          },
          // default: {
          //   chunks: "all",
          //   name(module) {
          //     return "app11"
          //   },
          //   // filename: "app112"
          //   // priority: -10,
          //   // minSize: 10000,
          //   maxSize: 10000,
          // },
        }
      }
    }
  }
})

 

增加路由配置文件如下, 如下配置了三个路由

import Vue from "vue";
import Router from "vue-router";

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: () => import('../components/snake/Game.vue')
    }, {
      path: '/HelloWorld',
      name: 'HelloWorld',
      component: () => import('../components/HelloWorld')
    }, {
      path: '/AsyncQueue',
      name: 'AsyncQueue',
      component: () => import('../components/AsyncQueue.vue')
    }
  ]
})

 

编译之后的生成的 js 相关的目录结构如下, 我们这里关注 app.js 相关的

即 app.js 和 src_components_xxx 相关的三个文件, 其他的为 node_modules 编译之后生成的项目文件

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_12,第12张

 

然后我们看一下 app.js 中 chunk 的拆分

在 visit “src\router\index.js” 的时候, 发现了三个 import(), 然后 采集为 blocks

然后 这里单独拆分出来, 成为单独的 chunk

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_13,第13张

 

该 chunk 里面没有保存上下文的任何信息, 上下文的信息是保存在 chunkGroup 中的, 后面对 chunk 和 chunkGroup 进行了关联

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_14,第14张

 

为目标 chunk 生成 chunkName 的地方是在 NamedChunkIdsPlugin.js 中, 从 chunkGroup 中相关数据中可以拿到目标 chunk 是属于哪一个文件的

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包_15,第15张

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_16,第16张

 

 

npm run build 中的 app.js 中默认情况下的 chunk 的拆分

整体的流程 和 上面 npm run serve 中的 app.js 的拆分情况如下

计算 chunk 的 id, 名称如下

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包_17,第17张

 

使用 numberHash 进行计算, 如果重复了, 就重新计算

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_18,第18张

 

整体来说, chunk 名称和其内容没有什么较为明显的关联

因此, 只能通过 文件内容, 来定位具体的业务组件是在哪一个文件中了

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_19,第19张

 

但是可以通过 app.js 来进行一个粗略的查找, entryPoint 编号为 3208

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_20,第20张

 

这里便是整个路由, 这两批可以看到 具体的路由信息, 以及组件信息, 比如 “/HelloWorld” 对应于组件 575

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_21,第21张

 

 

app.js 的手动拆包配置

和上面 chunk-vendors 的拆包的配置类似, app.js 相关, 也是可以手动配置 拆包

配置 vue.config.js 的配置如下, 其中 default 下面的配置对应的是 app.js 的配置

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    optimization: {
      splitChunks: {
        cacheGroups: {
          defaultVendors: {
            test: /[\/]node_modules[\/]/,
            name(module) {
              return "defaultVendors"
            },
            // chunks: "all",
            // minChunks: 3,
            priority: 10,
            // minSize: 10000,
            maxSize: 10000,
          },
          default: {
            chunks: "all",
            name(module) {
              return "app11"
            },
            // filename: "app112"
            // priority: -10,
            // minSize: 10000,
            maxSize: 10000,
          },
        }
      }
    }
  }
})

 

打包之后结果如下, 可以看到的是 拆分的和 chunk-vendors 的拆分貌似类似

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_22,第22张

 

假设是手动配置了分包的相关配置, 这里 具体的拆分就是和 chunk-vendors 类似的分包拆分处理

在 SplitChunksPlugin 中进行的处理, 这里可以参见上面的 chunk-vendors 的分包策略处理

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_分包_23,第23张

 

 

app.js 的默认分包 和 手动配置的分包 的差异

这个是从另外的一个维度 来进行的分析

在默认的分包处理下, 可以看到 我们这里访问 HelloWorld, 仅仅是请求了 HelloWorld 的相关的组件

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_24,第24张

 

编译出来的 index.html 如下, 可以看到的是 仅仅是导入了 app.js 这个入口的 chunk

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包_25,第25张

 

对于路由下面的各个情况, 是导入的各自的 js

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_26,第26张

 

js 的映射如下

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_27,第27张

 

在手动分包的处理下, 可以看到 请求了 app.js 囊括的所有的 js

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_分包_28,第28张

 

编译出来 index.html 如下, 可以看到是 引入了所有的包, 不管是进入哪一个页面, 都是请求的全量的 app.js 和 chunk-vendors.js

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_29,第29张

 

 

app.js 的默认分包的每一个组件包含了那些东西?

HelloWorld.vue 文件内容如下

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_前端_30,第30张

 

AsyncQueue.vue 文件内容如下, 导入了一个 HelloWorld.vue 的组件

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_node.js_31,第31张

 

然后编译完之后的 import('../components/HelloWorld') 如下

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_npm_32,第32张

 

然后编译完之后的 import('../components/AsyncQueue) 如下

可以看到 编译之后的结果 是将使用到的组件都内联进来了, 这样可能导致一些公用组件的内容被内联很多次, app.js 总共的包大小 膨胀

但是 页面时按照需要导入的对应的 js

增加了一些 编译器编译的开销, 服务器存储的开销, 减小了客户端请求的开销

55 npm run serve 和 npm run build 的分包策略,55 npm run serve 和 npm run build 的分包策略_拆包_33,第33张

 

 

完 

 

 

 


https://www.xamrdz.com/web/2c21961698.html

相关文章: