问题描述
项目目前遇到了一个比较大的问题,每次我使用ng build
打包系统上传到服务器更新之后,同事打开项目需要加载非常久的时间,加载约10分钟左右。
并且国内网和国外网的加载时间不一样,国外网4-10分钟,工厂的同事用国内网甚至一直加载不出来。
于是我开始查资料学习并实践,在此记录自己的优化历程,所以此文章仅用于分享自己的经验,并不是全面的专业技术文章,仅供参考!
文章中有大部分资料和知识都来自于这篇文章Angular:性能优化清单,这篇文章讲的会更专业、细致很多,有需要可以自行阅读。
项目信息
环境配置
OS:Windows10x64
Angular版本:Angular-11.0.0
NodeJS版本:NodeJs-14.15.4
项目原始大小
ng build打包
打包后大小:
打包时间:242416ms(4.04分钟)
加载时间
加载时间主要以以下三种为参考,是最初使用ng build
指令且没有任何优化的情况:
- 我自己的电脑:国内网约4min,国外网约0.5min
- 产品经理的电脑:国内网10min起步,国外网4min起步
- 工厂同事的电脑:国内网:无法打开,无国外网
电脑配置:我>产品经理>工厂同事
在进入系统的时候,可以在控制台看到加载中其实一直在加载一个文件:vendor-es2015.js(其他很快就加载完了)
我自己的理解是,Angular将所有代码打包成一个js文件,在进入系统的时候需要将这个非常大的js文件加载完才可以进入系统。
那么有没有方法可以缩小js文件的大小、或采用分布式加载(只加载当前页面,不加载未使用的页面)呢,带着这个疑问我开始在网络上去查资料
第一步优化:优化编译机制
了解Angular的编译原理
在优化之前先需要知道Angular是怎么编译的,
Angular的编译就是将Angular项目中的组件、管道、指令、HTML模板、Typescript编译成ES5文件,这样在浏览器JavaScript Virtual Machines (VM)就可以直接运行了。
了解Angular的两种编译机制:JiT和AoT
这里不深入说明,只大致讲解区别。
从网络查询资料得到两种编译机制的具体流程如下
JiT的编译机制:
- 基于 TypeScript 开发 Angular 项目
- 用 tsc 编译 Angular 项目
- 打包
- Minification
- 部署
当用户访问这个网站的时候:
- 下载相关的静态资源文件,包括 Angular 编译器(@angular/compiler)
- 启动 Angular
- Angular 编译器执行编译(ngc)
- 页面渲染
AoT的编译机制:
- 基于 TypeScript 开发 Angular 项目
- 编译 Angular 项目
- 先把模板和 component 编译成 TypeScript/es6(ngc)
- 再把 TypeScript 编译成 es5 (tsc)
- 打包
- Minification
- 部署
当用户访问网站的时候:
- 下载相关的静态资源文件,不需要下载 Angular 编译器(@angular/compiler)
- 启动 Angular
- 页面渲染
简单来说,AoT相比于JiT,在打包运行后不需要再下载Angular编译器,也不需要执行编译,而是直接渲染页面,在性能上优于JiT不少。
那么网络上就得到优化,因为AoT不需要再下载Angular编译器,所以因为国内外网差距导致的下载网速问题就解决了。
AoT渲染的速度和时机也都优于JiT,那么重新进入系统导致长时间加载的问题也得到了解决。
如何使用AoT编译
将打包指令修改为ng build --aot
即可
需要值得注意的是,通过查询资料我得知Angular6版本的时候,本地运行也可以使用AoT编译,也就是ng serve --aot
指令
但我在Angular11项目下使用该指令,显示已经弃用该指令,而是在浏览器中设置:
Option "aot" is deprecated: Use the "aot" option in the browser builder instead.
怎么在本地使用AoT编译我目前也暂时没找到使用方法
ng build –aot打包
打包后大小:
打包时间:215567ms(3.59分钟)
可以看到打包后的大小并没有区别,但我自己实际体验之后系统的加载速度明显快了不少,我接下来直接进行了第二步优化
第二步优化:Tree Shaking
了解Dead Code
在项目中,前同事的架构做的不是很成熟,公司在代码方面没有很高的要求,外加我刚进公司的时候也是比较萌新
所以导致了很多Dead Code(无效代码)的产生,例如某些并没有使用的引用、函数、css等
这些在打包编译的时候都会打包进文件中,会占用很大的空间和无用的内存
我最开始其实有想过花一段时间去整理并删除那些无用代码,但工作量着实太大,并且也没法从根源上解决问题,毕竟我无法保证Dead Code的完全不产生,时间久之后自然也会堆积
了解Tree Shaking
这时候我了解到了Tree Shaking:可以把项目想象成一棵树,有效的代码就是树叶,无效、未调用的代码就是无用的枯树叶,Tree Shaking就是通过摇晃树使枯叶掉落(忽略无效代码)
而Angular的某个编译指令自带Tree Shaking:ng build --prod
,并且该指令是使用AoT编译的
ng build –prod打包
打包后大小:
打包时间:863208ms(14.38分钟)
可以看到打包后文件小了整整六分之一,但打包时间增加了三倍多,但系统的加载时间得到了显著提升,这新增的打包时间是完全值得的。
- 我自己的电脑:国内网1.9min,登录进入系统10s左右
- 产品经理的电脑:国内网2.1min,登录进入系统1min
- 工厂同事的电脑:暂时还未使用
但产品经理只是2.1min加载完登录界面,点击登录后等待了1min才进入系统主页
其中体现了两个问题:1.系统登录界面加载速度还是有点慢 2.1min的时间应该是在预加载整个系统,时间过长
目前我的思路就是试着尝试结合懒加载和预加载,预加载系统主页和登录界面,其他模块功能则采用懒加载,其中还可能用到WebPack(需要从0开始学习,以前没用过)。
第三步优化:LazyLoading和PreLoading
正在研究中,如有进展会继续更新