web.dev エンジニアリング ブログ #1: サイトの構築とウェブ コンポーネントの使い方

これは、web.dev のエンジニアリング ブログの最初の投稿です。 今後数か月以内に、この取り組みから得られた実用的な分析情報を共有する予定です。エンジニアリング ブログのタグが付いた投稿をお待ちください。 ここでは、静的サイトのビルドプロセスと、Google のウェブ コンポーネントの背後にある JavaScript。

web.dev には、最新のウェブ エクスペリエンスの構築に関するコンテンツが提供されており、サイトのパフォーマンスを測定できます。ご存じの方も多いと思いますが、測定ページLighthouse のインターフェースにすぎません。Lighthouse は Chrome の DevTools でも利用できます。web.dev にログインすると、サイトに対して Lighthouse 監査を定期的に実行し、スコアの推移を確認できます。測定ページについては、後ほど詳しく説明します。🎊

はじめに

基本的に、web.dev は、Markdown ファイルのコレクションから生成される静的サイトです。Eleventy を選択したのは、洗練された拡張可能なツールであり、Markdown を HTML に変換するのが簡単だからです。

また、最新の JavaScript バンドルも使用します。これは、asyncawait など、type="module" をサポートするブラウザにのみ配信されます。また、常時使用できるブラウザではサポートされているが、少数の古いバージョンではサポートされていない機能も活用しています。 Google は静的なサイトなので、コンテンツを読み取るために JavaScript は必ずしも必要というわけではありません

静的 HTML を生成し、JavaScript を Rollup にバンドルするビルドプロセスが完了したら、テスト用のシンプルな静的サーバーで web.dev をホストできます。 このサイトはほぼ完全に静的ですが、特別なニーズもいくつかあり、カスタム Node.js サーバーのメリットを享受できます。 たとえば、無効なドメインへのリダイレクトや、今後の国際化機能でユーザーの希望する言語を解析するコードなどです。

静的生成

web.dev の各ページはマークダウンで記述されます。すべてのページには前書きが含まれ、各投稿に関するメタデータが記述されています。このメタデータは各ページのレイアウトに取り込まれ、見出しやタグなどが作成されます。次の例をご覧ください。

---
layout: post
title: What is network reliability and how do you measure it?
authors:
  - jeffposnick
date: 2018-11-05
description: |
  The modern web is enjoyed by a wide swath of people…
---

The modern web is enjoyed by a wide swath of [people](https://www.youtube.com/watch?v=dQw4w9WgXcQ), using a range of different devices and types of network connections.

Your creations can reach users all across the world...

このフロントマターで、著者、公開日、タグなどの任意のプロパティを定義できます。Eleventy は、インテリジェントに処理したいほぼすべてのプラグイン、テンプレート、その他のコンテキストで、第一線をデータとして便利に公開しています。 データ オブジェクトには、Eleventy がデータ カスケードと呼ぶものも含まれています。これは、個々のページ、ページで使用されているレイアウト、階層フォルダ構造にあるデータから取得されたさまざまなデータです。

各一意のレイアウトは異なるタイプのコンテンツを表し、他のレイアウトから継承できます。web.dev では、この機能を使用して、1 つの最上位 HTML レイアウトを共有しながら、さまざまな種類のコンテンツ(投稿や Codelab など)を正しくフレーム設定しています。

コレクション

Eleventy は、任意のコンテンツ コレクションをプログラマティックに作成する方法を提供します。これにより、ページネーションのサポートを構築し、投稿作成者向けに仮想ページ(ディスクに一致する Markdown ファイルがないページ)を生成できるようになりました。たとえば、固定リンクの式(著者ごとにテンプレートが再レンダリングされるようにするため)とバッキング コレクションを含むテンプレートを使用して、著者ページを作成します。

たとえば、Addy のすべての投稿を含むシンプルなページを作成できます。

制限事項

現在のところ、Eleventy のビルドプロセスに簡単にフックすることはできません。これは、命令型ではなく宣言型であるためです。つまり、どのようにするかではなく、何をするかを指定するものです。Eleventy はコマンドライン インターフェースからのみ呼び出すことができるため、大規模なビルドツールの一部として実行することは困難です。

テンプレート

web.dev は、Mozilla によって最初に開発された Nunjucks テンプレート システムを使用します。Nunjucks には、ループや条件などの一般的なテンプレート機能に加えて、HTML を生成したり、他のロジックを呼び出したりするためのショートコードを定義することもできます。

静的コンテンツ サイトを構築するほとんどのチームと同様に、最初は少数のショートコードから始め、徐々にショートコードを追加していきました。現在のところ、約 20 個のショートコードを使用しています。これらのほとんどは、(カスタム ウェブ コンポーネントを含む)追加の HTML を生成します。次の例をご覧ください。

{% Aside %}
See how Asides work in the web.dev codebase
{% endAside %}

最終的なコードは次のようになります。

実際には、次のような HTML が作成されます。

<div class="aside color-state-info-text">
<p>See how Asides work in the web.dev codebase</p>
</div>

この投稿の範囲外ですが、web.dev でも、一種のメタプログラミング言語としてショートコードを使用しています。ショートコードは引数を受け取ります。その引数の 1 つが、含まれるコンテンツです。ショートコードが何かを返す必要はありません。そのため、状態の構築や他の動作のトリガーに使用できます。🤔?💭?

スクリプト

前述のように、web.dev は静的サイトであるため、JavaScript なしで提供および使用できます。また、type="module" やその他の最新のコードに対応していない古いブラウザでも使用できます。これは、すべてのユーザーが web.dev にアクセスできるようにするための Google のアプローチにおいて非常に重要な部分です。

ただし、最新ブラウザ向けのコードは、主に次の 2 つの部分で構成されています。

  1. ブートストラップ コード(グローバル状態、アナリティクス、SPA ルーティングのコードを含む)
  2. サイトを段階的に強化するウェブ コンポーネントのコードと CSS

ブートストラップ コードは非常にシンプルです。web.dev は新しいページをシングルページ アプリケーション(SPA)として読み込むことができるため、ローカルの <a href="..."> 要素のクリックをリッスンするグローバル リスナーをインストールします。SPA モデルは、ユーザーの現在のセッションに関するグローバル状態を維持するのに役立ちます。そうでない場合、新しいページが読み込まれるたびに、ユーザーのログイン状態にアクセスするために Firebase への呼び出しがトリガーされます。

また、ヒットした URL に基づいてサイトへの複数のエントリポイントを指定し、動的な import() を使用して正しいエントリポイントを読み込みます。これにより、サイトがコードで拡張される前にユーザーが必要とするバイト数が削減されます。

ウェブ コンポーネント

ウェブ コンポーネントは、JavaScript で提供されるランタイム機能をカプセル化するカスタム要素であり、<web-codelab> などのカスタム名で識別されます。このデザインは、web.dev のような主に静的なサイトに適しています。サイトの HTML が更新されるとブラウザが要素のライフサイクルを管理し、要素がページからのアタッチまたはデタッチされたときに要素を正しく通知します。また、旧式のブラウザでは Web Components を完全に無視して、DOM に残っているものをレンダリングするだけです。

各ウェブ コンポーネントは、connectedCallback()disconnectedCallback()attributeChangedCallback() などのメソッドを持つクラスです。web.dev のカスタム要素のほとんどは LitElement から継承されており、複雑なコンポーネントのシンプルな基盤を提供します。

web.dev は多くのページで Web Components を使用しますが、[Measure] ページほど必要な場所はありません。 このページに表示される機能の大部分は、次の 2 つの要素によって提供されます。

<web-url-chooser-container></web-url-chooser-container>
<web-lighthouse-scores-container></web-lighthouse-scores-container>

これらの要素は、さらに多くの機能を提供する要素を作成します。重要なのは、これらの要素は通常の Markdown ソースコードの一部にすぎないことです。コンテンツ チームは、Measure ノードだけでなく、任意のページに拡張機能を追加できます。

Google のウェブ コンポーネントでは、React で普及したコンテナ コンポーネント モデルが最も一般的に使用されていますが、このモデルは現在は時代遅れになっています。各 -container 要素は(unistore によって提供される)グローバル状態に接続し、視覚要素をレンダリングします。それによって、スタイル設定やその他の組み込み機能を持つ実際の DOM ノードがレンダリングされます。

グローバル状態と、その状態を使用する HTML 要素の関係を示す図。
グローバル状態とウェブ コンポーネント

最も複雑なウェブ コンポーネントは、グローバルなアクションと状態を可視化するために存在します。たとえば、web.dev では、お気に入りのサイトを監査してから、[測定] ページから離れることができます。戻ると、タスクがまだ進行中であることがわかります。

シンプルなコンポーネントは、静的なコンテンツを純粋に強化したり、素晴らしい可視化を作成したりします(各折れ線グラフが独自の <web-sparkline-chart> であるなど)。グローバル状態とは関係ありません。

お問い合わせ

web.dev のエンジニアリング チーム(RobEwaMichaelSam)が、技術的な詳細を追って説明します。

Google の取り組みについてご紹介し、皆様のプロジェクトのヒントになれば幸いです。このブログについてご質問やトピックのリクエストがございましたら、Twitter でお問い合わせください。