Skip to content

フロントエンドの非機能要件

フロントエンドの非機能要件は、ユーザー体験に直接影響する重要な要件です。

フロントエンドで着目すべき非機能要件

Section titled “フロントエンドで着目すべき非機能要件”

レスポンスタイム:

  • 初回表示時間(FCP): 1.8秒以内
  • 最大コンテンツ表示時間(LCP): 2.5秒以内
  • First Input Delay(FID): 100ミリ秒以内
  • Cumulative Layout Shift(CLS): 0.1以下

実装例:

パフォーマンスを向上させるための実装例を示します。画像の最適化、コード分割、メモ化を組み合わせることで、初回表示時間を短縮できます。

// 画像の最適化
// Next.jsのImageコンポーネントを使用することで、自動的に画像を最適化
// loading="lazy"で遅延読み込みを実装し、初期表示を高速化
import Image from 'next/image';
<Image
src="/product.jpg"
width={500}
height={300}
alt="Product"
loading="lazy" // 遅延読み込み: 画面に表示されるまで画像を読み込まない
priority={false} // 優先度の設定: falseにすることで、重要な画像以外は後から読み込む
/>
// コード分割
// 大きなコンポーネントを動的にインポートすることで、初期バンドルサイズを削減
// ユーザーが実際にそのコンポーネントを使用するタイミングで読み込む
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <Loading />, // 読み込み中はローディング表示
ssr: false, // サーバーサイドレンダリングを無効化(クライアント側のみで実行)
});
// メモ化
// 高価な計算を行うコンポーネントをメモ化することで、不要な再レンダリングを防止
// propsが変更されない限り、前回のレンダリング結果を再利用
const MemoizedComponent = React.memo(ExpensiveComponent);

これらの最適化により、FCP(First Contentful Paint)を1.8秒以内、LCP(Largest Contentful Paint)を2.5秒以内に抑えることができます。

バンドルサイズ:

  • JavaScriptバンドル: 200KB以下(gzip圧縮後)
  • CSSバンドル: 50KB以下(gzip圧縮後)
  • 画像: WebP形式を使用、適切なサイズに最適化

XSS対策:

  • ユーザー入力のサニタイズ
  • Reactの自動エスケープを活用
  • Content Security Policy(CSP)の設定

実装例:

XSS(Cross-Site Scripting)攻撃を防ぐための実装例を示します。ユーザー入力を受け取る際は、必ず適切なエスケープまたはサニタイズを実施する必要があります。

// 危険な実装(XSS脆弱性)
// dangerouslySetInnerHTMLを使用すると、HTMLタグがそのまま実行されるため、
// 悪意のあるスクリプトが注入される可能性がある
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// 安全な実装
// Reactはデフォルトで自動的にエスケープを行うため、通常のJSX記法を使用すれば安全
// ユーザー入力に含まれるHTMLタグは文字列として表示される
<div>{userInput}</div> // Reactが自動的にエスケープ
// サニタイズが必要な場合
// リッチテキストエディタなど、HTMLを表示する必要がある場合は、
// DOMPurifyなどのライブラリでサニタイズしてから使用する
import DOMPurify from 'dompurify';
// サニタイズにより、危険なスクリプトタグなどを除去し、安全なHTMLのみを残す
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />

この実装により、XSS攻撃を防ぎ、ユーザーのセキュリティを保護できます。

CSRF対策:

  • CSRFトークンの実装
  • SameSite Cookieの設定

実装例:

CSRF(Cross-Site Request Forgery)攻撃を防ぐための実装例を示します。CSRFトークンをリクエストヘッダーに含めることで、正当なリクエストであることを証明します。

// CSRFトークンの送信
// HTMLのmetaタグからCSRFトークンを取得
// サーバー側で生成されたトークンを、クライアント側で取得して使用する
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
// APIリクエスト時にCSRFトークンをヘッダーに含める
// サーバー側でこのトークンを検証することで、正当なリクエストかどうかを判断
fetch('/api/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': csrfToken, // CSRFトークンをヘッダーに追加
},
body: JSON.stringify(data),
});

この実装により、CSRF攻撃を防ぎ、ユーザーの操作を保護できます。

エラーハンドリング:

  • 適切なエラーメッセージの表示
  • エラーバウンダリーの実装
  • リトライ機能の実装

実装例:

エラーハンドリングとリトライ機能の実装例を示します。エラーバウンダリーは、Reactコンポーネントツリー内で発生したエラーをキャッチし、適切に処理します。リトライ機能は、ネットワークエラーなどの一時的なエラーに対して自動的に再試行を行います。

// エラーバウンダリー
// Reactコンポーネントツリー内で発生したエラーをキャッチし、ユーザーに適切なエラー画面を表示
// エラーが発生したコンポーネントの代わりに、エラーフォールバックUIを表示する
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
// エラーが発生した際に、stateを更新してエラー状態にする
static getDerivedStateFromError(error) {
return { hasError: true };
}
// エラーの詳細情報をログに記録し、エラー報告サービスに送信
// これにより、本番環境でのエラーを追跡・分析できる
componentDidCatch(error, errorInfo) {
console.error('Error:', error, errorInfo);
// エラーログを送信
errorReportingService.report(error);
}
// エラーが発生している場合はエラーフォールバックを表示、そうでなければ通常の子コンポーネントを表示
render() {
if (this.state.hasError) {
return <ErrorFallback />; // エラー時の代替UI
}
return this.props.children; // 通常のコンポーネント
}
}
// リトライ機能
// TanStack Queryを使用したデータフェッチングのリトライ機能
// ネットワークエラーなどの一時的なエラーに対して、自動的に再試行を行う
const { data, error, retry } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
retry: 3, // 最大3回までリトライ
// 指数バックオフ: 1秒、2秒、4秒...とリトライ間隔を増やしていく(最大30秒)
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
});

この実装により、エラーが発生してもアプリケーションがクラッシュせず、ユーザーに適切なエラーメッセージを表示できます。また、一時的なネットワークエラーに対して自動的にリトライすることで、ユーザー体験を向上させます。

オフライン対応:

  • Service Workerの実装
  • オフライン時の動作定義

WCAG準拠:

  • レベルA: 最低限の要件
  • レベルAA: 推奨される要件
  • レベルAAA: 最高レベルの要件

実装例:

アクセシビリティを向上させるための実装例を示します。セマンティックHTML、キーボード操作、フォーカス管理を適切に実装することで、スクリーンリーダーやキーボードのみで操作するユーザーにも使いやすいアプリケーションになります。

// セマンティックHTML
// アイコンのみのボタンには、aria-labelでアクセシブルな名前を提供
// スクリーンリーダーが「メニューを開く」と読み上げることで、視覚障害者にも機能が伝わる
<button aria-label="メニューを開く">
<MenuIcon />
</button>
// キーボード操作
// マウスだけでなく、キーボードでも操作できるようにする
// Enterキーまたはスペースキーでクリックと同じ動作を実行
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
handleClick();
}
};
// フォーカス管理
// モーダルやフォームが開いた際に、適切な要素にフォーカスを移動
// これにより、キーボードユーザーがスムーズに操作できる
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
inputRef.current?.focus(); // コンポーネントがマウントされた際に、入力欄にフォーカス
}, []);

この実装により、WCAG 2.1 レベルAAに準拠し、すべてのユーザーがアプリケーションを利用できるようになります。

対応ブラウザ:

  • Chrome(最新版と1つ前)
  • Firefox(最新版と1つ前)
  • Safari(最新版と1つ前)
  • Edge(最新版)

実装例:

ブラウザ互換性を確保するための実装例を示します。ポリフィルを使用することで、古いブラウザでも最新のJavaScript機能を使用できます。機能検出により、ブラウザがサポートしていない機能を使用する前に確認できます。

// ポリフィルの使用
// core-jsは、古いブラウザで最新のJavaScript機能(Promise、Array.fromなど)を使用できるようにする
// regenerator-runtimeは、async/awaitなどの非同期処理を古いブラウザで動作させる
import 'core-js/stable';
import 'regenerator-runtime/runtime';
// 機能検出
// ブラウザがService Workerをサポートしているか確認してから使用する
// サポートしていないブラウザでは、Service Workerの登録をスキップしてエラーを防ぐ
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}

この実装により、主要なブラウザでアプリケーションが正常に動作することを保証できます。

レスポンシブデザイン:

  • モバイルファーストの設計
  • タッチ操作の最適化
  • 画面サイズの考慮

実装例:

モバイル対応のためのレスポンシブデザインの実装例を示します。モバイルファーストのアプローチでは、まずモバイル向けのスタイルを定義し、その後で大きな画面向けのスタイルを追加します。これにより、モバイルデバイスでのパフォーマンスを最適化できます。

/* モバイルファースト */
/* まず、モバイル向けの基本スタイルを定義 */
/* モバイルデバイスでは、パディングを1remに設定 */
.container {
padding: 1rem;
}
/* メディアクエリを使用して、768px以上の画面(タブレット・デスクトップ)向けのスタイルを追加 */
/* 大きな画面では、パディングを2remに増やすことで、より広い余白を確保 */
@media (min-width: 768px) {
.container {
padding: 2rem;
}
}

この実装により、モバイル、タブレット、デスクトップのすべてのデバイスで最適な表示を実現できます。

フロントエンドの非機能要件チェックリスト

Section titled “フロントエンドの非機能要件チェックリスト”
  • FCPが1.8秒以内
  • LCPが2.5秒以内
  • FIDが100ミリ秒以内
  • CLSが0.1以下
  • JavaScriptバンドルが200KB以下
  • 画像が最適化されている
  • XSS対策が実装されている
  • CSRF対策が実装されている
  • 機密情報がクライアントに露出していない
  • HTTPSが使用されている
  • エラーハンドリングが実装されている
  • エラーバウンダリーが実装されている
  • リトライ機能が実装されている
  • オフライン対応が実装されている
  • WCAG 2.1 レベルAAに準拠
  • キーボード操作が可能
  • スクリーンリーダーに対応
  • 適切なARIA属性が設定されている
  • 主要ブラウザで動作確認済み
  • ポリフィルが適切に設定されている
  • 機能検出が実装されている
  • レスポンシブデザインが実装されている
  • タッチ操作が最適化されている
  • モバイルでのパフォーマンスが良好

フロントエンドの非機能要件:

  • パフォーマンス: Core Web Vitals、バンドルサイズ、画像最適化
  • セキュリティ: XSS対策、CSRF対策、機密情報の保護
  • 可用性: エラーハンドリング、オフライン対応
  • アクセシビリティ: WCAG準拠、キーボード操作、スクリーンリーダー対応
  • ブラウザ互換性: 主要ブラウザでの動作確認
  • モバイル対応: レスポンシブデザイン、タッチ操作の最適化

適切な非機能要件を定義・実装することで、高品質なフロントエンドアプリケーションを構築できます。