フレームワークへの準拠

JavaScript フレームワーク エコシステムの準拠

導入に関するブログ投稿では、Google 検索、マップ、フォトなどの大規模なウェブ アプリケーションを開発、メンテナンスするためにフレームワークとツールを構築し、使用しながら多くのことを学んだ方法について説明しました。ユーザー エクスペリエンスに悪影響を及ぼすコードをデベロッパーが記述しないようにすることで、フレームワークがパフォーマンスとアプリケーションの品質の成果を改善するうえで重要な役割を果たすことができることを証明しました。

Google では、この方法論を説明するために「コンプライアンス」という用語を使用しています。この記事では、このコンセプトを JavaScript フレームワーク エコシステムにオープンソース化する方法について説明します。

コンプライアンスとは

Google では、コンプライアンスは進化でした。チームは、経験豊富な少数のメンテナーに依存し、広範なコードレビューを行い、正確性の問題を超えてアプリの品質と保守性に影響する問題を報告していました。これを拡大してアプリ デベロッパーのチームを増やしていくため、コンプライアンス システムが開発され、ベスト プラクティスを自動化され適用可能な方法でコード化しました。これにより、コード作成者の数に関係なく、アプリの品質とコードベースの保守性が一貫して高いレベルを維持できました。

コンプライアンスは、デベロッパーが明るい道を歩き続けることを保証するシステムです。信頼を築き、予測可能な結果を確実にします。これにより、チームの生産性が向上し、チームの規模が拡大し、同時に開発される機能が増えるにつれて、スケールに不可欠になります。これにより、開発者はプロダクト機能の構築に集中でき、パフォーマンス、ユーザー補助、セキュリティなど、さまざまな分野の細かい点や変化する状況から解放されます。コンプライアンスはいつでもオプトアウトできます。また、チームがコミットすることを決定したものをすべて適用できるように、カスタマイズできる必要があります。

コンプライアンスは、強力なデフォルトに基づいており、作成時に適用できる実行可能なルールを提供します。これは、次の 3 つの原則に分類されます。

1. 強力なデフォルト

コンプライアンスの基本的な側面は、デベロッパーが使用するツールに強力なデフォルトが設定されていることを確認することです。つまり、ソリューションはフレームワークに組み込まれているだけでなく、フレームワークの設計パターンにより、正しいことを簡単に行い、アンチパターンに従うことが難しくなります。このフレームワークは、アプリケーション設計とコード構造でデベロッパーをサポートします。

読み込みのパフォーマンスを高めるには、すべてのリソース(フォント、CSS、JavaScript、画像など)を最適化する必要があります。これは、バイトのトリミング、ラウンドトリップの削減、最初のレンダリング、視覚的な準備、ユーザー操作に必要なものの分離など、複雑な課題です。たとえば、重要な CSS の抽出や、重要な画像の優先度の設定などです。

2. 対処可能なルール

基本的な最適化を実施しても、デベロッパーは選択を行う必要があります。最適化には、開発者の入力が必要な程度に応じてさまざまな方法があります。

  • デベロッパーの入力を必要としないデフォルト(重要な CSS のインライン化など)。
  • デベロッパーによるオプトインが必要です。たとえば、フレームワーク提供の画像コンポーネントを使用して画像のサイズとスケーリングを行う場合。
  • デベロッパーによるオプトインとカスタマイズが必要。たとえば、重要な画像にタグを付け、早めに読み込むようにします。
  • 特定の機能ではなく、デベロッパーの判断が必要なものです。たとえば、早期レンダリングを遅らせるフォントや同期スクリプトを回避します。

自動と手動のデベロッパーの最適化の範囲を示す図

デベロッパーの意思決定を必要とする最適化は、アプリケーションのパフォーマンスにリスクをもたらします。機能が追加され、チームが拡大するにつれて、最も経験豊富なデベロッパーであっても、絶えず変化するベスト プラクティスに追いつくことはできません。また、時間を最大限に活用することもできません。コンプライアンスでは、デベロッパーが変更を加え続けてもアプリケーションが特定の基準を継続的に満たせるように、適切な実行可能なルールが強力なデフォルトと同じくらい重要です。

3. 作成時間

開発ライフサイクルの早い段階でパフォーマンスの問題を検出して回避することが重要です。コードが commit される前の作成段階は、問題を検出して対処するのに最適なタイミングです。開発ライフサイクルの後半で問題が検出されると、問題に対処するのが難しくなり、費用も高くなります。これは正確性の問題に適用されますが、パフォーマンスの問題にも当てはまります。これらの問題の多くは、コードベースに commit された後では遡及的に解決されないためです。

現在、ほとんどのパフォーマンス フィードバックは、ドキュメントや 1 回限りの監査を通じてアウトバンドで提供されています。また、本番環境へのデプロイ後に指標の回帰によってフィードバックが遅れて表示されることもあります。これを作成時に実現したいと考えています。

フレームワークの適合性

読み込みパフォーマンスのユーザー エクスペリエンスの基準を維持するには、次の質問に答える必要があります。

  1. 最適な読み込みとはどのようなもので、それに悪影響を及ぼす一般的な問題は何ですか?
  2. デベロッパーの入力を必要とせずにビルドに組み込むことができるソリューションはどれですか。
  3. デベロッパーがこれらのソリューションを使用して、最適に活用できるようにするにはどうすればよいですか?
  4. 読み込みのパフォーマンスに影響を与える可能性がある、デベロッパーによるその他の選択肢にはどのようなものがありますか?
  5. 作成時にこれらの選択肢(上記の #3 と #4)を早期に把握できるコードパターンは何ですか?
  6. これらのコードパターンを評価するために、どのようなルールを定式化できますか?ワークフローにシームレスに統合しながら、作成時にデベロッパーに表示するにはどうすればよいですか?

Google 内部で使用しているコンプライアンス モデルをオープンソース フレームワークに導入するために、Google のチームは Next.js で多くのテストを実施しました。その結果、コードパターンを評価できる最適なルールセットは、静的コード分析動的チェックを組み合わせたものである必要があると判断しました。これらのルールは、次のような複数のサーフェスにまたがって適用できます。

  • ESLint
  • TypeScript
  • ユーザーの開発用サーバーでの動的チェック(DOM 作成後)
  • モジュール バンドラ(webpack)
  • CSS ツール(まだ試験運用中)

さまざまなツールを使用してルールを提供するメリットは、ルールの整合性を保ちながら、読み込みパフォーマンスに直接影響するユーザー エクスペリエンスの問題も網羅できることです。また、これらのルールは、デベロッパーにさまざまなタイミングで表示されます。

  • 開発用サーバーでローカル開発を行うと、ブラウザとユーザーの IDE に警告が表示され、デベロッパーにコードの細かい変更を求めるメッセージが表示されます。
  • ビルド時に、未解決の問題がユーザーのターミナルに再表示されます。

要するに、チームは Core Web Vitals や読み込みパフォーマンスなど、重視する結果を選択し、すべてのコード作成者が遵守できるように関連するルールセットを有効にします。

これは新しいプロジェクトでは非常に効果的ですが、大規模なコードベースをアップグレードして完全なルールセットに準拠させることは簡単ではありません。Google では、ソースコードの個々の行、ディレクトリ全体、レガシー コードベース、積極的に開発されていないアプリの部分など、さまざまなレベルでオプトアウトするための包括的なシステムを用意しています。Google は、オープンソース フレームワークを使用しているチームにこれを導入するための効果的な戦略を積極的に検討しています。

Next.js のコンプライアンス

ESLint は JavaScript デベロッパーの間で広く使用されており、Next.js アプリケーションの 50% 以上がビルド ワークフローの一部で ESLint を使用しています。Next.js v11 では、カスタム プラグイン共有可能な構成を含む ESLint のサポートが導入されました。これにより、開発時とビルド時にフレームワーク固有の一般的な問題を簡単に検出できるようになりました。これにより、デベロッパーは作成時に重大な問題を修正できます。たとえば、ページに HTML リンクがないなど、特定のコンポーネントがパフォーマンスに悪影響を及ぼすような方法で使用されている場合や、使用されていない場合です。また、特定のフォント、スタイルシート、スクリプトがページのリソースの読み込みに悪影響を及ぼす場合もあります。たとえば、No synchronous script です。

ESLint に加えて、TypeScript のサポートが v9 以降の Next.js で追加され、開発と本番環境の両方で統合型の型チェックがサポートされています。フレームワークで提供される複数のコンポーネント(画像、スクリプト、リンク)は、HTML 要素(<img><script><a>)の拡張として構築されており、ウェブページにコンテンツを追加する際のパフォーマンスの高いアプローチをデベロッパーに提供します。型チェックは、割り当てられたプロパティとオプションが、サポートされている値と型の許容範囲内にあることを確認することで、これらの機能の適切な使用をサポートします。例については、必要な画像の幅と高さをご覧ください。

トーストとオーバーレイでエラーを表示する

前述のように、コンプライアンス ルールは複数の領域に表示できます。現在、ユーザーのローカル開発環境内のブラウザにエラーを直接表示する方法として、トーストとオーバーレイが検討されています。

トーストで表示されるエラー

デベロッパーが使用する多くのエラーチェックツールと監査ツール(Lighthouse、Chrome DevTools の [Issues] タブ)は受動的なため、情報を取得するには何らかのユーザー操作が必要です。デベロッパーは、エラーが既存のツール内で直接表示され、問題を解決するために必要な具体的なアクションが提供されている場合に、対応する可能性が高くなります。

他のフレームワークのコンプライアンス

コンプライアンスは、他のフレームワーク(Nuxt、Angular など)に拡大することを目標に、まず Next.js で検討されています。ESLint と TypeScript は、多くのフレームワークでさまざまな方法ですでに使用されていますが、統合されたブラウザレベルのランタイム システムのコンセプトが積極的に検討されています。

まとめ

コンプライアンスでは、ベスト プラクティスをルールセットにコード化し、デベロッパーがシンプルなコードパターンとして実践できるようにします。Aurora チームは読み込みパフォーマンスに重点を置いていましたが、ユーザー補助やセキュリティなどの他のベスト プラクティスも同様に適用されます。

コンプライアンス ルールに従うことで、予測可能な結果が得られます。また、技術スタック上に構築することで、ユーザー エクスペリエンスのレベルを高めることができます。コンプライアンスにより、チームの生産性が向上し、チームとコードベースが時間とともに成長しても、アプリケーションの高品質基準が確保されます。