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

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

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

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

また、最新の JavaScript バンドルも使用します。これは、asyncawait など、type="module" をサポートするブラウザにのみ配信されます。また、一部の古いバージョンではサポートされていないものの、エバーグリーン ブラウザでサポートされている機能も使用しています。静的サイトであるため、コンテンツの読み取りに JavaScript は不要です。

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

静的生成

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

---
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 が更新されると、ブラウザが要素のライフサイクルを管理し、要素がページに接続または切断されたときに要素に正しく通知します。古いブラウザでは、ウェブ コンポーネントは完全に無視され、DOM に残っているものがすべてレンダリングされます。

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

web.dev では多くのページでウェブ コンポーネントを使用していますが、[測定] ページほど必要性が高いページはありません。このページに表示される機能の大部分は、次の 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 でお問い合わせください。