web.dev Engineering Blog Nummer 1: How we build the site and use Web Components

Dies ist der erste Beitrag im Engineering-Blog von web.dev. In den kommenden Monaten möchten wir umsetzbare Erkenntnisse aus unserer Arbeit teilen. Achtet also auf Beiträge mit dem Tag „Engineering Blog“. Hier geht es um den Erstellungsprozess für unsere statische Website und die (optionalen!) hinter unseren Webkomponenten.

web.dev bietet Inhalte zum Erstellen moderner Weberfahrungen und ermöglicht es Ihnen, die Leistung Ihrer Website zu messen. Erfahrene Nutzer haben vielleicht schon bemerkt, dass die Seite „Messen“ nur eine Benutzeroberfläche für Lighthouse ist, die auch in den Chrome DevTools verfügbar ist. Wenn Sie sich in web.dev anmelden, können Sie regelmäßige Lighthouse-Audits auf Ihrer Website ausführen und so sehen, wie sich die Bewertung im Laufe der Zeit ändert. Ich komme gleich noch einmal auf die Seite „Messen“ zurück, da wir sie für besonders wichtig halten. 🎊

Einführung

Im Grunde ist web.dev eine statische Website, die aus einer Sammlung von Markdown-Dateien generiert wird. Wir haben uns für Eleventy entschieden, weil es ein ausgefeiltes, erweiterbares Tool ist, mit dem sich Markdown-Inhalte ganz einfach in HTML umwandeln lassen.

Außerdem verwenden wir moderne JavaScript-Bundles, die nur für Browser ausgeliefert werden, die type="module" unterstützen, einschließlich async und await. Wir verwenden auch gerne Funktionen, die von Evergreen-Browsern unterstützt werden, aber von einer Minderheit älterer Versionen nicht. Da es sich bei unserer Website um eine statische Website handelt, ist JavaScript nicht erforderlich, um unsere Inhalte zu lesen.

Sobald der Build-Prozess, also die Generierung von statischem HTML und das Bündeln von JavaScript mit Rollup abgeschlossen ist, kann web.dev zu Testzwecken mit einem einfachen statischen Server gehostet werden. Die Website ist fast vollständig statisch, aber wir haben ein paar besondere Anforderungen, die dennoch von einem benutzerdefinierten Node.js-Server profitieren würden. Dazu gehören Weiterleitungen zu ungültigen Domains sowie Code zum Parsen der bevorzugten Sprache eines Nutzers für eine bevorstehende Internationalisierungsfunktion.

Statische Generierung

Jede Seite auf web.dev ist in Markdown geschrieben. Alle Seiten enthalten Vorwort, in dem Metadaten zu jedem Beitrag beschrieben werden. Diese Metadaten werden in das Layout jeder Seite aufgenommen, wodurch Überschriften, Tags usw. erstellt werden. Beispiel:

---
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...

In diesem Vorspann können wir beliebige Eigenschaften wie Autoren, Veröffentlichungsdatum und Tags definieren. Eleventy stellt die erste Rechtsangelegenheit als Daten in fast jedem Plug-in, jeder Vorlage und jedem anderen Kontext bereit, in dem wir etwas Intelligentes tun möchten. Das Datenobjekt enthält auch die von Eleventy als Datenkaskade bezeichnete Vielzahl von Daten, die von jeder einzelnen Seite, dem verwendeten Layout und den Daten in der hierarchischen Ordnerstruktur abgerufen werden.

Jedes Layout beschreibt einen anderen Inhaltstyp und kann andere Layouts übernehmen. Auf web.dev verwenden wir diese Funktion, um verschiedene Arten von Inhalten (z. B. Beiträge und Codelabs) korrekt einzurahmen und gleichzeitig ein gemeinsames HTML-Layout auf oberster Ebene zu verwenden.

Sammlungen

Eleventy bietet eine programmatische Möglichkeit, beliebige Inhaltssammlungen zu erstellen. So konnten wir die Paginierung unterstützen und virtuelle Seiten (Seiten ohne entsprechende Markdown-Datei auf dem Laufwerk) für die Autoren von Beiträgen generieren. Zum Beispiel verwenden wir für unsere Autorenseiten eine Vorlage, die einen Ausdruck für ihren Permalink (damit die Vorlage für jeden Autor neu gerendert wird) und eine unterstützende Sammlung enthält.

So entsteht beispielsweise eine einfache Seite mit allen Beiträgen von Addy.

Beschränkungen

Derzeit können wir den Build-Prozess von Eleventy nicht einfach einbinden, da er deklarativ und nicht imperativ ist: Sie beschreiben, was Sie möchten, nicht wie Sie es möchten. Es ist schwierig, Eleventy als Teil eines größeren Build-Tools auszuführen, da es nur über die Befehlszeile aufgerufen werden kann.

Vorlagen

Auf web.dev wird das Nunjucks-Template-System verwendet, das ursprünglich von Mozilla entwickelt wurde. Nunjucks bietet die üblichen Funktionen für Vorlagen wie Schleifen und Bedingungen, aber auch die Möglichkeit, Shortcodes zu definieren, die weiteres HTML generieren oder andere Logik aufrufen.

Wie die meisten Teams, die Websites mit statischen Inhalten erstellen, haben wir klein angefangen und nach und nach shortcodes hinzugefügt – bisher etwa 20. Die meisten erzeugen einfach weiteren HTML-Code, einschließlich unserer benutzerdefinierten Webkomponenten. Beispiel:

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

Sie sieht dann so aus:

Tatsächlich wird aber folgender HTML-Code erstellt:

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

Auf web.dev werden auch Shortcuts als eine Art Metaprogrammiersprache verwendet, was aber nicht Gegenstand dieses Artikels ist. Kurzcodes können Argumente enthalten, wobei einer der Inhalte ein Argument ist. Es ist nicht erforderlich, dass Shortcodes etwas zurückgeben. Sie können also zum Aufbau eines Zustands oder zum Auslösen eines anderen Verhaltens verwendet werden. 🤔💭

Skripting

Da web.dev eine statische Website ist, kann sie, wie bereits erwähnt, ohne JavaScript bereitgestellt und verwendet werden. Dies gilt auch für ältere Browser, die type="module" oder unseren anderen modernen Code nicht unterstützen. Das ist ein wichtiger Teil unseres Ansatzes, web.dev für alle zugänglich zu machen.

Der Code für moderne Browser besteht jedoch aus zwei Hauptteilen:

  1. Bootstrap-Code, der Code für globalen Status, Analytics und SPA-Routing enthält
  2. Code und CSS für Webkomponenten, die die Website kontinuierlich verbessern

Der Bootstrap-Code ist ziemlich einfach: web.dev kann neue Seiten als Single-Page-Anwendung (SPA) laden. Daher installieren wir einen globalen Listener, der auf Klicks auf lokale <a href="...">-Elemente wartet. Das SPA-Modell hilft uns, den globalen Status der aktuellen Nutzersitzung beizubehalten, da sonst bei jedem neuen Seitenaufbau Aufrufe an Firebase ausgelöst werden, um auf den Anmeldestatus eines Nutzers zuzugreifen.

Außerdem geben wir je nach aufgerufener URL verschiedene Einstiegspunkte auf unserer Website an und laden den richtigen mithilfe von dynamischen import()-Werten. So wird die Anzahl der Bytes reduziert, die unsere Nutzer benötigen, bevor die Website mit Code erweitert wird.

Webkomponenten

Webkomponenten sind benutzerdefinierte Elemente, die Laufzeitfunktionen in JavaScript kapseln. Sie werden durch benutzerdefinierte Namen wie <web-codelab> identifiziert. Das Design eignet sich gut für weitgehend statische Websites wie web.dev: Der Browser verwaltet den Lebenszyklus eines Elements, während das HTML einer Website aktualisiert wird, und informiert alle Elemente korrekt, wenn sie an der Seite angehängt oder von ihr getrennt werden. Und veraltete Browser ignorieren einfach die Webkomponenten und rendern, was im DOM übrig bleibt.

Jede Webkomponente ist eine Klasse mit Methoden wie connectedCallback(), disconnectedCallback() und attributeChangedCallback(). Die benutzerdefinierten Elemente von web.dev werden größtenteils von LitElement abgeleitet, das eine einfache Basis für komplexe Komponenten bietet.

Web.dev verwendet zwar Webkomponenten auf vielen Seiten, ist aber nirgendwo wichtiger als die Seite Measure (Messen). Zwei Elemente bieten den Großteil der Funktionen, die Sie auf dieser Seite sehen:

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

Aus diesen Elementen werden weitere Elemente erstellt, die mehr Funktionen bieten. Wichtig ist, dass diese Elemente nur ein Teil unseres normalen Markdown-Quellcodes sind. Unser Content-Team kann jeder Seite erweiterte Funktionen hinzufügen, nicht nur dem Messknoten.

Unsere Webkomponenten nutzen am häufigsten das Containerkomponenten-Modell, das durch React bekannt geworden ist. Dieses Modell ist jetzt aber noch ein wenig passé. Jedes -container-Element verbindet sich mit unserem globalen Status (von unistore bereitgestellt) und rendert dann ein visuelles Element, das wiederum tatsächliche DOM-Knoten mit Stil oder anderen integrierten Funktionen rendert.

Ein Diagramm, das die Beziehung zwischen dem globalen Zustand und den HTML-Elementen zeigt, die ihn verwenden.
Globaler Zustand und eine Webkomponente

Unsere komplexesten Webkomponenten dienen der Visualisierung globaler Aktionen und Status. Mit web.dev können Sie beispielsweise Ihre Lieblingswebsite analysieren und dann die Seite „Messen“ verlassen. Wenn Sie zurückkehren, sehen Sie, dass die Aufgabe noch nicht abgeschlossen ist.

Unsere einfachen Komponenten dienen dazu, ansonsten statische Inhalte zu ergänzen oder beeindruckende Visualisierungen zu erstellen (z. B. ist jeder Liniendiagramm ein eigenes <web-sparkline-chart>), die keinen Bezug zum globalen Status haben.

Jetzt chatten

Das Web.dev-Entwicklerteam (Rob, Ewa, Michael und Sam) wird sich bald mit weiteren technischen Details an Sie wenden.

Wir hoffen, dass wir Ihnen einige Ideen für Ihre eigenen Projekte geben konnten. Wenn du Fragen oder Themenvorschläge für diesen Blog hast, kannst du dich jederzeit auf Twitter an uns wenden.