UmiJs - 拆包优化

news2024/11/19 10:40:22

UmiJs - 拆包优化

  • 前言
  • 一. 如何拆包,怎么拆
    • 1.1 分析自己项目的编译产物结构
    • 1.2 开始拆包
  • 二. 有哪些注意点
    • 2.1 样式丢失
    • 2.2 存在需单独打包的页面

前言

我们在写前端代码的时候,难以避免的是,我们可能引入的依赖越来越多。那么随之而来的,我们打包编译后的产物,也会随之越来越大。

默认情况下,使用Umi框架的人都知道,Umi会将前端页面,凡是用到的依赖都给打包到umi.js文件。同样地,CSS相关的则打入umi.css文件中。那当你的项目达到一定规模或者复杂程度上去的时候,尤其是umi.js文件就会很大。因此本篇文章主要分享一下拆包的经验。

一. 如何拆包,怎么拆

拆包之前我们应该去了解自己本身的项目,打出来的js文件结构是怎样的。我们可以在package.json文件中添加命令:

1.1 分析自己项目的编译产物结构

"scripts": {
	"analyze": "cross-env ANALYZE=1 umi build",
}

然后执行如下命令:

npm run anaylze

最后umi会分析你的编译产物,并弹出窗口进行图形化展示,如图:
在这里插入图片描述
可见我们的umi.js文件,即便是压缩后,依旧有4.5M的大小。可见它不一般呐。

1.2 开始拆包

首先,umiJs相关的配置,一般在目录的config/config.ts文件中,官网文档
在这里插入图片描述
我们需要在配置里面添加配置项 chainWebpack

chainWebpack: (config) => {
  config.optimization.splitChunks({
    chunks: 'all',
    minSize: 30000,
    minChunks: 1,
    maxSize: 0,
    automaticNameDelimiter: '.',
    name: true,
    maxAsyncRequests: 30,
    maxInitialRequests: 10,
    cacheGroups: {
      
    }
  });
}

相关配置项的含义:
chunks:用于指定哪些代码块应该被拆分。可以分为如下几种类型:

  • 'all':所有代码块都会被拆分。
  • 'async':只拆分异步代码块。异步代码块是指通过 import() 或类似方式动态加载的代码块。
  • 'initial':只拆分初始代码块。初始代码块是指在入口文件中直接引用的代码块。
  • 函数:可以使用一个函数来自定义哪些代码块应该被拆分。该函数接收一个参数 chunk代表当前的代码块。函数需要返回一个布尔值,表示该代码块是否应该被拆分。这个很有用

其他的配置含义如下:

  • minSize 选项指定了拆分后的代码块最小大小。
  • minChunks 选项指定了一个模块被多少个入口文件引用时才会被拆分。
  • maxSize 选项指定了拆分后的代码块最大大小。
  • automaticNameDelimiter 选项指定了拆分后的文件名的分隔符。
  • name 选项指定了是否根据模块名自动生成文件名。
  • maxAsyncRequests 选项指定了最大异步请求数。
  • maxInitialRequests 选项指定了最大初始请求数。
  • cacheGroups 选项用于配置缓存组。

大家可以照抄上面的配置。接下来看下cacheGroup的写法:

cacheGroups: {
  vendors: {
    name: 'vendors',
    test: /[\\/]node_modules[\\/]/,
    priority: 11
  },
  reactFileViewer: {
    name: 'reactFileViewer',
    test: /(react-file-viewer)/,
    priority: 12
  },
}

我这里呢,将我的umiJs中的相关依赖拆成了两个JS文件 umi.js本身还是会存在的,只不过它里面大部分的内容被“转移”到这俩js文件中) 因为react-file-viewer这个依赖它占用的大小非常非常的大,因此把他抽出来。

我们需要关注的是这么几个东西:

  1. 打包的文件名称:name
  2. 打包的正则匹配:test
  3. 优先级:priority 属性用于设置优先级,数字越大,优先级越高,打包时会优先匹配优先级高的配置。 这个同样很重要!!!

上面的配置含义如下:

  1. 我优先把react-file-viewer这个依赖单独打包成reactFileViewer.js文件。优先级12。
  2. 剩余所有的依赖全部打入到vendors.js文件中。优先级11。因为我的正则写的是[\\/]node_modules[\\/],所以会把所有用到的依赖都打入进去。

那么最后再次执行对应的分析命令 npm run anaylze,结果如下:
在这里插入图片描述

由于我这里是演示,其实umi.js文件还是很大。那么你就需要看它里面到底装了什么东西,把比较大的东西给他拆出来,我总结下几个拆分的规则:

  1. 跟业务无关的,比如antd这种文件,可以单独拆出来。按照依赖的类型进行拆包,比如工具类相关的(lodashmoment等)、React相关的等等。
  2. 特别特别大,但是只有个别页面使用的,可以单独抽出来,对应使用的页面引入对应JS,例如我上面的react-file-viewer
  3. 尽量做到均衡平分,因为页面加载Js是并行多个加载的,所以若你拆包不均衡,一个js大小2M,一个大小100KB,那么最后页面加载的时间还是以最长的2M为准。反之,如果你均分成两个1M大小的文件,那么页面加载JS的时长大概就在1秒。(都是粗略的计算)

二. 有哪些注意点

倘若你跟我一样,前端打包后,采取模板渲染的方式(比如Egg的ejs模板渲染),或者是外部显式引入umi.js等静态资源文件的地方。那么你在拆包之后就需要考虑到资源的加载顺序问题了。

2.1 样式丢失

比如:倘若你把antd相关的资源从umi.js文件中隔离出来,那么你在外部引入资源的时候,就需要考虑到两件事:

  1. antd打出的包你也要引入,例如 < link rel="stylesheet" href='antd.chunk.css' />
  2. 特别重要:考虑到antdumi的文件加载顺序。例如:当你先引入umi.css文件,再引入antd.css文件(而umi.js里面包含了我们的前端页面,里面使用到了antd的组件),那么就会造成完成umi.js文件加载的时刻,找不到对应的antd样式,即样式丢失。

那么我们怎么办,建议:

  1. 由于我们把umi.js文件中大部分的依赖全部抽除去了,最终umi.js文件的大小实际上只有几KB因此为了避免这种由于加载顺序导致的样式依赖丢失,我们可以把antd这类资源保留到umi.js中。

代码编写如下:

vendors: {
  name: 'vendors',
  test: /[\\/]node_modules[\\/](?!antd|@ant-design)/,
  priority: 11
},

在原本的基础上,通过正则表达式,排除了antd相关的依赖,即正则末尾加上:

(?!antd|@ant-design)

那么当umi.js把剩余所有的依赖抽出到vendors文件中的时候,会保留antd相关资源,因此antd相关的资源就会保留到umi.js文件中。那么外部引入的时候,也不会有样式丢失的问题了。

2.2 存在需单独打包的页面

如果你的项目,已经把个别页面单独打包了,而某些情况下,你又不希望它打出来的文件被更改。那么你可以在拆包的过程中,将其排除:

比如,我的项目单独对一个页面打包,打包成了test.js文件:

const ChunksIgnoreList = ['test','test2'];

chainWebpack: (config) => {
  // 单独打包
  config.entry('test').add('./src/pages/test/index.js');
  config.entry('test2').add('./src/pages/test2/index.js');
  // ...省略
  config.optimization.splitChunks({
    chunks: (chunk) => ChunksIgnoreList.filter((item) => item.includes(chunk.name)).length === 0,
    // ...省略
  });
}

我们就可以在splitChunks中的chunks属性,自定义函数(文章上面有提到,是可以写自定义函数的,我们就不要写all了),这里将我们上面单独打包的文件,全部给排除掉了,只有chunk的名称不是上面ChunksIgnoreList 中定义的几个,都允许被拆分打包。对应的拆包结果如下:

在这里插入图片描述

当然,这里需要补充一点:

  1. 如果你单独打包某个页面,又使用了split的拆包方式,那么是不建议前者的打包方式存在的。
  2. 比如antd为例,你单独打包一个页面,antd可能会被打包到test.js文件中。但是antd同样又会被打包到umi.js文件中,就造成了打包内容的重复。
  3. 因此推荐只用split方式打包就可以了。除非你有一些特殊的需求。

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

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

相关文章

Redis入门 - Lua脚本

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis入门 - Lua脚本 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-scription.html Redis 脚本使用 Lua 解释器来执行脚本。 Redis 2.6 版本通过内嵌支持 Lua 环境。执行脚本的常用命令为 EVAL。 …

【Golang系列】Golang环境配置和第一个Go程序

⭐️前面的话⭐️ 本篇文章将介绍Golang语言的环境配置&#xff0c;以及如何在VS code中运行第一个golang程序。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4cc;本文由未…

Pytest教程__定制allure报告(12)

定制报告需要先导入allure模块&#xff0c;再使用以下装饰器方法&#xff1a; feature: 标注主要功能模块。story: 标注feature功能模块下的分支功能。description&#xff1a;在报告中显示用例描述。step: 标注测试用例步骤。issue && testcase&#xff1a;标注用例关…

单链表刷题(1-3)

目录 反转链表 移除元素 合并有序链表 反转链表 力扣 我们用取头节点依次进行头插的方式解决这道题。需要注意的是头插前要保存下一个节点。 struct ListNode* reverseList(struct ListNode* head){typedef struct ListNode SL;SL* cur head;SL* rhead NULL;//初始指向空…

TienChin 代码格式化-项目结构大改造

代码格式化 博主下载项目之后发现&#xff0c;整体的代码格式化风格&#xff0c;与 C 那种语言很相似&#xff0c;说明这个作者之前就是从事这块的导致风格有点类似&#xff0c;我们来格式化一下&#xff0c;当然这不是必要的&#xff0c;我是没习惯这种写法所以这里我写一下我…

2023年测试岗,你真的懂测试吗?凭什么他能月薪25k+

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 测试人员应该居安…

Redis入门 - 事务

原文首更地址&#xff0c;阅读效果更佳&#xff01; Redis入门 - 事务 | CoderMast编程桅杆https://www.codermast.com/database/redis/redis-transaction.html Redis 事务可以一次执行多个命令&#xff0c; 并且带有以下三个重要的保证&#xff1a; 批量操作在发送 EXEC 命…

STM32串口通信详解(嵌入式学习)

STM32串口通信 1.通信基础知识1.1 时钟信号区分同步通信异步通信波特率总线协议(电气协议) 1.2 通信方式划分串行通信并行通信 1.3 通信方向划分单工通信半双工通信全双工通信常见通信总结 2. USARTUSART 介绍 3. 串口通信协议4. 相关寄存器串口控制寄存器波特率寄存器中断和状…

segment anything环境配置与使用测试

硬件&#xff1a;RTX3070 i9-11900H 内存16G 目录 一、环境配置 二、使用测试--predictor_example.ipynb 1.jupyter notebook准备操作 2.Object masks from prompts with SAM与Environment Set-up 3.Set-up 4.Example image 5.Selecting objects with SAM 6.Specifyin…

GeoServer安装部署

GeoServer是一款开源的GIS服务器,用于管理、共享和编辑空间数据。 它的主要功能包括: 管理空间数据&#xff1a;GeoServer可以连接各种空间数据源,包括文件(SHP、CSV等)、数据库(PostGIS,Oracle,SQL Server等)和云存储(S3,Swift,Azure等)。并提供数据的浏览、上传、下载和删除…

webgpu之旅04

继续继续 319854902 319854902 319854902 319854902 webgpu交Q流群首先准备好绘制到屏幕所需的这个descriptor if rendertarget this._textures.initRenderTarget( renderTarget ); 来看一下这个函数里面会做什么 renderTargetProperties是这个target的properties 创建一个co…

历时一个月,腾讯认证python全套项目实战笔记,终于整理出来了

前言 之前拿到一份关于腾讯认证的python的全套项目实战脑图&#xff0c;于是历时花费一个月&#xff0c;终于是熬夜加点的给肝出来了&#xff0c;先用typora全部写出来&#xff0c;然后再导出成PDF文件&#xff0c;目前已经完全搞定。 总共划分内容为&#xff08;七大模块&am…

Telnet协议详解

Telnet协议是一种远程登录协议&#xff0c;它允许用户通过网络连接到远程主机并在远程主机上执行命令。本文将对Telnet协议进行详细介绍&#xff0c;包括其基本概念、连接方式、C/S模式以及工作原理。 一、Telnet协议的基本概念 1. NVT&#xff08;Network Virtual Terminal&a…

通付盾荣获第六届(2023)数字金融创新大赛“创新先锋榜”!

今日&#xff0c;第六届&#xff08;2023&#xff09;数字金融创新大赛“创新先锋榜”揭晓&#xff0c;大赛由中国电子银行网、数字金融联合宣传年主办&#xff0c;自4月6日开启以来&#xff0c;得到数字金融行业各方的积极响应与支持。经过专家评分、路演评审等环节&#xff0…

Android中Activity、View和Window关系详解

Android系统启动篇 1&#xff0c;《android系统启动流程简介》 2&#xff0c;《android init进程启动流程》 3&#xff0c;《android zygote进程启动流程》 4&#xff0c;《Android SystemServer进程启动流程》 5&#xff0c;《android launcher启动流程》 6&#xff0c;…

8年测试总结,App测试要点常见bug分类,从功能到性能测试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 而针对手机应用软…

数字IC设计怎么入门?(附学习全流程)

看到很多小伙伴都不了解数字IC设计该怎么学&#xff0c;下面就来给大家来具体讲讲。 其实对于初级数字 IC 设计工程师而言&#xff0c;不仅仅需要较好的 Verilog 语法功底&#xff0c;还要熟悉企业的 Linux 环境以及 EDA 工具&#xff0c;此时你就需要掌握 Shell&#xff0c;V…

Django 权限管理和guardian插件

内置权限管理 Django内置的权限管理, 是一种表权限, 就是可分别配置某管理员用户对某个表的全部数据有没有增删改查4种权限. 图形界面配置权限 之前提到&#xff0c;使用命令行创建超管用户&#xff1a; python manage.py createsuperuser这其实是在最普通的用户的基础上将…

百度网盘的最新插件(懂得都懂)

下面先给大家介绍一下油猴插件。 这个插件为什么叫油猴&#xff1f; 现在我们经常提到的油猴插件&#xff0c;常指Tampermonkey&#xff0c;但Tampermonkey翻译过来是叫篡改猴&#xff0c;为什么会叫油猴呢&#xff1f;原因是因为另一个插件Greasemonkey&#xff0c;它翻译过…

Qt编写iFIx组态软件日报表插件的实现

一、iFIx中生成report.MDB文件 在Ifxi组态软件的【调度】中新建调度任务【report】添加【定时器调度项】FixTimer5&#xff0c;间隔1h触发一次。通过此任务及脚本程序&#xff0c;将相关变量定时存入自动生成的report.MDB文件中。 用户脚本程序如下&#xff1a; ---- User Co…