什么是 Angular ng build 输出中的 Lazy Chunk files

如图:


Lazy Chunk files 的概念和来源

当你在 Angular 项目中执行 ng build 时,生成的表格中有一列叫 Lazy Chunk files。顾名思义,Lazy Chunk files 指的是通过懒加载(Lazy Loading)技术加载的代码块。在现代前端开发中,懒加载是一种非常重要的性能优化手段,它可以显著降低应用的首屏加载时间,提升用户体验。

在 Angular 项目中,模块(Modules)是应用程序的基本组成部分,这些模块可能会被拆分为若干不同的代码块(Chunk)。有些模块在应用加载时是必须的,而有些模块可以延后加载。那些被标记为可以延后加载的模块被称为懒加载模块,而这些模块打包生成的 JavaScript 文件,就会列在 Lazy Chunk files 这一列中。

我们可以简单总结:Lazy Chunk files 是从懒加载模块中生成的代码文件,而这些懒加载模块的生成来自开发者在项目代码中对某些模块进行特殊配置,使得这些模块只在用户实际需要时才加载到浏览器中。

Angular 中懒加载模块的配置和实现

在 Angular 中,懒加载模块主要是通过路由(Routing)机制实现的。开发者可以利用 Angular 的路由配置,将某些特定的功能模块设为懒加载,以减少应用初次加载时的代码量。我们先来看看如何配置懒加载模块。

假设我们有一个 Angular 项目,这个项目有三个模块:AppModuleHomeModuleUserModule。其中 HomeModule 是应用的首页模块,它包含了一些基本的信息,是用户打开应用时需要立即展示的内容,因此我们将其配置为默认加载的模块。而 UserModule 则是一个包含用户信息、设置等内容的模块,我们可以将其配置为懒加载模块,因为这些内容并不是用户每次打开应用时都必须立刻查看的。

具体的实现可以通过 Angular 的路由器(Router)来完成:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', loadChildren: () => import('./home/home.module').then(m => m.HomeModule) },
  { path: 'user', loadChildren: () => import('./user/user.module').then(m => m.UserModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

在上面的代码中,我们定义了两个路由:

  1. 根路径 '',也就是应用的首页,它加载 HomeModule。由于这是默认路径,所以在用户访问应用时,HomeModule 会被立即加载。
  2. /user 路径,它加载 UserModule。这里我们使用了 loadChildren 属性,并使用动态导入语法 import() 来加载 UserModule。这种方式让 UserModule 成为一个懒加载模块。

当用户打开应用时,Angular 只会加载 HomeModule 的相关代码,而 UserModule 的代码只会在用户访问 /user 路径时才会被加载。这种按需加载的方式减少了首页的加载体积,从而加快了应用启动的速度。

生成 Lazy Chunk files 的过程

当我们执行 ng build 时,Angular CLI 会对整个项目的代码进行打包,其中懒加载的模块会被打包成独立的 JavaScript 文件,这些文件就是 Lazy Chunk files。比如上面的例子中,如果你执行了 ng build,你可能会看到以下输出:

Initial Chunk Files Raw Size Names
main.js 7.44MB main
runtime.js 5.14KB runtime
polyfills.js 35.4KB polyfills
Lazy Chunk Files Raw Size Names
user-user-module.js 120KB user

可以看到在 Lazy Chunk files 这一列中出现了一个 user-user-module.js 的文件。这个文件就是上面代码中配置为懒加载的 UserModule 被打包生成的文件。user-user-module.js 是一个独立的代码块,当用户访问 /user 路径时,Angular 会加载并执行这个文件。

Lazy Chunk 的来源和 Webpack 的分片打包机制

为了深入理解 Lazy Chunk files 的生成,我们需要了解一些 Webpack 的分片打包机制。Angular 使用 Webpack 作为底层的构建工具,Webpack 的一大特点就是代码分片(Code Splitting)。代码分片允许开发者将应用程序分解成多个小块,并在需要的时候加载它们。

Webpack 通过静态分析代码,找到所有动态导入(dynamic imports)的地方,并根据这些导入生成独立的代码块。在上面的例子中,我们使用了懒加载模块,代码中包含了 loadChildren: () => import('./user/user.module').then(m => m.UserModule) 这样的动态导入,Webpack 会将 UserModule 分解出来,生成一个独立的 user-user-module.js 文件。当用户导航到 /user 页面时,浏览器会发出请求,动态加载这个 JavaScript 文件。

Webpack 生成的代码块通常被称为 chunk。懒加载模块就被打包成独立的 Lazy Chunk,而这些文件的名称就出现在 Angular CLI 输出的 Lazy Chunk files 这一列中。文件名称一般遵循一定的规则,通常会以模块名称加上一些哈希值,这样可以确保模块名称的唯一性和缓存的有效利用。

真实世界案例:电子商务网站的模块化拆分

为了让概念更加具象化,我们来看一个真实世界的案例。假设我们在开发一个电子商务网站,这个网站有如下几个主要功能模块:

  1. 首页模块(HomeModule):包含商品推荐、特价活动、热门分类等内容。
  2. 用户模块(UserModule):包括用户的个人中心、订单管理、账户设置等功能。
  3. 商品详情模块(ProductModule):用于展示商品的详细信息,包括图片、价格、规格等内容。
  4. 购物车模块(CartModule):用户可以查看并管理添加到购物车中的商品。

在实际的开发中,首页模块是用户访问时首先加载的,因此应该尽量保持轻量。而像用户模块、商品详情模块、购物车模块等可以通过懒加载来减轻首页的加载压力。这些模块只有在用户访问到相关页面时才会被加载到客户端。

假设我们在路由中将 UserModuleProductModuleCartModule 都配置为懒加载。当我们执行 ng build 后,输出的 Lazy Chunk files 可能会像这样:

Lazy Chunk Files Raw Size Names
user-user-module.js 130KB user
product-product-module.js 220KB product
cart-cart-module.js 95KB cart

这些 Lazy Chunk files 就是我们通过懒加载配置生成的独立代码块。当用户进入个人中心时,Angular 会加载 user-user-module.js;当用户查看某个商品时,会加载 product-product-module.js;而当用户打开购物车时,Angular 会加载 cart-cart-module.js

通过这种按需加载的方式,我们可以显著减少首页的加载时间。例如,如果不采用懒加载,首页可能需要一次性加载 2MB 的代码,而通过懒加载,我们可以让首页只加载 1MB 的核心代码,其余模块按需加载,极大地提升了应用的响应速度。

Lazy Chunk 的命名和缓存策略

Lazy Chunk files 的命名通常会包含模块的名称,以方便开发者识别具体哪个模块生成了这个代码块。例如,user-user-module.js 中的 user 就是模块的名称。但在实际的生产环境中,Webpack 通常还会加上哈希值,形成像 user-user-module.abcd1234.js 这样的文件名。这个哈希值是根据模块的内容计算得到的,当模块的代码发生变化时,哈希值也会变化。

这样的命名策略有助于浏览器的缓存机制。比如当用户第一次访问 /user 页面时,user-user-module.abcd1234.js 会被下载并存储在浏览器缓存中。如果在后续的应用版本中,UserModule 没有发生任何变化,那么用户再次访问这个页面时,浏览器可以直接从缓存中加载这个文件,从而避免了重复下载,提升了页面的加载速度。而如果 UserModule 的代码发生了变化,那么生成的文件名的哈希值也会变化,浏览器会下载新的文件,确保用户看到的是最新的内容。

懒加载的优势与注意事项

懒加载在现代前端开发中是一种非常重要的性能优化手段,它可以显著减少应用的初始加载时间。然而,懒加载也不是没有代价的。在一些应用场景中,频繁地使用懒加载可能会导致用户在导航时频繁地看到加载指示器(loading spinner),尤其是在网络不佳的情况下。因此,在进行模块划分时,需要根据具体的业务需求和用户体验来决定哪些模块应该懒加载,哪些模块应该立即加载。

例如,在开发一个大型的内容管理系统(CMS)时,可能有一些很少使用的功能模块,比如系统设置或者一些高级配置项,这些模块非常适合懒加载。而像常用的内容编辑模块或者仪表盘模块,则应该立即加载,以确保用户进入系统后可以迅速开始工作。

在实际的开发中,通常会结合用户的行为数据和访问路径来决定模块的加载方式。通过分析用户的访问行为,可以发现哪些模块是用户频繁使用的,哪些模块是偶尔访问的,这样可以更有针对性地进行模块划分和懒加载配置。

总结

Lazy Chunk files 是 Angular 在打包过程中通过懒加载技术生成的独立 JavaScript 文件。这些文件的生成源于开发者对应用模块的懒加载配置,目的是通过按需加载来减少应用的初始加载时间,提升用户的体验。在构建输出中看到的 Lazy Chunk files 体现了每个懒加载模块被打包后的具体信息,包括文件名称、大小和模块名称。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容