Angular에서는 PWA를 매우 쉽게 적용할 수 있습니다. Cli에서 단순히 추가만 하면 알아서 필요한 요소들이 모두 설정되기 때문입니다.
이번 시간은 생성된 프로젝트에 PWA를 적용하고 작동여부 확인 테스트까지 진행해보겠습니다.
먼저 프로젝트를 하나 생성합니다. 기존 프로젝트가 있으면 이 과정을 스킵해도 됩니다.
ng new project-pwa
생성된 프로젝트에 아래와 같이 pwa를 추가합니다. --project 옵션 뒤에 프로젝트 명을 붙입니다.
ng add @angular/pwa --project [project-pwa]
정상적으로 추가가 되었으면 아래의 파일을 확인합니다. 아래의 파일이 모두 확인되면 이미 pwa가 프로젝트에 적용된 것입니다.
프로젝트 최초 시작 모듈 (기본으로 AppModule로 되어 있음)을 확인하여 아래와 같거나 유사한 코드가 있는지 확인합니다.
버전에 따라 다를 수 있으므로 만일 없으면 아래와 같이 추가하여야 합니다.
import { ServiceWorkerModule } from '@angular/service-worker';
@NgModule({
declarations: [],
imports: [
ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })
],
providers: [],
})
export class AppModule { }
최초로 로딩되는 component에 버전업 체크 코드를 넣어 앱의 버전이 변경되었을 때 이를 감지하는지 확인합니다.
import { Component, OnInit } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
updateMessage: string;
constructor(
private swUpdate: SwUpdate
) {
}
ngOnInit() {
if ('serviceWorker' in navigator) {
console.log('service worker!!!!!!!!!!!!!');
if (this.swUpdate.isEnabled) {
this.swUpdate.available.subscribe(() => {
if (confirm('New version available. Load New Version?')) {
window.location.reload(); // 재시작하면 캐시된 데이터를 버리고 새 버전의 코드를 불러와 적용한다.
}
});
}
}
else {
console.log('service worker is not ready');
}
}
}
빌드는 환경에 따라 기존과 동일하게 빌드합니다.
ng build --prod
아래의 과정대로 테스트를 진행합니다.
이 테스트에서 유의할 점은 수정한 코드를 업로드한다고 즉시 인식하지 않는다는 점입니다.
이는 Angular의 정책상 적용 시간에 유예를 준 것인데 이를 수정하려면 pwa 관련 코드에서 SwUpdate 부분을 수정하면 됩니다.
캐시 데이터를 직접 수정할 수도 있습니다.
ngsw-config.json의 external을 수정하면 되는데 원하는 캐시데이터를 추가하거나 삭제하면 됩니다.
"external": {
"urls": [
{"url": "https://fonts.googleapis.com/..."},
{"url": "https://fonts.gstatic.com/s/..."}
]
}
반대로 아래와 같이 캐시 금지를 적용할 수도 있습니다.
{
"name": "offline",
"urls": { "https://mysite.com/data.json": {"match": "prefix"}},
"cache": {
"optimizeFor": "freshness",
"maxAgeMs": 360000000,
"maxEntries": 1,
"strategy": "lru"
}
}