在 Angular Universal 应用程序中使用 webfontloader
使用webfontloader进行异步加载比使用link标签加载web字体可以提高PageSpeed Insights的得分。
所以,让我们在Angular中尝试使用webfontloader吧。
如果像 Angular Universal 这样进行 SSR (服务器端渲染),需要做一些额外的调整,否则会出现错误,请参考本文。
我们在GitHub上准备了示例代码。请实际运行一下。
这篇文章总结了出现在这篇文章中的命令。也请看这里。
前提 (paraphrased in Mandarin Chinese) :
假设
-
- Angular 9.1.12
- Angular Universal 9.1.11
使用Web字体加载器(webfontloader)在某个应用程序中使用Web字体。
Vocabulary:
準備 – to prepare, preparation
Paraphrased sentence:
做好準備 (zuò – to make necessary preparations
使用npm i webfontloader –save进行安装。
建议您在安装的时候也使用 `npm i @types/webfontloader –save-dev` 来安装类型定义。
首先试着正常使用一下
在没有使用Angular Universal进行服务器端渲染(SSR)的应用程序中,尝试使用webfontloader。
import { Component, OnInit } from '@angular/core'
import * as WebFont from 'webfontloader'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
ngOnInit() {
WebFont.load({
google: {
families: ['Modak', 'M+PLUS+1p:400,900'],
},
})
}
}
让我们在AppComponent的ngOnInit中尝试调用这样的方法。
如果在 CSS 中添加 font-family: Modak;,字体将会被应用。
使用APP_INITIALIZER
如果需要在整个应用程序中加载,那么请在应用程序初始化时使用APP_INITIALIZER进行webfontloader的设置。
通过ng g service app-init创建AppInitService,并进行以下修改。
import { Injectable } from '@angular/core'
import * as WebFont from 'webfontloader'
export function AppInitFactory(appInit: AppInitService) {
return () => appInit.init()
}
@Injectable({
providedIn: 'root',
})
export class AppInitService {
constructor() {}
init() {
this.initWebFont()
}
private initWebFont() {
WebFont.load({
google: {
families: ['Modak', 'M+PLUS+1p:400,900'],
},
})
}
}
接下来,我们需要修改 app.module.ts 文件。
import { BrowserModule } from '@angular/platform-browser'
import { NgModule, APP_INITIALIZER } from '@angular/core'
import { AppComponent } from './app.component'
import { AppInitService, AppInitFactory } from './app-init.service'
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
providers: [
// 以下を追加
{
provide: APP_INITIALIZER,
useFactory: AppInitFactory,
multi: true,
deps: [AppInitService],
},
],
bootstrap: [AppComponent],
})
export class AppModule {}
這樣就會在應用程序初始化時添加連結標籤。
使用Angular Universal 进行服务器端渲染 (SSR)。
在使用 ng add @nguniversal/express-engine 命令后,尝试运行 npm run dev:ssr 命令来启动应用程序。
然而,如果继续保持现状,会出现 ReferenceError: window is not defined 错误,从而无法启动服务器,因此我们需要修正之前的代码。
为了适应Angular Universal 进行的修改
我們將修改已經創建的 app-init.service.ts,使其如下所示。
import { Injectable, Inject, PLATFORM_ID } from '@angular/core'
import { isPlatformServer } from '@angular/common'
export function AppInitFactory(appInit: AppInitService) {
return () => appInit.init()
}
@Injectable({
providedIn: 'root',
})
export class AppInitService {
constructor(@Inject(PLATFORM_ID) private platformId: Object) {}
init() {
this.initWebFont()
}
private initWebFont() {
// SSRの場合は実行しないように
if (isPlatformServer(this.platformId)) {
return
}
// ここでimportしないとReferenceError: window is not definedになる
import('webfontloader').then((WebFont) => {
WebFont.load({
google: {
families: ['Modak', 'M+PLUS+1p:400,900'],
},
})
})
}
}
这就是全部了。