Tree Shakeable Providers and Services in Angular

Angular 最近推出了一项新功能,Tree Shakeable Providers。 Tree Shakeable Providers 是一种定义服务和其他东西的方式,以一种可以提高 Angular 应用程序性能的方式被 Angular 的依赖注入系统使用。

首先,在我们深入挖掘之前,让我们先定义一下摇树。摇树是构建过程中的一个步骤,它从代码库中删除未使用的代码。删除未使用的代码可以被认为是“摇树”,或者您可以想象一棵树的物理摇晃和剩余的枯叶从树上掉下来。通过使用摇树,我们可以确保我们的应用程序只包含我们的应用程序运行所需的代码。

例如,假设我们有一个实用程序库,其中包含函数 a()、b() 和 c()。在我们的应用程序中,我们导入并使用函数 a () 和 c () 但不使用 b ()。我们希望 b() 的代码不会被捆绑并部署给我们的用户。摇树是从我们发送到用户浏览器的已部署生产代码中删除函数 b() 的机制。

为什么过去版本的 Angular 中,服务已经不能被摇树优化?这其实又回到了我们如何在 Angular 的早期版本中注册 Service 的问题。让我们看一个示例,说明我们如何在以前的 Angular 版本中注册一个用于依赖注入的服务。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';import { AppComponent } from './app.component';
import { SharedService } from './shared.service';@NgModule({imports: [BrowserModule, FormsModule],declarations: [AppComponent],bootstrap: [AppComponent],providers: [SharedService]
})
export class AppModule {}

如您所见,我们导入了服务并将其添加到我们的 Angular AppModule。 这会将服务注册到 Angular 的依赖注入系统。 每当组件请求使用此服务时,Angular 的 DI 将确保创建 Service 及其任何依赖项并将其传递给组件的构造函数。

此注册系统的问题在于,构建工具和编译器很难确定我们的应用程序中是否使用了此代码。

摇树系统删除代码的主要方式之一是查看我们定义的导入路径。 如果类或函数未导入,则不会包含在我们提供给用户的生产代码包中。如果它是导入的,则摇树器假定它正在应用程序中使用。在我们上面的示例中,我们在 AppModule 中导入和引用我们的服务,导致显式依赖项不能被摇树优化掉。

Angular Tree Shaking Providers

使用 Tree Shaking Providers (TSP),我们可以使用不同的机制来注册我们的服务。 使用这种新的 TSP 机制将提供摇树性能和依赖注入的好处。 我们有一个带有特定代码的演示应用程序来演示我们如何注册这些服务的不同性能特征。 让我们来看看新的 TSP 语法是什么样的。

import { Injectable } from '@angular/core';@Injectable({providedIn: 'root'
})
export class SharedService {constructor() {}
}

在@Injectable 装饰器中,我们有一个名为providedIn 的新属性。有了这个属性,我们可以告诉 Angular 将我们的服务注册到哪个模块,而不必导入模块并将其注册到 NgModule 的提供者。也就是说,不需要像旧版本的 Angular 那样,在 AppModule 里显式 import 服务,并添加到 NgModule 的 providers 数组里。

默认情况下,此语法将其注册到根注入器,这将使我们的服务成为应用程序范围的单例。 对于大多数用例,根提供程序是合理的默认值。 如果您仍然需要控制服务实例的数量,Angular 模块和组件上的常规提供程序 API 仍然可用。

使用这个新 API,您可以看到,由于我们不必将服务导入 NgModule 进行注册,因此我们没有明确依赖。 因为没有 import 语句,构建工具可以确保该服务仅在组件使用时才捆绑在我们的应用程序中。 让我们看一个示例应用程序。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { Shared3Service } from './shared3.service';@NgModule({imports: [BrowserModule,FormsModule,RouterModule.forRoot([{ path: '', component: HelloComponent },{path: 'feature-1',loadChildren: () => import('./feature-1/feature-1.module').then(m => m.Feature1Module)},{path: 'feature-2',loadChildren: () => import('./feature-2/feature-2.module').then(m => m.Feature2Module) }}])],declarations: [AppComponent, HelloComponent],bootstrap: [AppComponent],providers: [Shared3Service]
})
export class AppModule {}

在这个示例应用程序中,我们有三个组件; 两个是延迟加载的模块,而一个是我们的着陆主页组件。 我们还将在应用程序中使用三种不同的服务。 让我们从第一个服务开始,看看它是如何使用的。

import { Injectable } from '@angular/core';console.log('SharedService bundled because two components use it');@Injectable({providedIn: 'root'
})
export class SharedService {constructor() {console.log('SharedService instantiated');}
}

我们的第一个服务使用 tree shakable providers API。 我们在每个延迟加载的功能模块中导入此服务两次,如下所示。

import { Component, OnInit } from '@angular/core';
import { SharedService } from './../shared.service';@Component({selector: 'app-feature-1',templateUrl: './feature-1.component.html',styleUrls: ['./feature-1.component.css']
})
export class Feature1Component implements OnInit {constructor(private sharedService: SharedService) {}ngOnInit() {}
}

因为我们的两个组件中都使用了服务 1,所以代码被加载并捆绑到我们的应用程序中。 如果我们检查控制台,我们会看到以下消息:

SharedService bundled because two components use it

第二个服务:

import { Injectable } from '@angular/core';console.log('Shared2Service is not bundled because it not used');@Injectable({providedIn: 'root'
})
export class Shared2Service {constructor() {}
}

如果我们检查控制台,我们不会看到日志消息。 这是因为我们的功能模块或组件中均未使用此服务。 由于它没有被使用,所以没有捆绑和加载代码。

最后,我们类似于前两个服务的第三个服务如下所示:

import { Injectable } from '@angular/core';console.log('Shared3Service bundled even though not used');@Injectable()
export class Shared3Service {constructor() {}
}

console 信息:

Shared3Service bundled even though not used

因为 Shared3Service 是使用较旧的提供程序 API 注册的,所以由于需要注册的 import 语句,它会创建显式依赖项。即使没有组件使用它,import 语句也会导致构建系统包含并加载此代码。

在这三个服务之间,我们可以看到摇树系统如何在我们的应用程序中包含或删除代码的特征。使用 TSP API,我们的服务仍然是单例的,即使对于我们示例中的延迟加载模块中使用的服务。如果我们加载示例应用程序,我们会注意到,如果我们在功能一和功能二之间路由,则 SharedService 中的控制台日志只会被调用一次。一旦请求模块,Angular 将实例化并确保该实例在应用程序的剩余生命周期中使用。

Angular Tree Shakeable Providers 为我们的应用程序提供了更好的性能,并减少了创建可注入服务所需的样板代码量。

Angular 应用里的摇树优化 - tree shaking相关推荐

  1. tree shaking(摇树优化)

    tree shaking(摇树优化) 前言 随着js的不断发展,性能优化成了主流的方向,但是如何性能优化又成了现在程序员的一大苦恼,而我作为一名前端小白,也就深陷其中,最近学习到了tree shaki ...

  2. 手写小程序摇树优化工具(三)——遍历json文件

    见素包朴,少私寡欲,绝学无忧 github: miniapp-shaking 上一章我们介绍了遍历js文件的方法,接下来我们介绍其他文件的遍历. 1. 遍历JSON文件 对于json文件,我们直接读取 ...

  3. webpack 如何优雅的使用tree-shaking(摇树优化)

    webpack 如何优雅的使用tree-shaking 1.什么是tree-shaking webpack 2 的到来带来的最棒的新特性之一就是tree-shaking .tree-shaking源自 ...

  4. Angular 项目中的可摇树依赖 - Tree-shakable dependencies

    Tree-shakable dependencies in Angular projects Tree-shakable 依赖更容易推理和编译成更小的包. Angular 模块 (NgModules) ...

  5. webpack构建中tree shaking、scope Hoisting(面试题)

    一.tree shaking (摇树优化) tree shaking概念: 1个模块可能有多个方法,只要其中某个方法使用了,整个文件会被打到bundle中 tree shaking 只将用到的方法打到 ...

  6. dce和tree shaking

    dce和tree shaking 为了在弱网环境下降低网络延迟以获取更好的用户体验,我想这些关于如何降低代码体积的技术都是值得研究的.目前降低网络延迟的一个方法是降低js代码的体积,本文研究的就是在压 ...

  7. webpack中的tree shaking(树摇)-----移除未使用的代码

    本篇大致概括一下tree shaking的作用以及与webpack相结合使用 什么是tree shaking 引用webpack官网的原文来说: tree shaking 是一个术语,通常用于描述移除 ...

  8. P1047 校门外的树(线段树优化)(校门三部曲)难度⭐⭐

    校门三部曲,总算完结了!完结散花! 难度呈阶梯状,都可以用线段树解决. 第一部 P1047 校门外的树(线段树优化)难度⭐⭐ 第二部 P1276 校门外的树(增强版)(线段树)校门三部曲难度⭐⭐⭐ 第 ...

  9. 图文详解哈希树-Merkle Tree(默克尔树)算法解析

    2019独角兽企业重金招聘Python工程师标准>>> Merkle Tree概念   Merkle Tree,通常也被称作Hash Tree,顾名思义,就是存储hash值的一棵树. ...

最新文章

  1. 缓存与库先写哪个,这十几张图告诉你
  2. Net设计模式之简单工厂模式(Simple Factory Pattern)
  3. redis集群之哨兵模式【原】
  4. Linux 学习笔记_10_Shell编程_2_Shell编程语法(三)
  5. fetch + async await 使用原生JS发送网络请求
  6. 台式计算机固定资产属于哪类,电脑属于固定资产的哪一类
  7. access() 函数 c++
  8. pythonmt4通讯swot矩阵_最经典的市场部SWOT分析矩阵
  9. 排列组合的一些公式及推导
  10. 超实用后台UI模板有这些就够了!(二)
  11. 只是一个文件节点类为了项目的数据处理
  12. win11安装低版本CAD报致命错误解决方案
  13. css多栏布局(双栏布局、三栏布局、圣杯布局、双飞翼布局)
  14. 美团饿了吗CPS红包,别人领红包下单,你拿推广佣金(送源码)
  15. LCD液晶驱动芯片VK0192M LQFP44电路图/技术资料简介
  16. 高级赚钱思维,降维打击,思维上比你高一维度的人吃掉你的蛋糕,你连察觉就没察觉到。...
  17. vs打开别人cpp_网恋奔现遇到现实版乔碧萝,怀疑她拿了别人的照片……
  18. Mobileye采用单目摄像头做ADAS太不精确?用双目摄像头的“中科慧眼”认为双目测距算法才是最精确的
  19. 原滴滴AI Labs负责人叶杰平加入贝壳找房,出任首席科学家
  20. 科普 | 焦距篇 | 相机焦距到底是什么 | 为什么手机总是拍不出人眼看到的?

热门文章

  1. ROS wiki安装及配置
  2. 全志A10s芯片用户手册
  3. matlab 鼠标响应函数,关于matlab鼠标响应
  4. iOS简易蓝牙对战五子棋游戏设计思路之二——核心棋盘逻辑与胜负判定算法
  5. 掌握Quick Basic编程的,都是OS操作系统自编程的精英人才
  6. linux 开机速度 固态,Windows/Linux系统开机OCZ胜出
  7. 计算机物流管理,大学饮食管理计算机物流管理程序作用
  8. 告别极寒,科学家突破将量子计算机运行最低温提了15倍
  9. phpcms mysql debug_phpcms教程之mysql配置优化
  10. C++把一个字符转换成string方法