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

Dies ist der erste Post im Engineering-Blog von web.dev. In den kommenden Monaten werden wir hoffentlich umsetzbare Erkenntnisse aus unserer Arbeit teilen. Achten Sie also auf Beiträge mit dem Tag für Engineering-Blog. Hier geht es um den Erstellungsprozess für unsere statische Website und den (optionalen!) JavaScript hinter unseren Webkomponenten.

Auf web.dev wird erklärt, wie Sie moderne Weberlebnisse schaffen. Außerdem können Sie dort die Leistung Ihrer Website messen. Erfahrene Nutzer haben vielleicht schon bemerkt, dass unsere Seite „Messen“ nur eine Benutzeroberfläche für Lighthouse ist, die auch in den Entwicklertools von Chrome verfügbar ist. Wenn Sie sich in web.dev anmelden, können Sie auf Ihrer Website regelmäßige Lighthouse-Prüfungen durchführen, um zu sehen, wie sich die Bewertung im Laufe der Zeit verändert. Da wir für etwas Besonderes denken, kann ich die Seite „Messen“ später noch einmal aufrufen. 🎊

Einleitung

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 sich um ein ausgefeiltes, erweiterbares Tool handelt, mit dem sich Markdown mühelos in HTML umwandeln lässt.

Außerdem verwenden wir moderne JavaScript-Bundles, die nur in Browsern verfügbar sind, die type="module" unterstützen. Dazu gehören async und await. Wir nutzen auch Funktionen, die von Evergreen-Browsern unterstützt werden, aber nicht von einer Minderheit älterer Versionen. Da wir eine statische Website sind, ist JavaScript nicht erforderlich, um unsere Inhalte zu lesen.

Sobald der Build-Prozess, der das Generieren von statischem HTML-Code und das Bündeln unseres JavaScripts mit Rollup abgeschlossen ist, abgeschlossen ist, kann web.dev zu Testzwecken mit einem einfachen statischen Server gehostet werden. Die Website ist fast vollständig statisch, aber es gibt einige spezielle Anforderungen, die noch von einem benutzerdefinierten Node.js-Server profitieren. Dazu gehören Weiterleitungen für ungültige Domains sowie Code zum Parsing der bevorzugten Sprache des Nutzers für eine künftige Internationalisierungsfunktion.

Statische Generierung

Jede Seite auf web.dev ist in Markdown geschrieben. Alle Seiten enthalten Front-Maßnahme, in der die Metadaten zu jedem Beitrag beschrieben werden. Diese Metadaten werden in das Layout jeder Seite aufgenommen und erstellen Überschriften, Tags usw. 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...

Damit können beliebige Eigenschaften wie Autor(en), Veröffentlichungsdatum und Tags definiert werden. Eleventy stellt das Frontmaterial praktisch in jedem Plug-in, jeder Vorlage oder jedem anderen Kontext als Daten zur Verfügung, in denen wir etwas Intelligentes tun möchten. Das Datenobjekt enthält auch das, was Eleventy als Datenkaskade beschreibt – eine Vielzahl von Daten, die von jeder einzelnen Seite, aus dem Layout der Seite und aus Daten in der hierarchischen Ordnerstruktur abgerufen werden.

In jedem einzelnen Layout wird ein anderer Inhaltstyp beschrieben und es können andere Layouts übernommen werden. Auf web.dev setzen wir diese Funktion ein, um verschiedene Inhaltstypen (wie Beiträge und Codelabs) korrekt in einen Frame zu setzen und gleichzeitig ein übergeordnetes HTML-Layout zu teilen.

Sammlungen

Eleventy bietet eine programmatische Möglichkeit zum Erstellen beliebiger Inhaltssammlungen. Auf diese Weise können wir die Paginierung unterstützen und virtuelle Seiten (Seiten ohne entsprechende Markdown-Datei auf der Festplatte) für die Verfasser von Beiträgen generieren. Beispielsweise erstellen wir die Autorenseiten mit einer Vorlage, die einen Ausdruck für seinen Permalink (sodass die Vorlage für jeden Autor neu gerendert wird) und eine unterstützende Sammlung enthält.

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

Beschränkungen

Im Moment können wir uns noch nicht so einfach in den Build-Prozess von Eleventy einbinden lassen, da er deklarativ und nicht unangemessen ist: Sie beschreiben, was Sie wollen, nicht wie Sie es möchten. Es ist schwierig, Eleventy im Rahmen eines größeren Build-Tools auszuführen, da es nur über die Befehlszeile aufgerufen werden kann.

Vorlagen

web.dev verwendet das Vorlagensystem Nunjucks, das ursprünglich von Mozilla entwickelt wurde. Nunjucks verfügt über die typischen Vorlagenfunktionen wie Schleifen und Bedingungen, ermöglicht uns aber auch die Definition von Kurzcodes, die weiteren HTML-Code generieren oder andere Logik aufrufen.

Wie die meisten Teams, die Websites mit statischen Inhalten erstellt haben, haben wir mit kleineren Teams begonnen und im Laufe der Zeit 20 kurz Codes hinzugefügt. Die meisten von ihnen generieren lediglich zusätzlichen HTML-Code (einschließlich unserer benutzerdefinierten Webkomponenten). Beispiel:

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

Die Ausgabe sieht dann so aus:

Tatsächlich wird aber HTML erstellt, das so aussieht:

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

Auch wenn es in diesem Beitrag nicht weitergeht, verwendet web.dev auch Shortcodes als eine Art Meta-Programmiersprache. Bei Kurzcodes können Argumente angegeben werden, wobei eines der Argumente der enthaltene Inhalt ist. Kurzcodes müssen nichts zurückgeben, sodass sie zum Aufbau eines Status oder zum Auslösen eines anderen Verhaltens verwendet werden können. 🤔💭

Skripting

Da web.dev eine statische Website ist, kann sie ohne JavaScript und von älteren Browsern, die type="module" oder unseren anderen modernen Code nicht unterstützen, bereitgestellt und verwendet werden. Das ist ein unglaublich wichtiger Teil unseres Ansatzes, um web.dev für alle zugänglich zu machen.

Unser Code für moderne Browser besteht jedoch aus zwei Hauptbestandteilen:

  1. Bootstrap-Code, der Code für globalen Status, Analytics und SPA-Routing enthält
  2. Code und CSS für Webkomponenten, mit denen die Website nach und nach verbessert wird

Der Bootstrap-Code ist ziemlich einfach: web.dev kann neue Seiten als Single-Page-Anwendung (SPA) laden. Daher installieren wir einen globalen Listener, der Klicks auf lokale <a href="...">-Elemente abhört. Mithilfe des SPA-Modells können wir den globalen Status der aktuellen Sitzung des Nutzers aufrechterhalten, da sonst jeder neue Seitenaufbau Aufrufe an Firebase auslösen würde, um auf den Anmeldestatus eines Nutzers zuzugreifen.

Je nachdem, welche URL Sie aufgerufen haben, legen wir auf unserer Website verschiedene Einstiegspunkte fest und laden mithilfe des dynamischen import() den richtigen Eintrag. Dies reduziert die Anzahl der Bytes, die unsere Nutzer benötigen, bevor die Website mit Code erweitert wird.

Webkomponenten

Webkomponenten sind benutzerdefinierte Elemente, die in JavaScript bereitgestellte Laufzeitfunktionen enthalten und durch benutzerdefinierte Namen wie <web-codelab> identifiziert werden. Das Design eignet sich gut für hauptsächlich statische Websites wie web.dev: Ihr Browser verwaltet den Lebenszyklus eines Elements, wenn der HTML-Code einer Website aktualisiert wird. Wenn Elemente an die Seite angehängt oder von ihr getrennt werden, werden sie korrekt informiert. Und veraltete Browser ignorieren Webkomponenten komplett und rendern alles, was im DOM verbleibt.

Jede Web Component ist eine Klasse mit Methoden wie connectedCallback(), disconnectedCallback() und attributeChangedCallback(). Die benutzerdefinierten Elemente von web.dev werden hauptsächlich von LitElement übernommen, das eine einfache Basis für komplexe Komponenten bietet.

Web.dev verwendet Webkomponenten auf vielen Seiten. Dies ist aber nirgendwo notwendiger als auf der Seite Messen. Zwei Elemente stellen den Großteil der Funktionen bereit, die Sie auf dieser Seite sehen:

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

Diese Elemente erstellen weitere Elemente, die mehr Funktionen bieten. Wichtig: Diese Elemente sind nur Teil unseres regulären Markdown-Quellcodes – und unser Content-Team kann jeder Seite erweiterte Funktionen hinzufügen – nicht nur dem Measure-Knoten.

In unseren Webkomponenten wird am häufigsten das von React beliebte Container Component-Modell verwendet, obwohl es jetzt etwas passé ist. Jedes -container-Element stellt eine Verbindung zu unserem globalen Zustand (bereit von unistore) her und rendert dann ein visuelles Element, das wiederum tatsächliche DOM-Knoten mit Stilen oder anderen integrierten Funktionen rendert.

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

Unsere komplexesten Webkomponenten dienen der Visualisierung globaler Aktionen und Status. Auf web.dev können Sie beispielsweise Ihre bevorzugte Website prüfen und dann die Seite „Messen“ verlassen. Wenn Sie zurückkehren, sehen Sie, dass die Aufgabe immer noch ausgeführt wird.

Mit unseren einfachen Komponenten lassen sich ausschließlich statische Inhalte optimieren und beeindruckende Visualisierungen erstellen (z. B. ist jedes Liniendiagramm ein eigenes <web-sparkline-chart>), das keinen Bezug zum globalen Status hat.

Jetzt chatten

Das web.dev-Entwicklerteam (Rob, Ewa, Michael und Sam) wird sich demnächst mit weiteren technischen Details bei Ihnen melden.

Wir hoffen, dass Ihnen unsere Vorgehensweise einige Ideen für Ihre eigenen Projekte gegeben hat. Schreibe uns auf Twitter, wenn du Fragen oder Themenvorschläge zu diesem Blog hast!