Angular项目加载时间优化

2,071 阅读10分钟

一:AOT

与在浏览器中完成编译的JIT编译相反,AOT在构建过程中编译了很多代码(也称为脱机编译),从而减少了客户端浏览器上的许多处理开销。使用angular-cli时,只需指定“ aot”标志(如果存在prod标志,则不需要aot标志),就会启用AOT。

二: Rollup 摇树优化

所谓Rollup是指Webpack2会把那些应用中未使用的引用代码除掉,但不会删除这些代码,所以就需要配合 UglifyJs 能够智能的移除这些未使用的代码。从而减少包体大小。

而Agnular应用是基于Typescript,因此Angular Cli提供了一个叫 Angular Build Optimizer 插件,将 Typescript 编译结果转化成更友好的UglifyJs版本。这样UglifyJs就能够更有效的移除那些未使用的代码。

Angular Cli只需要加上 --build-optimizer 参数就可以,这将禁用供应商数据块,并导致代码更小。在一些情况下压缩的还是很厉害的。

ng build --prod --build-optimizer

这是删除未使用的代码的过程,从而减小了构建大小。如果您使用angular-cli,则默认情况下会启用Tree-Shaking。

三:Uglify

在此过程中,将使用各种代码转换(例如,重整,删除空格,删除注释等)来减少代码大小。对于webpack,请使用uglify插件并与angular-cli一起指定“ prod ”标志来执行丑化过程。

注意:Uglify的缺点是只能压缩js文件(且只支持ECMAScript 5: ES5)。对于大部分页面是ts文件的angular项目并不适用。

  • 用法如下:
  1. 安装node
  2. 安装Uglify:
npm install uglify-js -g
  1. 找到需要压缩的文件,进入cmd页面:
uglifyjs 文件名.js -m -o 文件名.min.js
  • 使用webpack来安装uglifyjs-webpack-plugin 对于配置,您需要使用以下命令:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
    
    optimization: {
    
        minimizer: [new UglifyJsPlugin()],
    
    },

};

参考文章:aglowiditsolutions.com/blog/improv…

四:Google Closure编译器

这是Google用于其产品的编译器,与Webpack uglify相比,通过执行更具侵略性的缩小,可以使捆绑包的尺寸小得多。即使Angular团队未正式支持它,您也可以看一下这个 使用闭包编译器实现。

五:Webpack 4

与Webpack 3相比,将Webpack 4(及更高版本)用于angular-cli或自定义Webpack构建会导致构建尺寸更小。Webpack 4具有mode选项,可让您指定优化类型(生产或开发)而无需您需要编写任何显式配置,从而为目标环境提供最佳的结果。而且,使用Webpack 4的构建时间比早期版本要快得多(60%至98%),从而减少了开发时间。

六:Prod标志

对于生产,构建在angular-cli应用程序中指定“ prod ”标志。它将启用各种构建优化,例如uglify,AOT,删除源映射,服务工作者(如果启用),从而生成更小的构建大小。

七:懒加载

懒加是一种机制,而不是加载完整的应用程序,我们仅加载当前所需的模块,从而减少了初始加载时间。简而言之,它的意思是“ 不要加载不需要的东西。”

八:服务器端渲染

在服务器上渲染应用程序的第一页(使用Node.js,.Net,PHP)并将其作为静态页面使用,将导致几乎即时的渲染,从而大大提高了感知的性能,速度和整体用户经验。您可以使用Angular Universal执行服务器端渲染。

九:渐进式Web应用程序

PWA使您的应用程序加载速度更快,它为您的应用程序提供了脱机功能,并提供了接近本机的应用程序体验,从而极大地提高了用户的整体感知性能。

十:Ivy Render Engine

Angular团队最近宣布了一个新的名为Ivy的渲染引擎。与现有引擎相比,它产生的捆绑包大小要小得多,并具有改进的调试体验。尽管它还没有准备好生产,但是您仍然可以在您的应用中尝试它。您可以查看此www.youtube.com/watch?v=dIx…以了解更多详细信息。

十一:更新Angular和angular-cli

定期更新Angular和angular-cli将使您受益于许多性能优化,错误修复,新功能,安全性等。

十二:RxJS 6

RxJS是使用Observables 的响应式编程的库,它使编写异步或基于回调的代码更容易。

RxJS 是一个库,它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和受 [Array#extras] 启发的操作符 (map、filter、reduce、every, 等等),这些数组操作符可以把异步事件作为集合来处理。

可以把 RxJS 当做是用来处理事件的 Lodash 。

RxJS 6使整个库更容易被树摇晃,从而减小了最终的捆绑包大小。但是,它有一些重大变化,例如无法进行运算符链接,引入了pipe()函数(有助于更好地摇晃树)来添加运算符。他们还重命名了一些运营商。

可参考文章:

  1. RxJS中文文档:cn.rx.js.org/manual/over…
  2. Rxjs知识整理:www.jianshu.com/p/16be96d69…
  3. Angular用observable解决组件间通信:www.jianshu.com/p/52500abbe…

十三:Service Worker缓存

如果已将应用程序配置为支持Progressive Web App,请确保在PWA config JSON中指定所有必需的静态资源。这些静态文件将缓存在客户端的浏览器中,从而使第二次加载更快。

十四:缓存控制标头

缓存控制标头控制谁在什么条件下以及多长时间内缓存响应,从而消除了对缓存资源进行网络往返的需要。

十五:第三方软件包

查看您使用的第三方软件包,查看是否有更好和更小的替代方案,因为这可能会减少最终版本。

十六:不必要地使用第三方程序包

如果包含第三方程序包只是为了实现小的功能,而这些功能可以通过JavaScript或Angular轻松地完成,那么您会在应用程序中添加不必要的大小开销,这些开销可以很容易地节省下来。例如,如果包括Lodash只是为了进行简单的对象过滤,则完全没有必要,因为您可以在JavaScript 中原生执行相同的操作。

十七:defer属性

在script标记中提及defer属性将延迟脚本的加载(同步),直到未解析文档为止,从而使您的网站交互更快。对于angular-cli应用程序,当前无法在构建过程中自动添加它,您必须在构建后手动添加它。

十八:async属性

与defer属性一样,async延迟脚本的加载,直到未解析文档但不考虑脚本的加载顺序。与Google Analytics(分析)脚本一起使用的最佳示例,该脚本通常独立于任何其他脚本。

十九:Gzip压缩

Gzip压缩可以大大减小响应主体的大小,从而提高Web应用程序的速度。确保已在后端启用gzip压缩。对于express.js,您可以添加压缩中间件。

var compression = require('compression')
var express = require('express')
var app = express()
app.use(compression())

二十:Preload和Prefetch属性

这些属性有助于尽快加载静态资源,从而缩短了首次有意义的绘画的时间。拥有更快的第一笔有意义的颜料极大地影响了用户体验。Preload和Prefetch几乎相似,唯一的区别是Preload资源具有更高的优先级。因此,将Preload用于初始渲染必不可少的资产,并将Prefetch用于站点加载后所需的资源(以后在整个页面中都需要)。您可以在此处阅读有关这些属性的更多信息。

二十一:更新第三方软件包

请确保您定期更新第三方软件包。很多时候,较新的软件包可能包含许多性能改进,包括较小的尺寸和其他构建时性能优化(例如RxJS 6)。此外,通过定期更新软件包,您可能会获得许多与错误修复,安全漏洞修复,与软件包兼容性相关的修复等相关的改进。

二十二:压缩图像

压缩图像而不损失很多质量是一个好主意,从而节省了通过网络传输的字节,从而缩短了构建时间。有许多工具可以实现此目的。称为TinyPNG的 VS Code扩展可用于压缩Jpeg和PNG图像,而不会损失很多质量。

二十三:删除未使用的字体

删除未使用的字体是个好主意,这可以帮助您节省网络上的几个字节。

二十四:DNS和SSL速度慢

有时您的DNS和SSL提供商可能是加载时间慢的原因。因此,请确保DNS和SSL快速且配置正确。

在代码编译运行时,还有以下办法可以优化速度:

一:更改检测

默认情况下,在每个异步事件中,Angular都会通过对整个组件树执行更改检测来执行脏检查。对于中型到大型应用程序而言,这种脏检查可能会占用大量计算资源。您可以通过将“ ChangeDetectionStrategy”设置为“ OnPush”来大幅度减少更改检测。OnPush策略促进了不可变数据结构的使用。

二:分离变更检测器

我们可以将组件与变更检测完全分离,从而使开发人员可以控制Angular何时何地执行变更检测。

import {AfterViewInit, ChangeDetectorRef} from '@angular/core';
@Component(…)
class AppComponent implements AfterViewInit {

    constructor(private cdr: ChangeDetectorRef) {}
    ngAfterViewInit() {
        // We only want to detach the change detectors after change detection has been
        // performed for the first time
        this.cdr.detach();
    }

    update() {
        // Run change detection only for this component when update() method is called.
        this.cdr.detectChanges();
    }
}

三:Web Worker

所有浏览器中的JavaScript实现都是单线程的,因此使整个应用程序可以在单个线程上运行。这样的单线程执行会极大地降低复杂应用程序的帧速率,因为UI绘制和JS执行都由同一线程处理。由于默认情况下Angular避免了直接的DOM操作,因此可以在单独的Web工作线程中运行整个Angular应用,从而使主线程保持自由状态以仅处理UI呈现。查看这篇文章,了解如何在Web Worker中运行angular-cli应用:但是,有许多npm软件包尝试直接访问DOM,从而在worker进程中运行整个应用程序时产生问题。如果您只想在Web Worker线程下运行一段代码,那么请看一下npm软件包

四:Webassembly

Webassembly是一种低级程序集,例如一种语言,可实现接近本机的性能。WebAssembly旨在通过广泛使用各种平台上可用的通用硬件功能,以本机速度执行。您可以利用Webassembly通过Webassembly运行一定数量的Web应用程序代码。看看这个链接用angular-cli和wasm创建的应用程序。但是,您应该意识到wasm仍然是一个新事实,考虑到目前它只有4种受支持的数据类型(2个浮点和2个整数点),有时使用它可能会有些棘手。同样到目前为止,在大多数情况下,与内联JS相比,使用wasm执行一小段代码时,wasm的性能优势还不是那么巨大。正确评估要移至wasm的代码。

JavaScript方面提升编译速度

我们还可以从JavaScript方面提升编译的速度,详细可以参考: cnodejs.org/topic/5c467…


参考文件:

  1. medium.com/faun/44-qui…