Skip to main content
只要輪詢一個 JSON 檔,就能知道一個工作階段是就緒、壞掉,還是已經消失。 每一次 dev、start、preview 與 build 執行,都會在每次編譯時原子性地寫入 dist/extension-js/<browser>/ready.json。目前的契約是 schemaVersion: 2。 沒有建置產物的 preview 會載入原始碼資料夾,但仍然把契約寫到專案的 dist/extension-js/<browser>/ready.json,並帶有已建置的 preview 所帶的全部瀏覽器欄位。

狀態

兩階段就緒

status: "ready" 只代表編譯完成,不代表更多。瀏覽器可能還在啟動,service worker 也可能還沒連上。 act 類工具(eval、storage、reload、open、inspect)需要第二個階段。要等到契約帶上 runtime: "attached" 與一個 executorAttachedAt 時間戳之後,再去驅動擴充功能。 attach 這個標記是冪等的,而且能撐過重新編譯。一次 attach 也會清掉先前的 extension_load_refused 狀態,因為執行器就跑在被控的瀏覽器裡面。

欄位參考(schema v2)

一定存在的欄位: 已知時才會出現的欄位:

錯誤狀態

code 欄位為失敗類別命名。對自動化來說有四個代碼要緊: 一次載入被拒會活過下一次成功編譯。只有一次新的執行(starting)或一次真正的執行器 attach 才能把它清掉。 瀏覽器在擴充功能載入之前就結束的 dev 工作階段,會跨重新編譯一直停在 error,因為重新編譯不會把瀏覽器帶回來。啟動失敗同樣會活過重新編譯,直到真的有一個瀏覽器啟動,或開始一次新的執行。

用 —wait 等待

extension dev --wait 與 extension start --wait 每 250 毫秒輪詢一次契約,並在它回報 ready 時結束。搭配 --output json 可以拿到機器可讀的結果。 等待迴圈拒絕相信過期的檔案。每次讀取都會跑三項檢查:
  1. command 欄位必須與正在等待的指令相符。
  2. pid 必須還活著。對 dev 而言,產生者已死一定代表檔案過期,所以會繼續輪詢。
  3. 對 start 而言,只有契約夠新鮮時才接受一個已死的 pid。新鮮的意思是 ts、compiledAt 或 startedAt 落在最近 60 秒內。
逾時會以 E_READY_TIMEOUT 結束。處於 error 狀態的契約會帶著它的 message 讓等待失敗,結果裡的 error.code 由契約自身的代碼解析而來: 帶 browserLaunchFailedCode: "E_BROWSER_BINARY_INVALID" 或 "E_FLAG_NOT_SUPPORTED_HERE" 的 browser_launch_failed 契約會讓等待以該代碼與 status: "usage" 失敗,而不是 E_BROWSER_LAUNCH。

把工作階段檔案串起來

同一個資料夾裡還有 events.ndjson(編譯時間軸)與 logs.ndjson(擴充功能的主控台輸出)。兩者的每一列都帶著來自 ready.json 的 runId。 events.ndjson 在每次執行開始時被清空,所以它永遠只描述目前這次執行。事件型別有 compile_start、compile_success、compile_error、browser_exited、browser_launch_failed 與 shutdown。browser_exited 這一列對應啟動器蓋下的結束標記,帶 exitCode、exitSignal 與 browserExitedAt,所以時間軸會說明瀏覽器是什麼時候、怎麼走的。在它之後,每個 act verb 都會回答 E_CONTROL_UNAVAILABLE,並指出這次結束與需要的重新啟動,因為在新的 dev 工作階段重新啟動瀏覽器之前,不會有 service worker 重新連上。browser_launch_failed 這一列對應啟動失敗的標記,帶 browserLaunchFailedAt 與 reason。

範例

後續步驟