FCP(First Contentful Paint:最初のコンテンツ描画)の最適化について、API の呼び出しレベルに留まっている開発者は多い。本記事では本番環境の観点から、実際に起きる問題とその解決策を論じる。
基本原理
以下は全体のサンプルだ:
javascript
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
reportMetric('LCP', entry.startTime)
}
if (entry.entryType === 'first-input') {
reportMetric('FID', entry.processingStart - entry.startTime)
}
}
})
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] })
境界条件の処理に注意すること。これは本番環境では極めて重要だ。
高度な機能
肝心なのはコアとなるロジックを理解することだ:
javascript
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
reportMetric('LCP', entry.startTime)
}
if (entry.entryType === 'first-input') {
reportMetric('FID', entry.processingStart - entry.startTime)
}
}
})
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] })
パフォーマンス最適化は具体的な状況に合わせる必要があり、すべてのケースで過度な最適化が必要なわけではない。
プロジェクト実践
次の方法で改善できる:
javascript
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
reportMetric('LCP', entry.startTime)
}
if (entry.entryType === 'first-input') {
reportMetric('FID', entry.processingStart - entry.startTime)
}
}
})
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] })
このアプローチは本番環境で半年以上安定して動いており、実際に検証済みだ。
ベストプラクティス
基本的な実装方法を見てみよう:
javascript
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
reportMetric('LCP', entry.startTime)
}
if (entry.entryType === 'first-input') {
reportMetric('FID', entry.processingStart - entry.startTime)
}
}
})
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] })
このコードは基本的な使い方を示している。実際のプロジェクトではエラーハンドリングや境界条件も考慮する必要がある。
ハマりやすい注意点
これをベースに、さらに最適化できる:
javascript
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
reportMetric('LCP', entry.startTime)
}
if (entry.entryType === 'first-input') {
reportMetric('FID', entry.processingStart - entry.startTime)
}
}
})
observer.observe({ entryTypes: ['largest-contentful-paint', 'first-input'] })
このパターンは大規模なプロジェクトで非常に実用的で、保守コストを大きく下げられる。
まとめ
- 本番環境で使う前に、必ず互換性の検証を行うこと
- チーム開発では、技術そのものよりも取り決めとドキュメントの方が重要だ
- コミュニティの動向を追い、技術的なアプローチは継続的に磨き込む
