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

前言

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

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

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

3349532ecefa4a6d893ffc0f31cbd540.png

 

 

测试配置

在 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 的包会被单独拧出来形成一个单独的包, 不管他的大小多大

a23b5de626504cfa906f96b86832ea27.png

 

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

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

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

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

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

3212200534cb47fbbdc6313621fff005.png

 

 

拆分的过程调试如下

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

40bdcc62063e414db567e2ddf7359574.png

 

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

a243c842422a47d9b47dddc300f3f31b.png

 

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

2c43da1ba51f4013bfc201400a9543c1.png

 

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

1102e338718c49978dc26751c8a97724.png

 

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

ebc2a08a894045beb42f62563545628d.png

 

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

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

bc4d6555c69e460eaf441e386c1e21b9.png

 

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

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

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

5771dd4b111d48d19e5441903ef0f0fa.png

 

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

d36631b2318b4592b595c579551f0cff.png

 

 

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 编译之后生成的项目文件

4354757e42ec44fa8f0d1b07448cfb98.png

 

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

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

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

97ae45fa2f5e444590b9c97e500dcd76.png

 

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

9dcb45254f854e2586af081b5be702cc.png

 

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

9ace82f536f84b46a7409e4a1a6c8e27.png

39899cf0c0244645b4025ce6a9fd6b90.png

 

 

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

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

计算 chunk 的 id, 名称如下

1b6ce0e3bbd34d7e93292ca2bbe87baf.png

 

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

e18bd9a7d81e4ea3aeec2ab947e89e89.png

 

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

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

fc4ec0a359f548928430c20208a05463.png

 

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

37ca0b67675f4f2d988f6b18242fd5e0.png

 

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

c41c0fd77cf34c92a157dda74475df8f.png

 

 

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 的拆分貌似类似

26be90b0b55b4376a8188d9ae0905b2a.png

 

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

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

a93951de34704af8a541aa8144f62f51.png

 

 

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

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

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

412698767fc6463fbd50775a357c8031.png

 

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

9c2252773e8e44a2bf34d632f0236f1e.png

 

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

703a73f5d6ca4e60a5ab9091a5ec2921.png

 

js 的映射如下

cc34a94329fa42008290e8f9b58305cb.png

 

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

74b2048748f84887b0c9b958635e336b.png

 

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

5c7c068758464f4ca42fecece3f4978c.png

 

 

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

HelloWorld.vue 文件内容如下

5733b7e8058041489d10759fcb80bd03.png

 

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

498e6c5b7f6a419b885620fe0f88f6b4.png

 

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

a7cb1ed96fa54d878372f710da3b4f64.png

 

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

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

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

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

42416971f1b44f3fa5f15c8bf93ffe18.png

 

 

完 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/784699.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Verilog基础【一】

文章目录 1.1 第一个verilog设计1.2 Verilog 简介1.3 Verilog环境搭建1.4 Verilog 设计方法设计方法设计流程 2.1 Verilog 基础语法格式注释标识符与关键字 2.2 Verilog 数值表示数值种类整数数值表示方法实数表示方法十进制:科学计数法: 字符串表示方法…

2023年C++语言B组蓝桥杯的三道题解【题解整合】

链接整合包 飞机降落–>点我传送 接龙数列–>点我传送 岛屿个数–>点我传送

ubuntu23.10配置RUST开发环境

系统版本: gcc版本 下载rustup安装脚本: curl --proto https --tlsv1.2 https://sh.rustup.rs -sSf | sh下载完成后会自动执行 选择默认安装选项 添加cargo安装目录到环境变量 vim ~/.bashrc 默认已添加 使用环境变量立即生效 source ~/.bashrc 执行rust开发环境,在终端输入…

使用Pilotfish扩展Sui执行能力

Pilotfish第一个多机智能合约执行引擎,使Sui网络的验证节点可以利用多台机器,并在负载增加时自动扩展以执行更多的交易。这一目标实现不会影响可靠性或功能完整性。 Pilotfish可以从内部执行机器的故障中恢复,并支持Sui的全面动态操作。其流…

表白墙项目(JAVA实现)

1、在html里 class使用. id使用# 2、记得引入响应依赖(举例lombok) 3、messageController package com.example.demo.demos.web; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; i…

Springboot集成knife4j (swagger)

1、添加依赖 在pom.xml 文件中添加 knife4j-spring-boot-starter 的依赖 <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>3.0.3</version> </depe…

【千帆杯】K12教育常规赛 北京场线下交流会心得

千帆杯K12教育常规赛 北京场线下交流会心得 ​ 周日有幸参加了 百度智能云千帆AppBuilder北京场线下交流会 ( 活动链接 )&#xff0c;去线下组队创作了 K12教育 相关的智能体。参赛过程中认识了不少大佬与朋友&#xff0c;抱大佬队友的腿&#xff0c;他的 猜成语 应用获得了线…

【OS探秘】【虚拟化】【软件开发】VirtualBox 虚拟化软件卸载和重装

往期OS系列博文&#xff1a; 【OS探秘】【虚拟化】【软件开发】在Windows 11上安装mac OS虚拟机 【OS探秘】【虚拟化】【软件开发】在Windows 11上安装Kali Linux虚拟机 一、事出有因 近日&#xff0c;笔者的Oracle VM VirtualBox突然抽风了&#xff0c;虚拟机无法启动&…

世微 AP5191 降压恒流LED车灯 12-80V 9V5A电源驱动方案

AP5191是一款PWM工作模式,高效率、外围简 单、内置功率MOS管&#xff0c;适用于4.5-150V输入的高 精度降压LED恒流驱动芯片。输出功率150W&#xff0c; 电流6A。 AP5191可实现线性调光和PWM调光&#xff0c;线性调 光脚有效电压范围0.55-2.6V. AP5191 工作频率可以通过RT 外部…

(八)Gateway服务网关

Gateway服务网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。…

Java深拷贝与浅拷贝

Java深拷贝与浅拷贝 一、深拷贝与浅拷贝二、实现方式1、使用Object中的clone方法2、通过对象序列化 (实现Serializable接口) 三、原型设计模式 一、深拷贝与浅拷贝 浅拷贝只会复制对象中基本数据类型数据和引用数据的对象内存地址&#xff0c;不会递归的复制引用对象、以及引用…

[NOIP2005 普及组] 采药

题目描述 辰辰是个天资聪颖的孩子&#xff0c;他的梦想是成为世界上最伟大的医师。为此&#xff0c;他想拜附近最有威望的医师为师。医师为了判断他的资质&#xff0c;给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说&#xff1a;“孩子&#xff0c;这个山洞里…

containerd使用了解

containerd使用了解 yum安装 [rootvm ~]# curl -o /etc/yum.repos.d/docker.repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo [rootvm ~]# yum list | grep containerd containerd.io.x86_64 1.6.28-3.1.el7 doc…

2_2.Linux中的远程登录服务

# 一.Openssh的功能 # 1.sshd服务的用途# #作用&#xff1a;可以实现通过网络在远程主机中开启安全shell的操作 Secure SHell >ssh ##客户端 Secure SHell daemon >sshd ##服务端 2.安装包# openssh-server 3.主配置文件# /etc/ssh/sshd_conf 4.…

list(链表)容器(二)

一、list 插入和删除 函数原型&#xff1a; push_back(elem);//在容器尾部加入一个元素 pop_back();//删除容器中最后一个元素 push_front(elem);//在容器开头插入一个元素 pop_front();//从容器开头移除第一个元素 insert(pos,elem);//在pos位置插elem元素的拷贝&#xff0c…

Rhino.Inside.Revit根据直线创建剖面视图

Hello大家好&#xff01;我是九哥~ 今天简单分享一个小节点&#xff0c;根据Revit线构件的Location Line创建Revit剖面视图&#xff0c;主要用于快速创建线管、风道、墙等构件的详图视图。 效果如下&#xff1a; Rhino.Inside.Revit根据直线创建剖面视图 这次这个节点&#xff…

python中raise_for_status方法的作用

文章目录 说明示例1:基本使用示例2:多种异常说明 raise_for_status() 方法在 Python 的 requests 库中用于在发送 HTTP 请求后检查响应的状态码。如果响应的状态码表示请求未成功(即状态码不是 2xx),则该方法会抛出一个 HTTPError 异常。这允许你以一种更结构化的方式来处…

【C语言】字符串

C语言用字符数组存放字符串&#xff0c;字符数组中的各元素依次存放字符串的各字符 一维字符数组&#xff1a;存放一个字符串&#xff08;每个数组元素存放一个字符&#xff09;二维字符数组&#xff1a;存放多个一维数组&#xff08;字符串&#xff09;&#xff1b;二维数组的…

Python - 深度学习系列31 - ollama的搭建与使用

说明 做这个的主要目的是为了搭建Langchain的本地环境&#xff0c;使用LangChain让LLM具备调用自定义函数的功能。 内容 1 安装server 以下将ollama的安装方式&#xff0c;以及使用做一个简单的说明(记录&#xff09;。之前对这个工具没有了解&#xff0c;只是从快速实践的…

Linux速览(2)——环境基础开发工具篇(其一)

本章我们来介绍一些linux的常用工具 目录 一. Linux 软件包管理器 yum 1.什么是软件包? 2. 查看软件包 3. 如何安装软件 4. 如何卸载软件 5.yum补充 6. 关于 rzsz 二. Linux编辑器-vim使用 1. vim的基本概念 2. vim的基本操作 3. vim正常模式命令集 4. vim末行模式…