了解最新技术文章
Angular 已成为一种非常流行且广泛采用的用于开发现代 Web 应用程序的框架。这项技术非常强大且功能丰富。作为 Web 开发人员,您所需的一切都是开箱即用的,Angular 允许轻松配置、维护和扩展构建在框架之上的任何应用程序。
到目前为止,您可能已经组合了一个或多个 Angular 应用程序,但它们是最佳的吗?
然后,在我的软件性能系列的第 2 部分中,我将讨论 Angular 优化,演示如何使用我构建的 Angular 示例应用程序来提高 Angular 应用程序的性能。我将使用 Chrome 开发工具得出初始灯塔分数,以确定应用程序最初所处的位置。让我们看看哪些方面可以改进以及如何改进。
该系列的其他博客:
软件性能 [Web]第 I 部分
快速文章概述:
提高角度性能的方法
Angular 构建并改进初始灯塔评分
Angular 预渲染和服务器端渲染
角度延迟加载
优化图像
包起来
在本文中,我将使用我整理的一个示例 Angular 应用程序。在撰写本文时,该应用程序使用以下功能和库:
角16
Angular 16 的 Ignite UI
接收JS 7
PWA(角度服务工作者)
服务端渲染(express server)
角度定位
当我在开发环境中运行应用程序时,一切似乎都运行得很好,但最初的灯塔分数不是很高:
当我查看改进低分部分的建议时,我明白问题出在哪里。 第一个大问题是传输到客户端的资源(JavaScript、样式、静态资源)的大小。
通过运行我的 Angular 应用程序的生产版本而不是开发版本,可以轻松解决此问题 。在部署之前始终使用生产配置进行构建。这将解决减少JavaScript和CSS大小的警告。让我们看一下A ngular存储库根目录下的angular.json文件,看看生产版本有何不同:
全屏1234567891011121314151617 号18192021“配置”:{ “生产”:{ “预算”:[ { “类型”:“初始”, “最大警告”:“2mb”, “最大错误”:“5mb” } , { “类型”:“任何组件样式”, “最大警告”:“10kb” } ] , “文件替换”:[ { “替换”:“projects/common/src/environments/environment.ts”, “与”:“projects/common/src/environments/environment.prod.ts” } ] , “本地化”:true, “优化”:正确,
这里的配置相当多。然而,在这种情况下,最重要的一个 是。当我使用生产配置运行应用程序时,在加载时性能方面得分差异很大: "optimization": true
如果我 再看一下机会列表,建议的数量就少了很多。关于文本压缩列出的最大机会是未使用的 JavaScript 和静态资源的缓存:
Angular 是一个单页应用程序 (SPA) 框架。默认情况下,应用程序的生命周期是这样的:根据客户端的请求,托管应用程序的服务器会提供一个包含所有必要的脚本和样式引用的 HTML 文件。然而,它没有身体内容。一旦请求并提供了脚本和样式,应用程序就会被引导并根据给定应用程序的 JavaScript 逻辑填充内容。Angular 提供了两种机制来通过在初始 HTML 文档中提供实际内容来改善此生命周期。为此,需要在提供文档之前执行应用程序的 JavaScript 逻辑。实现方法:
要么在构建时(预渲染) - 对于主要包含静态内容的页面。
或者在服务器上运行时(服务器端渲染) - 对于具有更多动态内容且需要根据每个请求提供最新内容的页面。
我已经为 Angular 示例应用程序启用了服务器端渲染,并且使用 Express 引擎 来启用文本压缩和静态资源缓存。这是通过将以下内容添加到我的 Express 服务器逻辑中来完成的:
全屏12345678910111213导出 const app = ( lang : string ) => { // 服务器由 [ng add @nguniversal/express-engine] 搭建... // 启用压缩 [npm install compression] const 压缩 = require ( '压缩' ) ; 服务器。使用(压缩());... // 通过 1y 缓存从 /browser 提供静态文件 服务器。get ( ' *.* ' , express.static ( distFolder , { 最大年龄: '1年' })) ;...}
我将通过服务器端渲染为应用程序提供服务,并再次运行灯塔测试。初始负载进一步改善,使第一个内容丰富的绘制时间低于一秒,而速度指数降低至 1.2 秒。
Angular 优化的剩余机会是减少未使用的 JavaScript 和 CSS。
为了解决这些问题,我将不得不进行一些应用程序重构。
为了减少未使用的 JavaScript,最好的方法是创建 延迟加载的路由。这将告诉 Angular 框架顶层模块中不需要哪些组件,并将 JavaScript 拆分为模块,仅在加载请求的路由时加载其逻辑。
我在本博客中使用的 Angular 示例应用程序使用了更大的组件,例如 igx-grid,它们不属于主路由的一部分。我正在将使用此组件的路由分离到一个单独的模块中。这样,我将仅在加载使用该组件的路由之后加载该组件。模块分离后,路由如下所示:
全屏123456789101112131415导出 常量 路由: 路由 = [ { 路径: '' , 组件: HomeComponent } , { 路径: '注册' , 组件: RegistrationComponent } , { 路径: '未授权' , redirectTo : '未授权/' , pathMatch : '完整' } , { 路径: 'unauthorized/:message' , 组件: UnauthorizedComponent } , { 路径: 'emailconfirm' , 组件: EmailconfirmComponent } , { 路径: '策略' , loadChildren : ( ) => import ( './strategies/strategies.module' ) . 然后( m = > m .StrategiesModule ) } , { 路径: 'emailconfirm/:error' , 组件: EmailconfirmComponent } , { 路径: '玩家' , loadChildren : ( ) => import ( './player-section/player.module' ) . 然后( m = > m .PlayerModule ) } , { 路径: 'team' , loadChildren : ( ) => import ( './team-section/team.module' ) . 然后( m = > m .TeamModule ) } , { 路径: '通知' , loadChildren : ( ) => import ( './notifications/notifications.module' ) . 然后( m = > m .NotificationsModule ) } , { 路径: '搜索/团队/:查询' , 组件:TeamResultsComponent } , { 路径: '搜索/玩家/:查询' , 组件: PlayerResultsComponent } , { 路径: '**' , 组件:HomeComponent }] ;
这team.module
是我正在使用的加载网格的代码,因此它的代码如下所示:
全屏123456789101112@NgModule ( { 进口: [ 通用模块, 表单模块, // ... IgxGrid 模块, // ... 团队组件, // ... ]})导出 类 TeamModule { }
查看构建,这是初始拆分的结果:
为了提高 Angular 应用程序的性能,需要做的另一件事是将 CSS 的大小限制为所使用的样式。我使用 Ignite UI for Angular作为我的 UI 库,并且有一篇关于自定义和优化组件主题 的很棒的操作文章 。
Angular 优化的另一个方面是优化图像。Lighthouse 检查会根据类型或大小告诉您是否使用了次优图像。确保您加载的图像不大于它们所在的容器,并且它们具有最佳编码。我现在使用 .webp 格式的图像。它会稍微降低质量,但是应用程序仍然不需要最高保真度的图像。
图像加载后会导致布局发生变化。因此,最好在图像上设置宽度和高度属性,以便浏览器在加载图像之前知道尺寸。如果您缺少图像的宽高比设置(宽度和高度),Lighthouse 会警告您。这将减少或完全消除布局变化。
Angular 公开了一个指令,可以强制执行图像最佳实践并为您优化图像加载。它被称为NgOptimizedImage,并且相当容易使用。CommonModule
如果您仍在NgModule
基于 Angular 的应用程序中,您需要做的就是导入,或者导入NgOptimizedImage
到您想要使用它的组件中。然后,src
您可以使用而不是使用来设置图像源属性ngSrc
。
全屏1< img ngSrc = "/assets/wallpapers/strat-editor.webp" width = "600" height = "347" class = "preview-image" alt = "Strategy Editor" />
最后,您可以进一步指定每个图像的加载优先级,并告诉应用程序延迟加载每个非关键图像。如果我删除宽度和高度属性,那么我运行应用程序的结果是:
就是这样。
提高 Angular 应用程序的性能可能需要持续监控、优化和最佳实践,以确保应用程序在各种条件下高效可靠地执行。但最终,这就是您提供终极用户体验、吸引和留住用户、保持竞争力并取得业务成功的方式。