Chrome' 無頭模式升級:--headless=new

Chrome 的無頭模式功能再進化!

Mathias Bynens
Mathias Bynens
Peter Kvitek
Peter Kvitek

Chrome 的無頭模式功能再進化!本文會概略介紹近期的工程技術,藉由讓「Headless」更接近 Chrome 的一般「頭版」模式,為開發人員提供更實用的服務。

背景

2017 年,Chrome 59 推出「無頭版」模式,可讓你在無人看管的環境中執行瀏覽器,而沒有任何使用者介面。基本上,在不使用 Chrome 的情況下執行 Chrome!

無頭模式經常是透過 PuppeteerChromeDriver 等專案自動進行瀏覽器自動化。以下是最基本的指令列範例,說明如何使用無頭模式建立指定網址的 PDF 檔案:

chrome --headless --print-to-pdf https://developer.chrome.com/

無頭介面有什麼新功能?

在進一步探討最新無標題的改良功能之前,請務必瞭解「舊」的無頭耳機是怎麼運作的。我們稍早顯示的指令列程式碼片段使用 --headless 指令列標記,表明 Headless 只是一般 Chrome 瀏覽器的一種作業模式。可能出乎意料,但這其實不是真的。就技術層面而言,舊的無頭版是獨立的瀏覽器實作方式,日後做為同一種 Chrome 二進位檔一併出貨。也不會在 //chrome 中分享任何 Chrome 瀏覽器程式碼。

您可能會想到,實作及維護這個獨立的無頭瀏覽器瀏覽器會產生大量的工程負擔,但這並非唯一的問題。由於 Headless 是獨立的實作方式,因此有部分 Chrome 未提供的錯誤和功能。這會產生令人困惑的情況,因為任何自動化瀏覽器測試都可能會在無頭模式下失敗,但在無頭模式下失敗,反之亦然;這對自動化工程師來說是一大問題。也會排除所有依賴安裝瀏覽器擴充功能的自動測試。任何其他瀏覽器層級功能也是如此:除非 Headless 有個別的實作方式,否則不受支援。

Chrome 團隊在 2021 年著手解決這個問題,並全面整合無頭和頭腦模式。

新版 Chrome Headless 已不再是獨立運作的瀏覽器,現在改將程式碼提供給 Chrome。

很高興在此宣布,新的無頭模式現已在 Chrome 112 中推出!在這個模式下,Chrome 會建立但不會顯示任何平台視窗。所有其他功能 (包括現有和日後推出的功能) 皆可使用,沒有限制。

體驗全新的無頭遊戲

如要試用新的無頭模式,請傳送 --headless=new 指令列標記:

chrome --headless=new

目前仍可透過以下方式使用舊版無頭模式:

chrome --headless=old

目前,在沒有明確值的情況下傳遞 --headless 指令列旗標,仍會啟用舊的無頭模式,不過我們計劃逐步將此預設值變更為新的無頭戴頭模式。

我們計劃將舊版 Headless 從 Chrome 二進位檔完全移除,並在今年稍晚停止支援 Puppeteer 這個模式。同時,我們會將舊版無頭耳機做為獨立二進位檔,供尚未升級的使用者使用。

Puppeteer 中的全新無頭使用者介面

如要在 Puppeteer 中選擇採用新的無頭模式模式,請按照下列步驟操作:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: 'new',
  // `headless: true` (default) enables old Headless;
  // `headless: 'new'` enables new Headless;
  // `headless: false` enables "headful" mode.
});

const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');

// …

await browser.close();

Selenium-WebDriver 中的全新無頭使用者介面

如何在 Selenium-WebDriver 中使用全新的無頭模式:

const driver = await env
  .builder()
  .setChromeOptions(options.addArguments('--headless=new'))
  .build();

await driver.get('https://developer.chrome.com/');

// …

await driver.quit();

詳情請參閱 Senium 團隊的網誌文章,以及使用其他語言繫結的範例。

無頭專用的指令列旗標

下列指令列旗標適用於全新的無頭模式。

--dump-dom

--dump-dom 旗標會將目標頁面的序列化 DOM 列印至 stdout。範例如下:

chrome --headless=new --dump-dom https://developer.chrome.com/

請注意,這不同於直接列印 HTML 原始碼 (您可以使用 curl 處理)。為了提供 --dump-dom 的輸出內容,Chrome 會先將 HTML 程式碼剖析為 DOM,然後執行可能修改 DOM 的任何 <script>,再將該 DOM 轉換回 HTML 的序列化字串。

--screenshot

--screenshot 旗標會擷取目標網頁的螢幕截圖,並儲存為 screenshot.png 在目前工作目錄中。與 --window-size 旗標搭配使用時特別實用。範例如下:

chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/

--print-to-pdf

--print-to-pdf 旗標會在目前的工作目錄中,將目標網頁儲存為名為 output.pdf 的 PDF 檔案。範例如下:

chrome --headless=new --print-to-pdf https://developer.chrome.com/

或者,您可以新增 --no-pdf-header-footer 旗標來省略列印標頭 (包含目前日期和時間) 和頁尾 (含網址和頁碼)。

chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/

--timeout

--timeout 旗標會定義 --dump-dom--screenshot--print-to-pdf 擷取網頁內容的等待時間上限 (以毫秒為單位),即使網頁仍在載入中也一樣。

chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/

--timeout=5000 旗標會指示 Chrome 等候最多 5 秒再列印 PDF。因此這項程序最多需要 5 秒才能完成。

--virtual-time-budget

--virtual-time-budget 提供時光旅行!有些時候,虛擬時間可當做任何時間相關程式碼 (例如 setTimeout/setInterval) 的「快轉」使用。這會強制瀏覽器盡快執行任何網頁程式碼,同時讓網頁認為時間確實有時間。

為了說明其用途,請考慮使用 setTimeout(fn, 1000)這個示範頁面,每秒會遞增、記錄並顯示計數器。相關程式碼如下:

<output>0</output>
<script>
  const element = document.querySelector('output');
  let counter = 0;
  setInterval(() => {
    counter++;
    console.log(counter);
    element.textContent = counter;
  }, 1_000);
</script>

一秒後,頁面含有「1」;兩秒之後,「2」以此類推。以下說明如何在 42 秒後擷取頁面狀態,並儲存為 PDF:

chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time

--allow-chrome-scheme-url

如要存取 chrome:// 網址,必須使用 --allow-chrome-scheme-url 旗標。這個旗標自 Chrome 123 版起開放使用。範例如下:

chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu

偵錯

由於 Chrome 實際上在無頭模式下確實無作用,因此發生問題時可能難以察覺。不過幸好,無頭 Chrome 的偵錯方式,就像有頭版的 Chrome 非常類似。秘訣就是透過 --remote-debugging-port 指令列旗標,以無頭模式啟動 Chrome。

chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/

這會將專屬的 WebSocket 網址列印至 stdout,例如:

DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9

在一般的 Chrome 執行個體中,我們可以使用 Chrome 開發人員工具遠端偵錯功能連線至無頭目標,並進行檢查。如要這麼做,請前往 chrome://inspect,按一下「Configure...」按鈕,然後輸入 WebSocket 網址的 IP 位址和通訊埠號碼。在上述範例中,我輸入了 127.0.0.1:60926。按一下「完成」,您應該會看到遠端目標包含下列所有分頁和其他目標。按一下「檢查」inspect,即可使用 Chrome 開發人員工具檢查遠端無頭目標,inspect

Chrome 開發人員工具可以檢查遠端無頭目標頁面

意見回饋:

期待收到您對全新無頭模式的使用意見。如果您遇到任何問題,請向我們回報