美文网首页
关于 Angular 模块按需加载的讨论

关于 Angular 模块按需加载的讨论

作者: _扫地僧_ | 来源:发表于2024-12-03 10:00 被阅读0次

在一个编译并且构建好的 Angular 应用中,chunk 文件通常是按需加载的模块的代码。它们的存在是为了减少初始加载时的资源大小和提高应用的性能。这些 chunk 文件是 Webpack(Angular 的构建工具之一)生成的,Webpack 会根据代码的模块化特性、懒加载需求、依赖关系等来划分和打包成多个 JavaScript 文件。

chunk-7QB2PB1Z.mjs 文件就是一个典型的动态加载的模块文件。它的名字中的 chunk 表示这是由构建工具生成的、按需加载的模块。而后面的随机字符(例如 7QB2PB1Z)通常是由构建工具计算出的 hash 值,这个 hash 值用于确保每次构建时内容变更都会反映在文件名中,防止浏览器缓存加载旧版本的代码。

某 Storefront 开发模式下构建后生成的 chunk 列表

为什么使用 Chunk 文件

在现代的前端应用程序中,按需加载(lazy loading)是一种非常重要的优化策略。Angular 中通过使用 NgModule 的特性来实现模块的按需加载,可以显著减少初始加载的时间,提高页面响应速度。初始加载时,Angular 应用只会加载包含基本功能的主 bundle 文件,其他的功能模块则会被拆分成多个 chunk 文件,这些 chunk 文件会在用户访问相应功能页面时动态加载。

例如,如果你的 Angular 应用有一个大型的管理模块,而这个模块是用户需要点击某个链接才能访问的。通过懒加载,这个模块会被打包成一个单独的 chunk 文件,例如 chunk-7QB2PB1Z.mjs,只有当用户真正访问该页面时,浏览器才会去加载这个文件。这就使得应用的初始加载更加轻量,提高了用户体验。

Chunk 文件的生成过程

Angular 使用 Webpack 来处理应用的构建和打包。在构建应用时,Webpack 会分析整个依赖关系图,根据模块之间的关系来划分不同的代码块,这些代码块被打包成独立的文件,称之为 chunk。生成这些 chunk 的过程包括以下几个步骤:

  1. 模块依赖分析:Webpack 首先会分析所有代码模块,建立一个依赖关系图。这些模块可能是你的业务逻辑代码,也可能是第三方依赖库。Webpack 会使用这个依赖图来决定哪些模块是必须的,哪些模块是可以延迟加载的。

  2. 代码分割(Code Splitting):基于模块依赖图,Webpack 会进行代码分割。它会尝试将应用中不同的功能模块拆分成不同的 chunk 文件。代码分割的策略包括按入口点进行分割(例如分离应用的主入口文件)和按动态导入进行分割(例如通过路由懒加载的模块)。

  1. Chunk Hash 计算:为了让文件名反映内容的变化,每次生成 chunk 文件时,Webpack 都会基于文件的内容计算一个 hash 值,这个值通常会附加在文件名后面。例如 chunk-7QB2PB1Z.mjs 中的 7QB2PB1Z,这个 hash 值确保当模块的内容发生变化时,生成的文件名也会发生变化,这样浏览器就不会从缓存中加载旧文件,而是重新下载新的文件。

  2. 文件输出:最终,Webpack 会将这些拆分的 chunk 文件输出到构建目录中。通常情况下,这些 chunk 文件会放在构建目录中的 dist 目录下,里面包含了主应用文件(例如 main.js),还有按需加载的 chunk 文件(例如 chunk-7QB2PB1Z.mjs)。

懒加载和 Angular Router 的结合

在 Angular 中,懒加载可以非常方便地通过 Angular Router 来实现。为了举个例子,假设你有一个名为 AdminModule 的模块,你想让它在用户导航到 /admin 页面时才加载。你可以这样编写路由配置:

const routes: Routes = [
  {
    path: 'admin',
    loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule)
  }
];

在这个配置中,我们使用了 loadChildren 关键字来指定模块的懒加载。Webpack 在构建时会识别这种动态导入语法(import()),然后将 AdminModule 打包成一个单独的 chunk 文件,例如 chunk-7QB2PB1Z.mjs。当用户真正访问 /admin 页面时,Angular 会发起一个网络请求来加载这个 chunk 文件,从而将 AdminModule 加载到应用中。

这样做有几个好处:

  • 减少初始加载时间:应用的初始加载只需要加载主模块和核心代码,不需要加载所有的功能模块。这意味着用户可以更快地看到页面。

  • 按需加载:只有当用户访问特定的页面时,才会去加载相关的代码文件,从而节省了带宽。

构建工具的配置

为了实现上述的按需加载和代码分割,你需要确保 Angular 项目中使用的是生产模式的构建配置。Angular CLI 已经为你预配置好了生产模式下的代码分割策略。你只需要执行以下命令来构建应用:

ng build --prod

生产模式的构建会自动启用 Tree Shaking(去除无用代码)、代码压缩、以及 chunk 文件的生成。Webpack 会自动根据代码的模块化结构来进行代码分割,将懒加载的模块打包成单独的 chunk。


Tree Shaking 来去除无用代码

Tree Shaking 和按需加载的作用

Tree Shaking 是指在构建时去除代码中那些未使用的部分,从而减少最终输出包的大小。这种优化在 Angular 的构建过程中发挥着重要作用,尤其是在懒加载的模块中。例如,一个模块中可能导入了很多工具函数,但有些函数在某些情况下并没有被使用到。通过 Tree Shaking,Webpack 可以自动识别并移除这些未使用的代码,减少 chunk 文件的体积。

结合懒加载的按需加载机制,应用可以将各个功能模块的代码分割开来,不同的 chunk 文件只在需要时才加载。这样既可以利用 Tree Shaking 移除冗余代码,也可以通过按需加载减少初始页面的代码大小,从而优化用户体验。

实例演示

假设你在 Angular 项目中创建了三个模块:

  • AppModule:主模块。
  • AdminModule:用于管理功能的模块。
  • UserModule:用于用户功能的模块。

你希望 AdminModuleUserModule 都是懒加载的模块,只有当用户点击进入相应页面时才去加载。你可以这样设置路由:

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

通过这种配置,当用户访问 http://yourapp.com/admin 时,Angular 会在后台请求加载 AdminModule 的代码文件。假设生成的 chunk 文件为 chunk-7QB2PB1Z.mjs,这个文件会在 Network 面板中被看到。类似地,当用户访问 http://yourapp.com/user 时,另一个懒加载的 chunk 文件,例如 chunk-8CDE3FGH.mjs,也会被加载。

懒加载的技术优势

在实际的开发中,合理地使用懒加载和代码分割技术,能够显著提升应用的性能。通过将不同功能模块按需加载,Angular 可以:

  1. 减少初始加载的资源:使得主模块体积较小,用户在首次访问应用时可以更快地加载页面,从而缩短白屏时间。

  2. 提高代码可维护性:模块化的代码结构能够将业务逻辑进行分层解耦,便于团队协作开发,也便于未来的扩展和维护。

  3. 节省带宽:只在需要的时候加载特定模块的代码,可以减少用户不必要的网络请求,尤其在网络条件较差的情况下显得尤为重要。

    Angular Lazy-Load mechanism

如何手动控制 Chunk 的生成

虽然 Webpack 和 Angular CLI 会自动进行代码分割,但在某些情况下,你可能需要手动控制哪些模块被分割成 chunk。你可以使用 Webpack 的 SplitChunksPlugin 插件来控制这些细节,例如你想将某些公共模块提取出来作为独立的 chunk 以便多次复用。

例如,你可以在 Angular 项目的 angular.json 文件中配置一些特定的构建选项,来调整代码分割策略。通过这种配置,你可以影响 chunk 的生成方式,例如限制单个 chunk 的大小,或者将一些通用的第三方库提取成单独的文件:

"optimization": {
  "splitChunks": {
    "chunks": "all",
    "maxSize": 200000
  }
}

上述配置告诉 Webpack 将所有模块进行分割,且每个 chunk 的最大大小为 200KB。这种方式可以避免单个 chunk 文件过大,从而减少加载时间。

懒加载在大型应用中的实践

在大型应用中,模块化和懒加载显得尤为重要。通常,大型应用包含多个业务模块,每个模块都可能非常复杂,代码量庞大。将这些模块按需拆分为 chunk 文件,可以有效地避免因代码量过大而导致的首屏加载缓慢问题。

比如,你可以将不同功能模块独立成多个子模块,并且每个子模块内部还可以进一步分成更小的部分。一个电商应用可以将用户模块、商品模块、支付模块等拆分为独立的 chunk 文件,这些模块在初始加载时不会被加载,只有当用户实际使用到相关功能时,才会请求加载相应的代码文件。

此外,Angular 的预加载策略也可以进一步优化用户体验。通过在用户空闲时间加载可能需要的模块,预加载策略可以在用户尚未点击某个功能之前,就已经将该功能所需的代码提前加载好,从而减少用户的等待时间。

你可以在路由中设置预加载策略:

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

在这个例子中,PreloadAllModules 表示 Angular 会在加载主模块之后,利用空闲时间将其他懒加载的模块在后台加载完成,这样当用户实际访问这些模块时,可以直接呈现出来,而不需要额外的等待时间。

总结

chunk-7QB2PB1Z.mjs 文件是 Angular 应用构建过程中生成的一个按需加载的模块文件。它的作用在于实现模块的动态加载,以提高应用的性能和用户体验。这些 chunk 文件是在应用构建过程中,由 Webpack 分析代码依赖关系、进行代码分割和生成文件时产生的。

通过懒加载,Angular 可以显著优化用户体验,减少首屏加载时间和节省带宽,尤其是在大型应用场景下显得尤为重要。同时,通过合理的构建配置和预加载策略,开发者可以进一步提升应用的性能,确保用户在不同网络环境下都能有良好的体验。

相关文章

  • angular的一些服务

    angular的一些服务 $ocLazyLoad $ocLazyLoad是angular的一个懒加载服务,可以按需...

  • ocLazyLoad

    Angular.js 模块按需懒加载 “又到了月底,不得不逼自己写一篇 blog 了,不然底线一旦破了,以后就没有...

  • 用webpack实现模块懒加载、预取/预加载

    模块懒加载本身与webpack没有关系,webpack可以让懒加载的模块代码打包到单独的文件中,实现真正的按需加载...

  • webpack代码分片

    代码分片 按需加载 代码分片与公共模块提取 CommonsChunkPlugin 与 SplitChunksPlu...

  • .webpack4.x 配置篇

    webpack 是一个打包工具,进行代码分割,模块通过loader处理各种文件,模块打包器,按需加载,使初始化加载...

  • ng-bind-html的用法总结

    angular中的$sanitize这个服务.此服务依赖于ngSanitize模块.(这个模块需要加载angula...

  • Angular2 -- SystemJS解析

    SystemJS SystemJS是一个通用的动态模块加载器,Angular2就是通过SystemJS加载所需的模...

  • WEB性能优化的常用方法

    1、压缩JS可以减少加载时间。 2、模块打包可以减少文件加载次数。 3、按需加载图片、视频等。 4、缓存。 5、C...

  • angular+require按需加载

    index.html main.js index.js 启动angular

  • webpack配置中常用的CommonsChunkPlugin认

    CommonsChunkPlugin主要是用来提取第三方库和公共模块,避免首屏加载的bundle文件或者按需加载的...

网友评论

      本文标题:关于 Angular 模块按需加载的讨论

      本文链接:https://www.haomeiwen.com/subject/ycqndjtx.html