Lazy Loading은 초기 로딩 시간을 줄여주는 역할을 하는 장점이 있지만, 해당 페이지가 로딩될 때 SPA의 특징인 즉시 페이지가 변경되는 빠른 로딩이 되지 않는다는 문제가 있습니다.
이 두 가지를 모두 만족하는 방법은 없을까요?
여기 PreloadAllModules와 QuicklinkStrategy 라는 두 가지 방안을 제시합니다.
기존의 모든 모듈을 전부 로딩하는 방법과는 다르게 초기 로딩 시 모든 모듈을 실행 가능한 최소한의 양만 로드하여 대기하는 방법입니다.
이 방법은 매우 유용하며 빠른 속도와 기존보다 매우 작은 양의 네트워크 사용량을 가집니다.
그러나 대규모의 프로젝트에서는 여전히 많은 양의 네트워크 사용량을 필요로 하며,
라우터는 모든 사전 로드된 모듈에 경로를 등록해야하기 때문에,
UI 스레드에서 집중적인 계산을 유발하고 사용자 경험 저하를 초래할 수 있습니다.
따라서, 라우터가 적은 소규모의 프로젝트에 추천합니다.
최초 RouterModule.forRoot를 선언할 때 옵션을 설정해주면 되며,
PreloadAllModules는 @angular/roter에 내장되어 있습니다.
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
],
exports: [RouterModule]
})
export class AppRoutingModule {}
QuicklinkStrategy는 Angular 기본 라이브러리가 아니므로 npm을 통해 다운 받아야 합니다.
npm i ngx-quicklink --save
QuicklinkStrategy는 대규모의 프로젝트에서 더 나은 대안일 수 있습니다.
동작원리는 다음과 같습니다.
- IntersectionObserver Api를 통해 로직 화면에 표시되는 routerlink를 찾아냅니다.
- requestIdleCallback을 통해 브라우저가 안정화 될 때까지 대기합니다.
- navigator.connection.effectiveType을 통해 유저가 느린 연결 상태이거나 navigator.connection.saveData를 통해 데이터-절약 가능상태 (data-saver) 인지 파악합니다.
- Angular의 사전 판독 계획 (prefetching strategy)을 통해 lazy load될 모듈을 준비합니다.
QuicklinkStrategy는 quicklink와 3가지 면에서 다른 점이 있습니다.
- quicklink는 가능한 경우 link[rel="prefetch"] 를 통해 리소스를 미리 가져오고, 그 뒤에 XMLHttpRequest로 대체하지만, ngx-quicklink는 Angular 라우터의 현재 모듈을 preloading 하는 원리(mechanism) 때문에 XMLHttpRequest만 사용합니다. 비록 Guess.js에서 사용하는 것과 같은 link[rel="prefetch"]를 사용하는 것이 더 나은 대안일 수 있으나 대부분의 경우에 유저들은 이 점을 발견하지 못할 것입니다.
- ngx-quicklink는 단지 관련 스크립트 번들만 다운로드하는 것이 아니라 컨텐츠를 파싱하고 평가합니다. 이 방법은 유저가 페이지를 변경할 때 성능의 큰 향상을 가져옵니다.
- ngx-quicklink는 모든 요청된 모듈을 사전 로드하기 위해 모든 부모 모듈을 다운로드 합니다.
최초 RouterModule.forRoot를 선언할 때 옵션을 설정해주면 되며,
ngx-quicklink에서 import 해야 합니다.
import { RouterModule, Routes } from '@angular/router';
import { QuicklinkStrategy } from 'ngx-quicklink';
@NgModule({
imports: [
RouterModule.forRoot(routes, { preloadingStrategy: QuicklinkStrategy })
],
exports: [RouterModule]
})
export class AppRoutingModule {}
최신 Angular의 독립형 API 환경에서는 NgModule 대신 app.config.ts에서 라우팅을 설정합니다. provideRouter 함수와 withPreloading이라는 라우터 기능을 사용하여 Preloading 전략을 적용합니다.
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter, withPreloading, PreloadAllModules } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
// withPreloading 기능과 함께 PreloadAllModules 전략을 전달합니다.
provideRouter(routes, withPreloading(PreloadAllModules))
]
};
ngx-quicklink 라이브러리는 독립형 API를 위해 provideQuicklink라는 프로바이더 함수를 제공합니다.
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter, withPreloading } from '@angular/router';
// ngx-quicklink에서 필요한 프로바이더와 전략을 임포트합니다.
import { provideQuicklink, QuicklinkStrategy } from 'ngx-quicklink';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes, withPreloading(QuicklinkStrategy)),
// Quicklink 기능을 애플리케이션에 제공합니다.
provideQuicklink()
]
};