フロントエンド Angular 19: 複雑なアプリのための最新アーキテクチャ
フロントエンド イベントをプレイする 27 の機能モジュールを処理する Angular 19 アプリケーションをサポートします。 21 の言語に対応し、Univerjs、Konva、D3.js、および マップリブレ。この記事では、次のようなアーキテクチャ上の選択について検討します。 パフォーマンスと保守性を犠牲にすることなく、これらすべてが可能になります。
この記事でわかること
- NgModules を使用しないスタンドアロン アーキテクチャ
- Signals と BaseStore による状態管理
- Express を使用したサーバー側レンダリング
- 27 個の遅延ロードモジュールとレスポンシブデザイン
- 高度な UI ライブラリ: Univerjs、Konva、D3.js、MapLibre、Chart.js
- HTTP インターセプター、プレミアム ガード、アクセシビリティ
スタンドアロン コンポーネント: さようなら NgModules
アプリケーション全体が使用するのは、 スタンドアロンコンポーネント、 NgModule を完全に排除します。各コンポーネントは独自の宣言を行います 依存関係をデコレーター内で直接作成し、コードをより明示的にします。 より効果的なツリーシェイクを実現します。
@Component({
selector: 'app-event-dashboard',
standalone: true,
imports: [
CommonModule,
TranslateModule,
ChartComponent,
ExpenseSummaryComponent,
GuestListComponent
],
templateUrl: './event-dashboard.component.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class EventDashboardComponent {
private readonly store = inject(EventStore);
event = this.store.currentEvent;
guests = this.store.guests;
expenses = this.store.expenses;
isLoading = this.store.isLoading;
}
主な利点と明確さ: コンポーネントを見ると、それがわかります。 まさにそれが何に依存しているのか。フォーム間を移動する必要はありません テンプレートで利用できるものを理解するためにネストされています。
シグナルによる状態管理: BaseStore パターン
状態管理のために、Play The Event はパターンを使用します に基づいてカスタマイズされた 角度信号。 の ベースストア すべてに共通の機能を提供します アプリケーションストア。
export abstract class BaseStore<T> {
// Stato interno con signals
protected readonly _data = signal<T | null>(null);
protected readonly _isLoading = signal(false);
protected readonly _error = signal<string | null>(null);
protected readonly _lastFetch = signal<number>(0);
// Cache TTL configurabile (default: 5 minuti)
protected readonly cacheTTL = 5 * 60 * 1000;
// Selettori pubblici (readonly)
readonly data = this._data.asReadonly();
readonly isLoading = this._isLoading.asReadonly();
readonly error = this._error.asReadonly();
// Computed signals
readonly hasData = computed(() => this._data() !== null);
readonly isStale = computed(() => {
const elapsed = Date.now() - this._lastFetch();
return elapsed > this.cacheTTL;
});
// Fetch con cache intelligente
async loadIfNeeded(): Promise<void> {
if (this.hasData() && !this.isStale()) {
return; // Dati freschi in cache, skip
}
await this.forceLoad();
}
protected abstract fetchData(): Observable<T>;
}
なぜNgRxではなくBaseStoreなのか?
- シンプルさ: NgRx にはアクション、リデューサー、エフェクト、セレクターが必要です。 BaseStore は単一のファイルです。
- パフォーマンス: シグナルは Angular にネイティブであり、OnPush 変更検出用に最適化されています。
- 統合キャッシュ: TTL は、ライブラリを追加せずに冗長な API 呼び出しを回避します。
- 類型化: TypeScript ジェネリックのおかげで、各ストアは厳密に型指定されます。
Express を使用したサーバー側レンダリング
SSR は、知覚されるパフォーマンスと SEO にとって重要です。 イベントをプレイする レンダリングを処理する Express サーバーで Angular Universal を使用します サーバー側。
Express サーバーはレンダリングに限定されず、圧縮、 サポートのための静的ページのキャッシュと URL 書き換え 多言語。公開ページ (ランディング、価格設定、ブログ) は事前にレンダリングされます 認証されたページはオンデマンドでレンダリングされますが、キャッシュされます。
27 個の遅延ロードモジュール
アプリケーションは次のように分かれています 27 の機能モジュール、それぞれ 遅延読み込みによりオンデマンドで読み込まれます。これは、ユーザーが アクセスしているページに必要なコードのみをダウンロードします。
export const routes: Routes = [
{
path: 'events',
loadComponent: () =>
import('./features/events/event-list.component')
.then(m => m.EventListComponent),
canActivate: [authGuard]
},
{
path: 'events/:id/expenses',
loadComponent: () =>
import('./features/expenses/expense-dashboard.component')
.then(m => m.ExpenseDashboardComponent),
canActivate: [authGuard, premiumGuard('PRO')]
},
{
path: 'events/:id/seating',
loadComponent: () =>
import('./features/seating/seating-chart.component')
.then(m => m.SeatingChartComponent),
canActivate: [authGuard, premiumGuard('ENTERPRISE')]
},
// ... altri 24 moduli
];
レスポンシブ デザイン: モバイル ファースト
インターフェースは考え抜かれて設計されています モバイルファースト 3 つの主要なブレークポイントを使用します。
/* Breakpoint */
--breakpoint-mobile: 320px; /* Smartphone */
--breakpoint-tablet: 768px; /* Tablet */
--breakpoint-desktop: 1024px; /* Desktop */
/* Typography: Montserrat + Lato */
--font-heading: 'Montserrat', sans-serif;
--font-body: 'Lato', sans-serif;
/* Layout responsive */
.event-grid {
display: grid;
grid-template-columns: 1fr; /* Mobile: 1 colonna */
}
@media (min-width: 768px) {
.event-grid {
grid-template-columns: repeat(2, 1fr); /* Tablet: 2 colonne */
}
}
@media (min-width: 1024px) {
.event-grid {
grid-template-columns: repeat(3, 1fr); /* Desktop: 3 colonne */
}
}
TranslateService で 21 言語に対応
国際化は次の方法で管理されます。 翻訳サービス 21の言語をサポートするようにカスタマイズされています。翻訳ファイルはJSONです 機能モジュールごとに編成され、オンデマンドでロードされます。 対応するフォーム。
21 の言語での i18n チャレンジ
21 の言語を管理することは、文字列を翻訳するだけではありません。考慮する必要があります テキストの方向 (アラビア語の場合は LTR/RTL)、日付形式、 現地通貨、複数形(言語によって大きく異なります)、 そしてレイアウトに影響を与えるテキストの可変長。
高度な UI ライブラリ
Play The Event は、5 つの特殊な UI ライブラリを統合しています。 特定の使用例。
統合ライブラリ
- 大学: 共同予算およびスプレッドシート用のブラウザーのスプレッドシート
- コンヴァ: フロアプランおよびテーブルレイアウトエディター用の 2D Canvas
- D3.js: 参加者の関係性のグラフと複雑なデータの視覚化
- マップリブレGL: 旅行日程と会場の場所を示すインタラクティブな地図
- チャート.js: 分析用のグラフ、統計ダッシュボード、財務レポート
HTTP インターセプター
2 つの HTTP インターセプターが API 呼び出しを全面的に処理します。
トークンリフレッシュを備えた認証インターセプター
認証インターセプターは、JWT トークンを各リクエストに自動的に追加します。 トークンの有効期限が切れると (401 応答)、インターセプターは 自動更新 リフレッシュトークンを使用して、次の操作を繰り返します。 新しいトークンを使用した元のリクエスト、および更新も失敗した場合、 ログインページにリダイレクトされます。
エラーインターセプター
エラー インターセプタは、HTTP エラー処理を一元化します。 show クライアント エラー (4xx) のトースト通知、エラーのエラー ページ サーバー (5xx)、およびデバッグ用のエラーのログ。
プレミアム機能ガード
一部の機能はサブスクリプション ユーザーのみが利用できます プロまたはエンタープライズ。ザ 見て ~のレベルをチェックする ルートへのアクセスを許可する前にサブスクリプションを行ってください。
export function premiumGuard(requiredLevel: 'PRO' | 'ENTERPRISE') {
return () => {
const auth = inject(AuthStore);
const router = inject(Router);
const userLevel = auth.subscriptionLevel();
const levels = { 'BASIC': 0, 'PRO': 1, 'ENTERPRISE': 2 };
if (levels[userLevel] >= levels[requiredLevel]) {
return true;
}
return router.createUrlTree(['/pricing'], {
queryParams: { upgrade: requiredLevel }
});
};
}
WCAG 2.1 AA アクセシビリティ
アクセシビリティは後から追加されたものではなく、プロセスに組み込まれています。 開発の。各コンポーネントは、WCAG 2.1 AA 準拠についてテストされています。
アクセシビリティの実践
- 最小カラーコントラスト 通常のテキストの場合は 4.5:1、大きなテキストの場合は 3:1
- フォーカスが表示されるフルキーボードナビゲーション
- カスタム対話型コンポーネントの ARIA 属性
- ダイナミックな株式に関するスクリーン リーダー広告
- サポート
prefers-reduced-motionアニメーションを減らすには - 自動テスト 斧の芯 CIパイプライン内
テスト: Jest、Playwright、および axe-core
テスト戦略は 3 つのレベルに分かれています。
単体およびコンポーネントのテスト
- 冗談: サービス、パイプ、ビジネス ロジックの単体テスト
- TestBed による Angular コンポーネントのコンポーネント テスト
- 分離テスト用のモック HTTP サービス
E2E とアクセシビリティ
- 劇作家: エンドツーエンドのクロスブラウザー テスト (Chrome、Firefox、Safari)
- 斧の芯: E2E テストに統合された自動アクセシビリティ テスト
- 重要なコンポーネントの視覚的な回帰テスト
重要なポイント
- 最大限の明瞭さと効果的なツリーシェイキングを実現するスタンドアロンコンポーネント
- シグナルと TTL キャッシュを備えた BaseStore により、応答性とパフォーマンスの高い状態を実現
- Express を使用した SSR による SEO と知覚されたパフォーマンス
- 最適なバンドル サイズを実現する 27 個の遅延ロード モジュール
- 5 つの特殊な UI ライブラリが調和して統合されました
- 自動認証と集中エラー処理のための HTTP インターセプター
- 3 つのレベルでのテスト: ユニット、E2E、アクセシビリティ
フロントエンドのソースコードは次の場所から入手できます。 GitHub。 訪問 www.playtheevent.com 最終結果を確認します。







