這是 web.dev 工程部落格的第一篇文章。我們希望在未來幾個月內,與各位分享我們在工作中獲得的實用洞察資料,請密切留意標有工程網誌標記的文章!我們將在這裡介紹靜態網站的建構程序,以及 (選用)網頁元件後方的 JavaScript。
web.dev 提供有關建構現代化網站體驗的內容,並可讓您評估網站成效。精明的使用者可能已經發現,「評估」頁面只是Lighthouse 的介面,後者也可在 Chrome 的開發人員工具中使用。登入 web.dev 後,您就能定期在網站上執行 Lighthouse 稽核,瞭解分數隨時間變化的情形。我稍後會再回顧一下「評估」頁面,因為我們認為這個頁面相當特別。🎊?
簡介
從根本上來說,web.dev 是從一系列 Markdown 檔案產生的靜態網站。我們選擇使用 Eleventy,因為這是一款經過精心設計且可擴充的工具,可輕鬆將 Markdown 轉換為 HTML。
我們也使用新版 JavaScript 套件,只會提供給支援 type="module"
的瀏覽器,包括 async
和 await
。我們也樂於使用永續瀏覽器支援的功能,但不支援少數舊版。由於我們是靜態網站,因此不必使用 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 上,我們會使用這項功能正確設定不同類型的內容 (例如文章和程式碼教室),同時共用一個頂層 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 的做法中,非常重要的一環。
不過,我們為新式瀏覽器編寫的程式碼包含兩個主要部分:
- 啟動安裝程式程式碼,包括全域狀態、Analytics 和 SPA 路由的程式碼
- 用於逐步改善網站的 Web 元件程式碼和 CSS
引導程式碼相當簡單:web.dev 可將新網頁載入為單頁應用程式 (SPA),因此我們會安裝全域事件監聽器,監聽本機 <a href="...">
元素的點擊動作。SPA 模型可協助我們維護使用者目前工作階段的全域狀態,否則每當載入新網頁,系統都會觸發對 Firebase 的呼叫,以存取使用者的登入狀態。
我們也會根據您點選的網址,在網站中指定幾個不同的進入點,並使用動態 import()
載入正確的進入點。這樣一來,使用者在網站使用程式碼強化前,所需的位元組數量就會減少。
網頁元件
Web 元件是自訂元素,可封裝 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 節點。
最複雜的 Web 元件可用於將全域動作和狀態視覺化。舉例來說,web.dev 可讓您稽核喜愛的網站,然後離開「評估」頁面。如果您返回,就會發現工作仍在進行中。
我們的簡單元件純粹是用來強化靜態內容,或建立精彩的視覺化資料 (例如每個線圖都是獨立的 <web-sparkline-chart>
),與全域狀態無關。
歡迎洽詢
web.dev 工程團隊 (Rob、Ewa、Michael 和 Sam) 很快就會推出更多技術深入分析。
希望這篇文章能讓您瞭解我們的做法,並為您提供一些專案構想。如有任何問題或想提出主題建議,歡迎透過 Twitter 與我們聯絡!