Angular Service Workerを既存のプロジェクトに統合しようとしています。正しく理解できた場合、データがAngular SWにキャッシュされる方法は2つあります。資産データをプリフェッチまたは遅延更新し、特定のAPI呼び出しやその他のXHRリクエストをキャッシュすることができます。
私が達成しようとしているのは、ネットワークを介して特定のアセットを最初にロードすることです。リクエストがタイムアウトになるか、アクセスできない場合、キャッシュを介して処理されます。 API呼び出しをキャッシュするときのfreshness
戦略と同じです。しかし、AngularプロジェクトでアセットとしてロードされるJSファイルに対して、このようなフレッシュネスロードメカニズムを設定する方法はないようです。テスト用のサンプルプロジェクトをセットアップしました:- https://github.com/philipp-schaerer-lambdait/angular-service-worker-test
次の例は標準のAngular Appであり、作業中の実際のプロジェクトは含まれていませんが、キャッシュしたい要素を示しています。構造は次のようになります。
\_ Angular root
|_ src/
|_ index.html <----------- links to excluded_asset.js
|_ app/
|_ assets/
|_ excluded_asset.js <-- this one is excluded in ngsw-config.json
|_ included_asset.js
|_ ...
ここで関連する構成:
ngsw-config.json
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": ["/assets/**", "!/assets/excluded_asset.js"]
}
}
]
}
アセットにfreshness
とinstallMode
を使用して、updateMode
戦略のようなキャッシュ動作を実現することは可能ですか?
アセットキャッシュから除外しようとしましたが、ネットワーク経由でロードされましたが、オフラインになった後は明らかにサービスワーカーによって配信されません。
その後、dataGroups
を介して再度追加しようとし、戦略をfreshness
に設定しましたが、アセット構成から除外されると、アセットは再度キャッシュされないようです。また、このファイルにdataGroups
設定を使用できるとは思わない。
"dataGroups": [
{
"name": "config",
"urls": ["assets/excluded_asset.js"],
"cacheConfig": {
"maxSize": 10,
"maxAge": "1d",
"timeout": "100",
"strategy": "freshness"
}
}
}
何かを見逃したか、freshness
戦略でアセットをキャッシュする方法はありませんか?ファイルを移動しないか、ファイルの要求方法を変更することをお勧めします。
編集
キャッシュされたアセットディレクトリの外に移動してdataGroups
設定に含めようとしましたが、動作しませんでした。
サービスワーカーを使用した新しいアプリ
コマンドは次のようになります。
ng new myApp --service-worker (or using the alias — -sw )
このサービスワーカーフラグを使用すると、Angular CLI 1.6が自動化を行います。
とにかく、CLI 1.6がリリースされた後でも、NGSWサポートを既存のアプリに追加するには手動で実行する必要があるため、これらの手順を再現する方法を知っておくとよいでしょう。 Angular Service WorkerをPWAtterに追加しましょう。
Angular Service Workerを既存のアプリに追加する
上記と同じ4つの手順を手動で実行してみましょう。
1。 NGSWのインストール
npm install @angular/service-worker --save
2。ビルドサポートを有効にします(Angular CLI 1.6のみ、以下の通知を参照してください)
ng set apps.0.serviceWorker=true
または、.angular-cli.json
ファイルでこのパラメーターを手動で追加/編集します。
重要!とりあえず、Angular CLI 1.5を使用する場合は、
.angular-cli.json
にこのプロパティがないことを確認してください。ビルドエラーが発生します。このステップをエミュレートする方法については、以下のAngular CLI 1.5をご覧ください。
3。 AppModule
にNGSWを登録します。これは、Angular CLI 1.6での表示方法です。
import { ServiceWorkerModule } from '@angular/service-worker'
import { environment } from '../environments/environment';
...
@NgModule({
imports: [
...
environment.production ? ServiceWorkerModule.register('/ngsw-worker.js') : []
],
...
})
export class AppModule { }
4。 NGSW構成ファイルを作成します(デフォルト名はsrc/ngsw-config.jsonです)。デフォルトのコンテンツはAngular CLI 1.6によって生成されます。
{
"index": "/index.html",
"assetGroups": [{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html"
],
"versionedFiles": [
"/*.bundle.css",
"/*.bundle.js",
"/*.chunk.js"
]
}
}, {
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**"
]
}
}]
}
現時点では、Angular CLI 1.5を使用している間、ステップ2からビルドサポートをエミュレートする必要があります。実際には、ng build --prod
コマンドに加えて、2つの追加アクションを実行する必要があります。 NGSWを使用するには!):
NGSW CLI ngsw-configを使用して、NGSW構成ファイルsrc/ngsw-config.jsonに基づいてNGSW制御(マニフェスト)ファイルngsw.jsonを生成します。
NGPM自体をnpm_modulesパッケージフォルダーからdistフォルダーにコピーします。
NGSWサポートを使用して実稼働ビルドを生成する簡単なコマンドを1つ作成するには、npmスクリプトを追加します。
{
...
"scripts": {
...
"ngsw-config": "node_modules/.bin/ngsw-config dist src/ngsw-config.json",
"ngsw-copy": "cp node_modules/@angular/service-worker/ngsw-worker.js dist/",
"build-prod-ngsw": "ng build --prod && npm run ngsw-config && npm run ngsw-copy",
"serve-prod-ngsw": "npm run build-prod-ngsw && http-server dist -p 8080"
}
}
ここでnpm run build-prod-ngsw
を実行すると、Angular PWAがdist
フォルダーに格納されます。オプションで、http-server
を実行することにより、最も簡単なnpm run serve-prod-ngsw
を使用してサービスを提供できます。
重要!
ng serve
を使用してAngular Service Workerをテストしないでください。この開発サーバーは、PWAフローと連携して動作するようには設計されていません。アプリの製品版を常にビルドし、静的Webサーバーを使用して配布フォルダーから提供します。
アプリケーションシェル
上記のアクションを実行してnpm run build-prod-ngsw
を実行すると、デフォルトのAngular PWAの準備が整います。アプリケーションをデプロイするか、静的Webサーバーを使用してローカルで実行します(私の場合はhttp-server
パッケージ、ビルドして提供するにはnpm run serve-prod-ngsw
を実行します)。
オフラインになった後、アプリケーションは動作します。どうして? NGSWは、構成ファイルのassetGroupsセクションにリストされているすべてのリソースをキャッシュしたため、現在はレコードでいっぱいのキャッシュストレージからリソースを提供する責任があります。
Service Workerは登録済みでアクティブです
キャッシュされた応答のコンテンツを表示できます(現時点でChrome Canaryでのみ使用可能)
NGSWは、キャッシュストレージを使用して、HTTP応答データと一部のメタデータの両方を保存し、バージョン管理を処理します。
NGSWによるストレージのタイプ
:cache
のエントリ—実際のHTTP応答。:meta
が付いたエントリ—バージョン管理メタ情報を保存します。後でこの種類の保存データはindexedDB
に移動される可能性があります。DevToolsを開いたままにしておくと、キャッシュワーカーセクション内のエントリは、おそらくサービスワーカー側からの各アクションの後に自動的に更新されません。実際のデータを表示する場合は、右クリックして[キャッシュの更新]を選択します。
右。 NGSW構成ファイルのデフォルト形式では、マテリアルアイコンwebfontを使用しているため、このケースでは不十分です。明らかに、これらのリソース(対応するCSSおよびWOFF2ファイル)はNGSWによってキャッシュされませんでしたが、デフォルトのassetGroups
およびapp
に加えてassets
にもう1つのグループを追加することで簡単に修正できます。それをfonts
と呼びましょう:
{
...
"assetGroups": [
...
{
"name": "fonts",
"resources": {
"urls": [
"https://fonts.googleapis.com/**",
"https://fonts.gstatic.com/**"
]
}
}]
}
フォントファイルの正確なURLはウェブフォントのバージョン管理をサポートするために随時変更される可能性があるため、globs構文を使用してこれらのリソースを指定することは理にかなっています。また、installMode
もupdateMode
も指定していないことに気付くかもしれません。一方で、これはデフォルト値であるため、結果のNGSW制御ファイルでは両方がprefetch
として設定されます。一方、urls
- wayの詳細はリソースをリストするため、リクエストされた後にのみキャッシュされます。
再構築して実行し、オフラインモードに切り替えた後、すべてのアイコンが配置されたアプリケーションの通常の状態が表示されます。
キャッシュストレージに2つの新しいエントリが表示されます。
NGSWによって生成されたストレージ
キャッシュされたフォントをプレビューすることもできます。
assetGroups
とdataGroups
には根本的な違いがあります。
assetGroups
は、アプリの[シェル]バージョンを追跡しています。dataGroups
はアプリのバージョンに依存しません。それらは独自のキャッシュポリシーを使用してキャッシュされ、APIレスポンスを処理するのに適切なセクションです。ランタイムキャッシング
/timeline
APIエンドポイントにNetwork-First戦略を使用し、/favorites
エンドポイントにCache-First戦略を使用します。 src/ngsw-config.json
の対応するセットアップは次のようになります。
{
...
"dataGroups": [{
"name": "api-freshness",
"urls": [
"/timeline"
],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "3d",
"timeout": "10s"
}
},
{
"name": "api-performance",
"urls": [
"/favorites"
],
"cacheConfig": {
"strategy": "performance",
"maxSize": 100,
"maxAge": "3d"
}
}
]
}
NGSWの動作を定義するメインスイッチがあります:cacheConfig / strategy
。ネットワーク優先戦略の場合、freshness
、キャッシュ優先-の場合— performance
。
APIレスポンスを取得してキャッシュし、オフラインに切り替えるには、ビルド、提供、タイムラインのロードボタン、お気に入りのロードボタンの順にクリックします。
オンラインモードの最適化について。オンラインに戻り、Timeline / Favorites
を1回または2回クリックします。ネットワークトリップ全体をスキップしてキャッシュからデータを取得したからといって、お気に入りがすぐに読み込まれることは明らかです。キャッシュする期間を指定するにはcacheConfig
セクションの設定を使用して—詳細な制御があります。
NGSWは、いくつかの非常にスマートなネットワーク最適化で私たちを大いに助けてくれました。
私も同じ問題を抱えています。私が見つけた解決策は、常に最新のjsファイルとcssファイルを持っていることが、キャッシュされたアセットからindex.htmlを除外することです。
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"updateMode": "prefetch",
"resources": {
"files": [
"/*.css",
"/*.js",
"!/index.html" // Right here!!!!!
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "lazy",
"resources": {
"files": ["/static/**"]
}
}
]
}
"outputHashing": "all",
to angular= build configuration。コードを変更すると、別の名前のファイルが生成されます。スクリプトタグ(またはリンクタグ)が自動的に追加されます)htmlファイル(サービスワーカーは無視します)に変更をプロダクションにプッシュすると、index.htmlは新しいjsファイルとcssファイルを指します。
もちろん、これは非常に明白な方法です。index.htmlはサービスワーカーによってキャッシュされませんが、少なくともユーザーに最新のファイルをまっすぐに提供することができます。
アセットにも「鮮度」オプションがある方法があればいいのにと思いました...