在 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'],
        },
      })
    })
  }
}

这就是全部了。

广告
将在 10 秒后关闭
bannerAds