web.dev 工程網誌 #1:我們如何製作網站並使用網頁元件

這是 web.dev 工程部落格的第一篇文章。我們希望在未來幾個月內,與各位分享我們在工作中獲得的實用洞察資料,敬請鎖定標有「工程師網誌」標記的文章!我們將在這裡介紹靜態網站的建構程序,以及 (選用)網頁元件背後的 JavaScript。

web.dev 提供有關建構現代化網站體驗的內容,並可讓您評估網站成效。精明的使用者可能已經發現,「評估」頁面只是Lighthouse 的介面,後者也可在 Chrome 的開發人員工具中使用。登入 web.dev 後,您就能定期在網站上執行 Lighthouse 稽核,瞭解分數隨時間變化的情形。我稍後會再回顧一下「評估」頁面,因為我們認為這個頁面相當特別。🎊?

基本上,web.dev 是由一系列 Markdown 檔案產生的靜態網站。 我們選擇使用 Eleventy,因為這是一款經過精心設計且可擴充的工具,可輕鬆將 Markdown 轉換為 HTML。

我們也使用新版 JavaScript 套件,只會提供給支援 type="module" 的瀏覽器,包括 asyncawait。我們也樂於使用永續瀏覽器支援的功能,但不支援少數舊版。因為我們是靜態網站,所以使用 JavaScript 來閱讀我們的內容就並不一定要使用 JavaScript。

建構程序 (包括產生靜態 HTML 和使用 Rollup 將 JavaScript 打包) 完成後,您可以使用簡單的靜態伺服器代管 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 上,我們會使用這項功能正確設定不同類型的內容 (例如文章和程式碼教室),同時共用一個頂層 HTML 版面配置。

集合

Eleventy 提供程式輔助方式,可用來建構任意內容集合。這讓我們能夠建構分頁支援功能,並為文章作者產生虛擬頁面 (在磁碟上沒有對應的 Markdown 檔案的頁面)。舉例來說,我們會使用包含永久連結運算式 (因此每位作者都會重新轉譯範本) 和後端集合的範本建構作者頁面。

舉例來說,這會產生一個簡單的網頁,其中包含Addy 的所有貼文

限制

目前我們無法輕易連結至 Eleventy 的建構程序,因為 Eleventy 是宣告式,而非命令式:您必須說明想要的內容,而非想要的內容。由於 Eleventy 只能透過指令列介面叫用,因此很難以大型建構工具的一部分來執行 Eleventy。

範本

web.dev 使用 Nunjucks 模板系統,該系統是由 Mozilla 原始開發。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 也會使用簡碼做為中繼程式設計語言的類型。 簡碼可接受引數,其中一個引數是包含的內容。簡碼不需要傳回任何值,因此可以用來建構狀態或觸發其他行為。🤔?💭?

影片腳本

如先前所述,由於 web.dev 是靜態網站,因此無須使用 JavaScript 即可提供及使用,且可供不支援 type="module" 或其他新式程式的舊版瀏覽器使用。這是我們讓所有人都能使用 web.dev 的做法中,非常重要的一環。

不過,我們為新式瀏覽器編寫的程式碼包含兩個主要部分:

  1. 啟動安裝程式程式碼,包括全域狀態、Analytics 和 SPA 路由的程式碼
  2. 網頁元件的程式碼和 CSS,逐步強化網站

引導程式碼相當簡單:web.dev 可將新網頁載入為單頁應用程式 (SPA),因此我們會安裝全域事件監聽器,監聽本機 <a href="..."> 元素的點擊動作。SPA 模型可協助我們維護使用者目前工作階段的全域狀態,否則每當新的網頁載入,都會觸發對 Firebase 的呼叫,以便存取使用者的登入狀態。

此外,我們也會根據您點選的網址,在網站上指定幾個不同的進入點,然後使用動態 import() 載入正確的進入點。 這樣一來,使用者在網站透過程式碼強化前,所需的位元組數量就會減少。

網頁元件

網頁元件是自訂元素,會封裝 JavaScript 提供的執行階段功能,且以 <web-codelab> 之類的自訂名稱識別。這項設計非常適合 web.dev 等主要為靜態網站:當網站的 HTML 更新時,瀏覽器會管理元素的生命週期,並正確通知任何元素何時附加或從網頁中移除。而過時的瀏覽器則會完全忽略網頁元件,並轉譯 DOM 中剩餘的內容。

每個網頁元件都是一個類別,其中包含 connectedCallback()disconnectedCallback()attributeChangedCallback() 等方法。web.dev 的自訂元素大多繼承自 LitElement,可為複雜元件提供簡單的基礎。

雖然 web.dev 在許多網頁上使用 Web 元件,但在Measure 頁面上使用 Web 元件最為必要。以下兩個元素可提供這個網頁提供的大部分功能:

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

這些元素會建立更多元素,提供更多功能。請注意,這些元素屬於一般 Markdown 原始碼的一部分,內容團隊可以在「任何」網頁上加入擴充功能,而不只是「測量」節點。

我們的網頁元件最常使用 React 推出的 容器元件模式,不過這個模式現在有點過時。每個 -container 元素都會連線至我們的全球狀態 (由 unistore 提供),然後算繪視覺元素,接著實際轉譯具有樣式或其他內建功能的實際 DOM 節點。

這張圖表顯示全域狀態與使用該狀態的 HTML 元素之間的關係。
全域狀態和網頁元件

我們最複雜的 Web 元件可用於將全域動作和狀態視覺化。舉例來說,web.dev 可讓您稽核喜愛的網站,然後離開「評估」頁面。如果您返回,會發現工作仍在進行中。

我們的簡單元件純粹是用來強化靜態內容,或建立精彩的視覺化資料 (例如每個線圖都是獨立的 <web-sparkline-chart>),與全域狀態無關。

歡迎洽詢

web.dev 工程團隊 (RobEwaMichaelSam) 很快就會推出更多技術深入分析。

希望這篇文章能讓您瞭解我們的做法,並為您提供一些專案構想。如有任何關於此網誌的問題或主題要求,歡迎透過 Twitter 與我們聯絡!