將 Puppeteer 遷移至 TypeScript

開發人員工具團隊非常喜歡 TypeScript,因此開發人員工具中的新程式碼都是以 TypeScript 編寫,我們也正將整個程式碼集大規模遷移至 TypeScript 進行型別檢查。如要進一步瞭解這項遷移作業,請參閱 2020 年 Chrome 開發人員高峰會的演講。因此,將 Puppeteer 的程式碼集遷移至 TypeScript 也十分合理。

規劃遷移作業

在規劃遷移方式時,我們希望能夠逐步完成。這樣一來,您一次只會處理一小部分程式碼,可降低遷移作業的負擔和風險。如果其中一個步驟發生錯誤,您可以輕鬆還原。Puppeteer 有許多使用者,如果發布的版本有問題,會對許多人造成影響,因此我們必須盡可能降低破壞性變更的風險。

我們也很幸運,Puppeteer 擁有一套強大的單元測試,涵蓋所有功能。這表示我們有信心在遷移時不會破壞程式碼,也不會對 API 進行變更。遷移的目標是讓所有 Puppeteer 使用者在不知不覺中完成遷移,而測試是這項策略的重要環節。如果測試涵蓋範圍不夠廣泛,我們會在繼續遷移之前新增測試。

在未經測試的情況下變更程式碼,會帶來風險,但如果變更涉及整個檔案或整個程式碼集,風險會特別高。在進行機械式變更時,很容易遺漏步驟,而測試多次發現了實作者和審查者都忽略的問題。

我們一開始就投入時間進行持續整合 (CI) 設定。我們發現,針對提取要求執行的 CI 不穩定,且經常失敗。這種情況太常發生,因此我們習慣忽略 CI,照常合併提取要求,並假設失敗是 CI 的一次性問題,而非 Puppeteer 的問題。

經過一般維護,並花費時間修正一些常見的測試不穩定問題後,我們讓測試通過的狀態更加穩定,因此可以監聽 CI,並瞭解失敗表示實際問題。這項工作並不光彩,而且看著無止盡的 CI 執行作業令人沮喪,但鑑於遷移作業會產生大量提取要求,因此可靠地執行測試套件至關重要。

挑選並放置一個檔案

此時我們已準備好遷移,並有穩固的 CI 伺服器,可執行大量測試來確保遷移過程順利。我們並非隨意選擇檔案,而是刻意挑選小型檔案進行遷移。這項練習非常實用,可讓您驗證即將執行的規劃程序。如果能順利處理這個檔案,就表示方法有效;如果不行,則可重新構思。

此外,逐一處理檔案 (並搭配定期發布的 Puppeteer 版本,因此所有變更不會在同一個 npm 版本中發布),可降低風險。我們選擇 DeviceDescriptors.js 做為第一個檔案,因為這是程式碼集最簡單的檔案之一。做完所有準備工作後,卻只進行這麼小的變更,可能會讓人覺得有點不夠,但我們的目標並非立即進行大幅變更,而是謹慎地逐一處理檔案。花時間驗證方法絕對值得,因為之後遇到較複雜的檔案時,可節省遷移時間。

證明模式並重複

幸好 DeviceDescriptors.js 的變更已成功納入程式碼集,而且計畫的運作方式也如我們所願!這時,您就可以開始著手進行,我們正是這麼做的。使用 GitHub 標籤是將所有提取要求分組的好方法,我們發現這有助於追蹤進度。

先遷移,稍後再改善

對於任何個別 JavaScript 檔案,我們的程序如下:

  1. 將檔案從 .js重新命名為 .ts。
  2. 執行 TypeScript 編譯器。
  3. 修正所有問題。
  4. 建立提取要求。

這些初始提取要求的大部分工作,都是為了擷取現有資料結構的 TypeScript 介面。以先前討論過、遷移 DeviceDescriptors.js 的第一個提取要求為例,程式碼從:

module.exports = [
  { 
    name: 'Pixel 4',
    … // Other fields omitted to save space
  }, 
  …
]

並成為:

interface Device {
  name: string,
  …
}

const devices: Device[] = [{name: 'Pixel 4', …}, …]

module.exports = devices;

在這個過程中,我們檢查了程式碼集中的每一行,找出問題。與任何已存在幾年且隨著時間成長的程式碼集一樣,有些地方可以重構程式碼並改善情況。特別是在改用 TypeScript 後,我們發現只要稍微重構程式碼,就能更依賴編譯器,並提高類型安全性。

但請注意,請勿立即進行這些變更。遷移的目標是將程式碼集移至 TypeScript,在大型遷移期間,您應隨時考量造成軟體和使用者中斷的風險。我們盡量減少初始變更,因此風險不高。檔案合併並遷移至 TypeScript 後,我們就能進行後續變更,改善程式碼以善用型別系統。請務必為遷移作業設定嚴格的界線,並盡可能遵守。

將測試遷移至測試型別定義

將整個原始碼遷移至 TypeScript 後,我們就能專注於測試。我們的測試涵蓋範圍很廣,但全都是以 JavaScript 編寫。這表示他們沒有測試我們的類型定義。這個專案的長期目標之一 (我們仍在努力) 是在 Puppeteer 中提供高品質的型別定義,但我們的程式碼集沒有任何型別定義的檢查。

將測試遷移至 TypeScript (按照相同程序,逐一處理檔案) 後,我們發現 TypeScript 有問題,否則使用者可能需要自行找出問題。現在我們的測試不僅涵蓋所有功能,還能檢查 TypeScript 的品質!

身為 Puppeteer 程式碼集工程師,我們已從 TypeScript 獲益良多。搭配大幅改善的 CI 環境,我們在 Puppeteer 上的工作效率更高,且 TypeScript 能找出原本會進入 npm 版本的錯誤。我們很高興能提供高品質的 TypeScript 定義,讓所有使用 Puppeteer 的開發人員也能從中受益。

下載預先發布版

建議使用 Chrome Canary、開發人員版或 Beta 版做為預設開發瀏覽器。這些預覽管道可讓您存取最新的開發人員工具功能、測試尖端的網路平台 API,並在使用者發現網站問題前,搶先找出問題!

聯絡 Chrome 開發人員工具團隊

您可以透過下列管道,討論新功能、更新或任何與開發人員工具相關的事項。

  • 如要提交意見回饋和功能要求,請前往 crbug.com。
  • 如要回報開發人員工具問題,請在開發人員工具中依序選取「more_vert」「更多選項」 >「說明」 >「回報開發人員工具問題」。
  • 在 Twitter 上發布推文並標記 @ChromeDevTools。
  • 在「開發人員工具新功能」YouTube 影片或「開發人員工具提示」YouTube 影片中留言。