Angular アプリケーション高速化:ng cacheとクライアントサイドキャッシュ
ng cache の主な目的
- リソースの効率的な利用
同じファイルを何度もコンパイルする必要がなくなるため、CPU やメモリなどのリソースを効率的に利用できます。 - ビルド時間の短縮
キャッシュを利用することで、以前のビルドで生成された成果物を再利用し、不要な再コンパイルや処理をスキップできます。これにより、特に大規模なアプリケーションや頻繁にビルドを行う場合に、ビルド時間を大幅に短縮できます。
ng cache の主なコマンドと機能
ng cache path
: キャッシュが保存されているディレクトリのパスを表示します。ng cache list
: 現在のキャッシュの設定や保存場所などの情報を表示します。キャッシュが有効になっているか、どのディレクトリに保存されているかなどを確認できます。ng cache clean
: キャッシュを完全にクリアします。キャッシュが破損している疑いがある場合や、強制的にすべてのファイルを再ビルドしたい場合に実行します。ng cache off
: キャッシュ機能を無効にします。キャッシュが原因で予期せぬ問題が発生する場合などに、一時的に無効にすることがあります。ng cache on
: キャッシュ機能を有効にします。Angular CLI のデフォルト設定ではキャッシュは有効になっていますが、明示的に有効にしたい場合にこのコマンドを使用します。
キャッシュの仕組みの簡単なイメージ
Angular CLI がアプリケーションをビルドする際、処理されたファイルや生成されたコードを特定の場所に保存します。次回のビルド時に、Angular CLI はまずキャッシュを確認し、変更されていないファイルについてはキャッシュされたものを再利用します。変更されたファイルのみが再度処理され、その結果がキャッシュに更新されます。
- まれに、キャッシュされた古い情報が原因でビルドが失敗したり、予期せぬ動作をすることがあります。そのような場合は、
ng cache clean
コマンドでキャッシュをクリアすることで問題が解消されることがあります。 - キャッシュは通常、プロジェクトごとではなく、グローバルに管理されます。つまり、複数の Angular プロジェクトで共通の依存関係がある場合、それらは一度だけキャッシュされます。
一般的なエラーとトラブルシューティング
キャッシュされた古い情報によるビルドエラー
- トラブルシューティング
- ng cache clean を実行する
これが最も一般的な解決策です。キャッシュを完全にクリアし、次回のビルドで新しいファイルが生成されるようにします。ng cache clean
- --no-cache オプションを使用する
一度だけキャッシュを使用せずにビルドを実行したい場合に便利です。
またはng build --no-cache
ng serve --no-cache
- node_modules と package-lock.json (または yarn.lock) を削除して再インストールする
依存関係の問題が疑われる場合は、これらのファイルを削除し、npm install
またはyarn install
を実行して依存関係を再インストールします。その後、再度ng build
やng serve
を試します。
- ng cache clean を実行する
- 原因
- Angular CLI が古いキャッシュされたファイルを使用している。
- 依存関係のアップデートがキャッシュに正しく反映されていない。
- 症状
- 最近コードを変更したにもかかわらず、古いバージョンのコードがビルド結果に反映される。
- ライブラリをアップデートしたのに、古いバージョンのまま動作する。
- 原因不明のビルドエラーが発生する。
キャッシュディレクトリへのアクセス権の問題
- トラブルシューティング
- キャッシュディレクトリの権限を確認・修正する
ng cache path
でキャッシュディレクトリのパスを確認し、OS のコマンド(例:chmod
(Linux/macOS), 管理者権限での実行 (Windows))を使用して適切なアクセス権を設定します。 - 他のプロセスがキャッシュディレクトリを使用していないか確認する
他の Angular CLI のプロセスや、キャッシュディレクトリ内のファイルを操作している可能性のあるアプリケーションを終了させます。 - 一時的にキャッシュディレクトリを変更する
環境変数NG_CACHE_PATH
を設定することで、一時的に別の場所にキャッシュディレクトリを変更できます。問題が特定のディレクトリに依存するかどうかを切り分けるのに役立ちます。export NG_CACHE_PATH=/tmp/angular-cache # Linux/macOS の例 ng cache clean ng build unset NG_CACHE_PATH
- キャッシュディレクトリの権限を確認・修正する
- 原因
- キャッシュディレクトリの所有者やアクセス権が正しく設定されていない。
- 他のプロセスがキャッシュディレクトリを使用中でロックされている。
- 症状
ng cache on
やng cache clean
などのコマンドを実行した際に、パーミッション関連のエラーが表示される。- キャッシュディレクトリへの書き込みや読み取りができない。
キャッシュ設定の誤り
- トラブルシューティング
- ng cache list で現在の設定を確認する
キャッシュが有効になっているか、パスは正しいかなどを確認します。ng cache list
- 環境変数の設定を確認する
NG_CACHE_PATH
などの環境変数が意図しない値に設定されていないか確認します。
- ng cache list で現在の設定を確認する
- 原因
ng cache
コマンドの誤用。- 環境変数の設定ミス。
- 症状
- 意図しないキャッシュの挙動(有効になっていない、保存場所が不明など)。
Angular CLI のバージョン不整合
- トラブルシューティング
- Angular CLI を最新バージョンにアップデートする
またはnpm uninstall -g @angular/cli npm install -g @angular/cli@latest
yarn global remove @angular/cli yarn global add @angular/cli@latest
- プロジェクトごとの Angular CLI のバージョンを確認・修正する
プロジェクトディレクトリで以下のコマンドを実行し、プロジェクトで使用している Angular CLI のバージョンを確認し、必要に応じて修正します。npm list @angular/cli # または yarn list @angular/cli
- Angular CLI を最新バージョンにアップデートする
- 原因
- Angular CLI のバージョンがプロジェクトの要件と一致していない。
- 症状
- 古いバージョンの Angular CLI を使用している場合に、新しいバージョンのキャッシュ機能と互換性がない。
- インターネットで検索する
同じような問題に遭遇した他の開発者の情報が見つかるかもしれません。 - Angular CLI のドキュメントを参照する
Angular CLI の公式ドキュメントには、ng cache
コマンドの詳細な説明やトラブルシューティングの情報が記載されています。 - エラーメッセージをよく読む
エラーメッセージには、問題の原因や解決策の手がかりが含まれていることが多いです。
ng cache コマンドの使用例
以下に、一般的な ng cache
コマンドとその実行例、およびその効果を説明します。
キャッシュの状態を確認する
ng cache list
このコマンドを実行すると、現在のキャッシュの設定が表示されます。例えば、キャッシュが有効になっているかどうか (enabled: true
または enabled: false
)、キャッシュが保存されているパス (path: /path/to/angular/cache
) などが確認できます。
実行例
ng cache list
出力例
Cache settings:
enabled: true
path: /Users/yourusername/.angular/cache
この例では、キャッシュが有効になっており、/Users/yourusername/.angular/cache
ディレクトリに保存されていることがわかります。
キャッシュを有効にする
ng cache on
このコマンドを実行すると、Angular CLI のキャッシュ機能が有効になります。通常はデフォルトで有効になっていますが、明示的に有効にしたい場合に実行します。
実行例
ng cache on
出力例
Angular CLI cache is now enabled.
キャッシュを無効にする
ng cache off
このコマンドを実行すると、Angular CLI のキャッシュ機能が無効になります。キャッシュが原因で問題が発生している疑いがある場合などに、一時的に無効にすることがあります。
実行例
ng cache off
出力例
Angular CLI cache is now disabled.
キャッシュをクリアする
ng cache clean
このコマンドを実行すると、Angular CLI のキャッシュが完全にクリアされます。古いキャッシュデータが原因でビルドエラーが発生する場合や、強制的にすべてのファイルを再ビルドしたい場合に実行します。
実行例
ng cache clean
出力例
Successfully cleaned the Angular CLI cache.
特定のビルドでキャッシュを無効にする (オプション指定)
Angular CLI の build
や serve
コマンドには、--no-cache
オプションがあります。これを使用すると、その特定のビルド処理でのみキャッシュを無効にできます。
実行例 (ビルド時)
ng build --no-cache
実行例 (開発サーバー起動時)
ng serve --no-cache
これらのコマンドを実行しても、グローバルなキャッシュ設定 (ng cache on
/ng cache off
) は変更されません。あくまで、その一度のビルドまたは開発サーバー起動時のみキャッシュが無効になります。
キャッシュのパスを確認する
ng cache path
このコマンドを実行すると、Angular CLI のキャッシュが保存されているディレクトリのパスが表示されます。
実行例
ng cache path
出力例
/Users/yourusername/.angular/cache
これらの例からわかるように、ng cache
関連の「プログラミング」は、Angular アプリケーションのコード内で行うものではなく、Angular CLI のコマンドラインインターフェースを通じて行うものです。これらのコマンドを適切に使用することで、Angular アプリケーションのビルド時間を最適化したり、キャッシュに関連する問題をトラブルシューティングしたりすることができます。
アプリケーション実行時のデータキャッシュ
ng cache
は主にビルド時のパフォーマンス向上を目的としていますが、アプリケーションが実際に動作する際には、API から取得したデータや計算結果などをクライアント側でキャッシュすることで、ユーザーエクスペリエンスを向上させることができます。
-
RxJS の shareReplay オペレーター
-
Observable から流れてくる値をキャッシュし、後から購読する Subscriber にも最新の値を再配信します。
-
同じ API リクエストの結果を複数のコンポーネントで共有する場合などに便利です。
-
例
```typescript import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { shareReplay } from 'rxjs/operators';@Injectable({ providedIn: 'root', }) export class ApiService { private cachedData$: Observable<any> | null = null; private apiUrl = '/api/data';
constructor(private http: HttpClient) {}
getData(): Observable<any> { if (!this.cachedData$) { this.cachedData$ = this.http.get<any>(this.apiUrl).pipe(shareReplay(1)); } return this.cachedData$; } }
-
-
IndexedDB
- より複雑な構造化データを非同期に保存・検索できるブラウザのデータベースです。
- Angular のライブラリ(例:
ngx-indexed-db
)を利用することで、より簡単に扱うことができます。 - 大量のデータをクライアント側で効率的に管理する場合に適しています。
-
- 比較的単純なデータを永続的(LocalStorage)またはセッション期間のみ(SessionStorage)保存できます。
- Angular のサービス内でデータの取得時にストレージを確認し、存在すればそれを再利用、なければ API を呼び出して取得後に保存するロジックを実装します。
- 例
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class DataCacheService { private cache: { [key: string]: any } = {}; getData(key: string, fetchFn: () => Promise<any>): Promise<any> { if (this.cache[key]) { return Promise.resolve(this.cache[key]); } return fetchFn().then((data) => { this.cache[key] = data; return data; }); } // LocalStorage を利用する例 getDataFromLocalStorage(key: string, fetchFn: () => Promise<any>): Promise<any> { const storedData = localStorage.getItem(key); if (storedData) { return Promise.resolve(JSON.parse(storedData)); } return fetchFn().then((data) => { localStorage.setItem(key, JSON.stringify(data)); return data; }); } }
より高度なビルドキャッシュ戦略
ng cache
は Angular CLI によって提供される便利なキャッシュ機能ですが、より細かくビルドキャッシュを制御したい場合や、特定の処理に特化したキャッシュを実装したい場合は、他の方法も検討できます。
-
CI/CD パイプラインでのキャッシュ
- CI/CD (Continuous Integration/Continuous Delivery) パイプラインのツールによっては、ビルドの中間生成物や依存関係をキャッシュする機能が提供されています。
- これを利用することで、CI/CD 環境でのビルド時間を短縮できます。例えば、GitHub Actions の
actions/cache
や GitLab CI/CD のキャッシュ機能などがあります。
-
Webpack のキャッシュ設定
- Angular CLI は内部的に Webpack を利用しています。Webpack のキャッシュ設定を直接調整することで、より詳細なキャッシュ戦略を制御できます。
angular.json
のwebpackConfig
オプションでカスタムの Webpack 設定ファイルを指定し、そこでキャッシュ関連の設定を行います。- 例 (webpack.config.js)
const path = require('path'); module.exports = { // ... 他の設定 ... cache: { type: 'filesystem', cacheDirectory: path.resolve(__dirname, '.webpack-cache'), buildDependencies: { config: [__filename], // この設定ファイルを依存関係に含める }, }, };
-
カスタムビルドスクリプトの作成
angular.json
のarchitect
セクションで定義されているビルド処理をカスタマイズし、特定のファイルや処理結果を明示的にキャッシュするロジックを Node.js などで記述します。- 例えば、外部 API から取得した設定ファイルをビルド時にキャッシュしたり、特定の処理の結果をファイルに保存して再利用したりすることができます。
サーバーサイドでのキャッシュ
Angular は主にクライアントサイドで動作するフレームワークですが、API サーバー側でキャッシュを導入することも、アプリケーション全体のパフォーマンス向上に大きく貢献します。
-
サーバーサイドのキャッシュストア
- Redis や Memcached などのインメモリデータストアを利用して、API のレスポンスや計算結果をキャッシュします。
-
HTTP キャッシュ
- サーバーが適切な HTTP ヘッダー(
Cache-Control
,Expires
など)を設定することで、ブラウザや CDN (Content Delivery Network) にレスポンスをキャッシュさせることができます。
- サーバーが適切な HTTP ヘッダー(