執行環境套件管理器打包器測試執行器程式碼檢查格式化指南參考部落格意見回饋

WebView

通過 Bun 控制無頭瀏覽器,用於自動化、測試和抓取 — 在 macOS 上零相依;其餘平臺到處都是 Chrome DevTools Protocol

Bun.WebView 是內建在執行環境中的無頭瀏覽器。使用它來載入頁面、在其中執行 JavaScript、模擬真實使用者輸入,並擷取螢幕截圖 — 不需要 Puppeteer、Playwright,也不需要單獨下載瀏覽器。

TypeScript
await using view = new Bun.WebView();

await view.navigate("https://example.com");
await view.click("a[href]"); // 等待連結變為可點選
const title = await view.evaluate("document.title");

await Bun.write("page.png", await view.screenshot());

在 macOS 上,Bun.WebView 使用系統的 WKWebView — 無需安裝任何東西。在 Linux 和 Windows 上,它會通過 Chrome DevTools Protocol 驅動已安裝的 Chrome、Chromium、Edge 或 Brave;在 Windows 上,預裝的 Edge 就足夠了。

每個檢視都會在單獨的渲染器行程中執行其頁面。所有輸入方法(click、type、press、scroll)都會分發原生瀏覽器事件,因此頁面會看到 isTrusted: true — 與真實使用者一致。


建立檢視

TypeScript
const view = new Bun.WebView({
  width: 1280, // 視口寬度(CSS 畫素,1-16384,預設 800)
  height: 720, // 視口高度(CSS 畫素,1-16384,預設 600)
  url: "https://bun.sh", // 可選:立即開始導航
});

建構函式是同步的——它會立即傳回,並在後臺啟動瀏覽器子行程。你 await 的第一個操作(例如 navigate() 或 evaluate())會等待瀏覽器準備就緒。

如果傳入 url,檢視會在建構函式傳回前開始導航,效果與在下一行呼叫 view.navigate(url) 相同。不同之處在於:建構函式會將導航的 promise 保留在內部,因此失敗時不會產生拒絕。設定 onNavigationFailed 以便觀察導航失敗。

使用 using 的自動清理

Bun.WebView 實現了 Symbol.dispose 和 Symbol.asyncDispose,因此你可以使用 using 或 await using,當檢視超出作用域時自動關閉:

TypeScript
{
  await using view = new Bun.WebView();
  await view.navigate("https://example.com");
  // ...
} // 這裡會自動呼叫 view.close()

持久化儲存

預設情況下,每個檢視使用短暫的記憶體儲存 — cookies、localStorage、IndexedDB 和快取都會在檢視關閉時丟棄。要在多次執行之間持久化狀態,請傳入目錄:

TypeScript
const view = new Bun.WebView({
  dataStore: { directory: "./browser-profile" },
});

共享同一個 directory 的檢視會共享 cookies 和儲存。傳入 dataStore: "ephemeral"(預設值)以顯式回到記憶體儲存。


後端

Bun.WebView 支援兩種渲染引擎。預設取決於你的平臺:

後端引擎平臺要求
"webkit"WKWebView僅 macOS無 — 使用系統的 WebKit.framework
"chrome"BlinkmacOS / Linux / Windows已安裝 Chrome、Chromium、Edge 或 Brave(或 Playwright 的 chrome-headless-shell)

在 macOS 上,預設後端是 "webkit";其他平臺預設使用 "chrome"。在非 macOS 平臺請求 backend: "webkit" 會丟擲異常。"chrome" 後端每個行程驅動一個瀏覽器,且只能從主執行緒使用;在 Worker 中構造它會丟擲異常。

TypeScript
// 在 macOS 上強制使用 Chrome
const view = new Bun.WebView({ backend: "chrome" });

WebKit 後端如何工作

Bun 會生成一個輕量級宿主子行程(即 bun 二進位制檔案本身,以特殊模式重新執行),由它在主執行緒上管理 WKWebView。你的 Bun 行程通過 Unix socket 使用緊湊的二進位制協議與其通訊。Bun 只生成一次宿主行程,你的程式中的每個 "webkit" 檢視都會共用它。

Chrome 後端如何工作

Bun 要麼連線到一個已經執行的 Chrome(通過 WebSocket),要麼生成一個無頭 Chrome 子行程,並通過管道與它通訊(--remote-debugging-pipe)。無論哪種方式,通訊都使用 Chrome DevTools Protocol。

Bun 每個行程只生成(或連線)一次 Chrome。每個 new Bun.WebView({ backend: "chrome" }) 都會在該 Chrome 例項中使用 Target.createTarget 建立一個新標籤頁。

查詢 Chrome 執行檔

當 Bun 需要生成 Chrome 時,它會按以下順序搜尋:

  1. 你在 backend: { type: "chrome", path: "..." } 中傳入的 path
  2. BUN_CHROME_PATH 環境變數
  3. $PATH(google-chrome-stable、google-chrome、chromium-browser、chromium、brave-browser、microsoft-edge、chrome;在 Windows 上為 chrome、chromium、brave、msedge)
  4. 標準安裝位置(/Applications/Google Chrome.app、~/Applications/...、/usr/bin/...、/snap/bin/...;在 Windows 上為 %ProgramFiles%、%ProgramFiles(x86)% 和 %LOCALAPPDATA% 下的 Application\*.exe 目錄)
  5. Playwright 的快取(~/Library/Caches/ms-playwright、~/.cache/ms-playwright 或 %LOCALAPPDATA%\ms-playwright)中的 chrome-headless-shell

如果 Bun 找不到 Chrome,建構函式會丟擲異常。

連線到已在執行的 Chrome

預設情況下,在生成瀏覽器之前,Bun 會從標準設定檔目錄讀取 DevToolsActivePort 檔案,以檢查是否已經有啟用了遠端除錯的 Chrome 系瀏覽器在執行。如果找到,Bun 會通過 WebSocket 連線到該瀏覽器,而不是生成新瀏覽器 — 你的檢視會作為標籤頁在現有瀏覽器中開啟。

要在執行中的 Chrome 中啟用遠端除錯,請訪問 chrome://inspect/#remote-debugging 並開啟開關,或者使用 --remote-debugging-port=9222 啟動 Chrome。使用 chrome://inspect 開關時,Chrome 會在每次建立新連線時請求許可權。

要顯式控制這一行為,請使用 backend 的物件形式:

TypeScript
// 總是生成一個新的無頭 Chrome;永遠不自動連線
new Bun.WebView({
  backend: { type: "chrome", url: false },
});

// 連線到特定的 DevTools WebSocket URL
new Bun.WebView({
  backend: {
    type: "chrome",
    url: "ws://127.0.0.1:9222/devtools/browser/abc123...",
  },
});

如果自動探測發現過期的 DevToolsActivePort 檔案(Chrome 崩潰或重啟),WebSocket 連線將失敗,並且 Bun 會透明地回退到生成自己的 Chrome。顯式指定 url: "ws://..." 不會回退 — 連線失敗會直接丟擲異常。

啟動引數

生成時,Bun 會傳入一組最小的引數:

Code
--user-data-dir=<temp> --remote-debugging-pipe --headless --no-first-run
--no-default-browser-check --disable-gpu --disable-extensions
--disable-background-networking --disable-background-timer-throttling
--disable-backgrounding-occluded-windows --disable-renderer-backgrounding
--disable-ipc-flooding-protection --no-startup-window

用 argv 把你自己的引數追加進去 — Chrome 處理重複開關時採用“最後生效”,因此你可以覆蓋任意預設值:

TypeScript
new Bun.WebView({
  backend: {
    type: "chrome",
    argv: ["--headless=new", "--lang=ja-JP", "--window-size=1920,1080"],
  },
});

子行程輸出

瀏覽器子行程的 stdout/stderr 預設會被靜默處理。尤其是 Chrome,其 stderr 輸出十分嘈雜(字型設定警告、GCM 註冊、更新程式檢查)。要檢視這些輸出 — 在 Chrome 靜默崩潰時很有用 — 請傳入 "inherit":

TypeScript
new Bun.WebView({
  backend: { type: "chrome", stderr: "inherit", stdout: "inherit" },
});

"webkit" 後端也接受相同的 stdout/stderr 選項。


導航

TypeScript
await view.navigate("https://example.com");
await view.navigate("data:text/html,<h1>hello</h1>");
await view.navigate("file:///path/to/index.html");

當主框架的 load 事件觸發時,navigate() 才會解析完成。解析完成後,view.url 和 view.title 會反映新頁面,且 view.loading 為 false。

如果導航失敗(DNS 失敗、連線被拒絕、URL 無效),該 promise 會以描述失敗原因的 Error 形式拒絕。

每個檢視在任一時刻只能進行一個正在進行的導航。若在另一個 navigate() 仍待處理時再次呼叫 navigate(),會同步丟擲 ERR_INVALID_STATE。

歷史記錄

TypeScript
await view.goBack(); // 類似瀏覽器的傳回按鈕
await view.goForward(); // 類似瀏覽器的前進按鈕
await view.reload(); // 重新載入當前頁面

在歷史記錄的起點(或終點)呼叫 goBack()(或 goForward())會直接解析為 undefined,不進行導航 — 不會拒絕。

導航回撥

設定 onNavigated 和 onNavigationFailed 來觀察每一次導航,包括頁面自身觸發的導航(點選連結、location.href = ...、重定向)以及由 reload()/goBack()/goForward() 觸發的導航:

TypeScript
view.onNavigated = (url, title) => {
  console.log("Loaded", url);
};

view.onNavigationFailed = error => {
  console.error("Navigation failed:", error.message);
};

這些回撥會在對應的 navigate() promise 完成(settle)之前觸發,因此當你 await view.navigate(...) 傳回時,你的回撥已經執行過了。設定為 null 可移除。


計算 JavaScript

在頁面的主框架中執行一個表示式,並把結果作為原生 JavaScript 值傳回:

TypeScript
const title = await view.evaluate("document.title");
const items = await view.evaluate("[...document.querySelectorAll('li')].map(li => li.textContent)");
const user = await view.evaluate("({ name: 'bun', ok: true })");

Bun 會將指令碼包裝為 await (<your script>),因此:

  • 它必須是一個表示式,而不是語句序列。若要執行多個語句,請將它們包裝在 IIFE 中:evaluate("(() => { let x = foo(); return x + 1 })()")。
  • 如果計算結果是一個 Promise,evaluate() 會等待該 promise,並傳回其解析後的值。

結果會在頁面側通過 JSON.stringify,在 Bun 側通過 JSON.parse 來往返傳遞。陣列和普通物件會以真實結構傳回;undefined、函式和 symbol 會解析為 undefined;迴圈引用會導致拒絕。

TypeScript
await view.evaluate("42"); // 42
await view.evaluate("[1, 2, 3]"); // [1, 2, 3]
await view.evaluate("undefined"); // undefined
await view.evaluate("() => 1"); // undefined(函式不會序列化)
await view.evaluate("fetch('/api').then(r => r.json())"); // 已等待

如果指令碼丟擲異常(或傳回被拒絕的 promise),evaluate() 會拒絕,並把訊息作為頁面側異常資訊的一部分傳回一個 Error。

每個檢視在任一時刻只能進行一個正在進行的 evaluate();第二個並行呼叫會同步丟擲 ERR_INVALID_STATE。


截圖

把當前視口捕獲成圖片:

TypeScript
const png = await view.screenshot();
await Bun.write("page.png", png);

圖片格式

TypeScript
await view.screenshot({ format: "png" }); // 無損(預設)
await view.screenshot({ format: "jpeg", quality: 90 }); // 有損,quality 0-100(預設 80)
await view.screenshot({ format: "webp", quality: 75 }); // 僅 Chrome 後端

PNG 會忽略 quality。"webp" 只在 backend: "chrome" 時可用 — WebKit 後端會丟擲異常。

傳回型別

encoding 選項控制 Bun 如何傳回圖片位元組:

encoding傳回內容說明
"blob" (預設)BlobMIME 型別自動設定。WebKit 上基於 mmap 的零複製。可與 Bun.write()、new Response() 一起使用
"buffer"BufferNode Buffer。WebKit 上基於 mmap 的零複製
"base64"stringBase64 編碼。Chrome 上無需解碼(CDP 原生傳回 base64)
"shmem"{ name: string, size: number }POSIX 共享記憶體段名稱。呼叫方負責 shm_unlink。Windows 不支援
TypeScript
const buf = await view.screenshot({ encoding: "buffer" });
console.log(buf[0] === 0x89); // PNG 魔術位元組

const b64 = await view.screenshot({ encoding: "base64" });
console.log(`<img src="data:image/png;base64,${b64}">`);

終端圖形的共享記憶體

encoding: "shmem" 專為 Kitty 的終端圖形協議 t=s 傳輸模式設計。Bun 會將圖片寫入 POSIX 共享記憶體段並傳回其名稱。終端會直接讀取它,並在完成後取消連結。無需通過管道複製。

TypeScript
const { name, size } = await view.screenshot({ encoding: "shmem" });
process.stdout.write(`\x1b_Gf=100,t=s,a=T,S=${size};${btoa(name)}\x1b\\`);
// Kitty 從共享記憶體讀取 PNG 並取消連結該段

在 WebKit 上,shm 名稱看起來像 /bun-webview-<pid>-<seq>;在 Chrome 上是 /bun-chrome-<pid>-<seq>。如果你請求 "shmem",但沒有把名稱交給某個會執行 shm_unlink 的邏輯,那麼共享記憶體段會在你的行程退出前一直洩漏。


輸入模擬

所有輸入方法都會分發原生瀏覽器事件。頁面會收到 isTrusted: true 的 pointerdown/mousedown/keydown/wheel 事件。CSS :active 和 :hover 狀態會生效。預設操作(表單提交、連結導航、文本選擇)會與使用者實際操作時完全一樣地觸發。

點選

在視口座標處點選:

TypeScript
await view.click(150, 200);
await view.click(150, 200, { button: "right" });
await view.click(150, 200, { clickCount: 2 }); // 雙擊
await view.click(150, 200, { modifiers: ["Shift", "Meta"] });

promise 會在頁面處理完完整的 mousedown → mouseup → click 序列(包括任何 JavaScript 處理程序)後解析。無需輪詢 — 後續的 evaluate() 可以看到結果。

通過選擇器點選

傳入 CSS 選擇器而不是座標,Bun 會等待元素變為可操作,然後點選其中心:

TypeScript
await view.click("#submit");
await view.click("button.primary", { timeout: 5000 });

當元素滿足以下條件時,它才是可操作的:

  • 存在於 DOM 中
  • 擁有非零的邊界框
  • 位於視口內
  • 已保持穩定(在連續兩幀動畫中邊界框未改變)
  • 在其中心點處是最上層元素(沒有被覆蓋物遮擋)

該檢查會在頁面側以 requestAnimationFrame 的頻率執行。如果該元素在 timeout 毫秒內始終未變為可操作(預設 30000),promise 會以類似 timeout waiting for '#submit' to be actionable 的錯誤拒絕。

Bun 會將選擇器作為資料傳遞,而不是將其插入指令碼中,因此包含引號或 JavaScript 語法的選擇器也是安全的。

輸入文本

把文本插入到當前聚焦的元素中:

TypeScript
await view.click("input#email"); // 先聚焦
await view.type("hello@example.com");

type() 使用瀏覽器的 InsertText 編輯命令(與貼上使用同一路徑),而不是逐字元的按鍵模擬。它會觸發帶 isTrusted: true 的 beforeinput/input 事件,但不會觸發 keydown/keyup 事件。不會進行 IME 處理,也不會進行智慧引號替換 — 文本會被按原樣精確寫入。

按下按鍵

TypeScript
await view.press("Enter");
await view.press("Escape");
await view.press("ArrowDown");
await view.press("a", { modifiers: ["Meta"] }); // Cmd+A / Ctrl+A

命名的虛擬按鍵:Enter、Tab、Space、Backspace、Delete、Escape、ArrowLeft、ArrowRight、ArrowUp、ArrowDown、Home、End、PageUp、PageDown。

任意單個字元(例如 "a")與 modifiers 組合使用時,會發送鍵盤組合鍵。

在 WebKit 後端上,大多數命名按鍵(不帶修飾鍵)會對映到 DeleteBackward、MoveLeft 和 InsertNewline 等編輯命令,並在頁面應用這些命令後解析。Escape、Space 和帶有修飾鍵的任何按鍵都會回退到原始的 keydown/keyup 事件。這些按鍵會觸發頁面可觀察到的 keydown,但沒有完成屏障。如果需要觀察結果,請接著呼叫 evaluate()。

修飾鍵名稱:"Shift"、"Control"(或 "Ctrl")、"Alt"(或 "Option")、"Meta"(或 "Cmd" / "Command")。

滾動

按畫素增量滾動 — 在視口中心觸發一個原生 wheel 事件:

TypeScript
await view.scroll(0, 500); // 向下滾動 500px
await view.scroll(-100, 0); // 向左滾動 100px

正的 dy 會向下滾動(內容向上移動),與 window.scrollBy 一致。如果視口中心下方有可滾動元素,它會接收到 wheel 事件,而不是整個文件。

通過選擇器把元素滾入視野:

TypeScript
await view.scrollTo("#footer"); // 居中顯示(預設)
await view.scrollTo("#hero", { block: "start" }); // 讓元素頂部對齊視口頂部
await view.scrollTo(".card", { block: "nearest" }); // 最小滾動

scrollTo() 會以 requestAnimationFrame 的頻率等待元素存在,然後呼叫 element.scrollIntoView({ block, behavior: "instant" })。它會滾動所有可滾動祖先,而不僅僅是文件。預設 timeout 為 30000 ms。

調整大小

TypeScript
await view.resize(1920, 1080);

寬度和高度分別必須在 1 到 16384 之間。


控制台捕獲

通過在建構函式中傳入 console 選項,把頁面側的 console.* 呼叫轉發到你的 Bun 行程。

映象到 Bun 的控制台

傳入 globalThis.console(實際物件,按引用傳遞)。頁面側的 console.log("hi") 會使用 Bun 的格式化程式將 hi 列印到 stdout,console.error 則會輸出到 stderr。此路徑通過 Bun 的控制台實現直接分發,不會產生每次呼叫都要承擔的 JavaScript 開銷。

TypeScript
const view = new Bun.WebView({
  console: globalThis.console,
});

自定義處理器

傳入一個函式來接收每次呼叫:

TypeScript
const view = new Bun.WebView({
  console: (type, ...args) => {
    // type 是 "log" | "warn" | "error" | "info" | "debug" | ...
    if (type === "error") reportError(args);
  },
});

原始引數(字串、數字、布林值、null、undefined)會解包為它們的原始值。物件引數會以序列化描述符的形式到達:

  • Chrome 後端:原始的 CDP RemoteObject — 一個包含 type、className、description,以及(在可用時)preview.properties 陣列的物件。
  • WebKit 後端:物件經過 JSON.stringify 往返後的結果。函式、迴圈引用以及其他不可序列化值會回退為 String(...) 的強制轉換。

如果你沒有傳入 console,Bun 會丟棄頁面側的控制台輸出。


原始 Chrome DevTools Protocol

當使用 backend: "chrome" 時,如果高層 API 沒有覆蓋你想要的能力,你可以直接切換到原始的 CDP 命令。

傳送命令

TypeScript
const view = new Bun.WebView({ backend: "chrome" });
await view.navigate("https://example.com"); // 必需:設定 CDP 會話

await view.cdp("Emulation.setUserAgentOverride", {
  userAgent: "MyBot/1.0",
});

const { root } = await view.cdp("DOM.getDocument");
const { nodeId } = await view.cdp("DOM.querySelector", {
  nodeId: root.nodeId,
  selector: "input[name=q]",
});
await view.cdp("DOM.focus", { nodeId });

cdp(method, params?) 會傳回 CDP 響應中的 result 物件。如果 Chrome 傳回錯誤(未知方法、引數錯誤),該 promise 會以 error.message 拒絕。

命令會被限定在此檢視的會話範圍內(目標是此標籤頁)。在呼叫 cdp() 之前至少要 await navigate(...) 一次 — 第一次導航會建立會話。若在那之前呼叫 cdp() 會丟擲 ERR_INVALID_STATE。

params 必須是可 JSON 序列化的物件;對於不帶引數的命令可省略。每個檢視同一時刻最多隻能有一個 cdp() 呼叫正在進行。

訂閱事件

Bun.WebView 擴充套件了 EventTarget。使用 Chrome 後端時,檢視會將 CDP 事件作為 DOM 事件分發,其 type 為 CDP 方法名稱,data 為解析後的 params 物件:

TypeScript
await view.navigate("about:blank");
await view.cdp("Network.enable"); // 僅 Chrome:只有啟用了域才會發出事件

view.addEventListener("Network.responseReceived", event => {
  console.log(event.data.response.status, event.data.response.url);
});

await view.navigate("https://example.com");

對於沒有註冊監聽器的事件,Bun 會在解析其 JSON params 之前就將其丟棄,因此如果你只監聽一兩種事件型別,啟用像 Network 這樣的高頻事件域也不會造成開銷。

在 WebKit 後端上,cdp() 會丟擲 ERR_METHOD_NOT_IMPLEMENTED — 沒有 DevTools Protocol 的橋接。EventTarget 介面仍然可用於你自己對 dispatchEvent() 的呼叫。


生命週期

關閉檢視

TypeScript
view.close();

關閉操作是同步且冪等的。它會銷燬頁面的渲染器行程,以 Error("WebView closed") 拒絕該檢視上所有待處理的 promise,並使之後的每次方法呼叫都丟擲 ERR_INVALID_STATE。這些拒絕會被標記為已處理:你持有的 promise 仍可以捕獲到拒絕,但沒有被任何物件持有的待處理操作不會觸發 unhandledRejection。

view[Symbol.dispose] 和 view[Symbol.asyncDispose] 都指向 close(),所以 using / await using 可以正常工作。

殺死所有瀏覽器

TypeScript
Bun.WebView.closeAll();

強制終止(SIGKILL)所有瀏覽器子行程(包括 Chrome 子行程和 WebKit 宿主子行程)。每個檢視上的待處理 promise 會在下一次事件迴圈 tick 時拒絕。之後的 new Bun.WebView() 呼叫會在需要時重新生成。

Bun 會在行程退出時自動呼叫它,因此瀏覽器子行程不會在你的指令碼之外存活。

事件迴圈行為

瀏覽器子行程本身不會讓 Bun 的事件迴圈保持執行。開啟的 WebView 僅會在存在待處理操作(例如尚未完成的 navigate() 或 evaluate())時讓行程保持執行。一旦你關閉最後一個檢視,或最後一個待處理操作完成,Bun 就會自然退出。

子行程死亡

如果瀏覽器子行程意外死亡(崩潰、被 OOM-kill、SIGKILL),每個檢視上所有待處理的 promise 都會以描述其死亡原因的錯誤拒絕("Chrome killed by signal 9"、"WebView host process died")。對這些檢視進行後續操作會丟擲異常。


並行模型

每個檢視都有少量用於並行的獨立“操作槽位”。同一種操作在任一時刻最多隻有一個在執行:

  • 一個 navigate()(在 Chrome 後端與 reload()/goBack()/goForward() 共享)
  • 一個 evaluate()
  • 一個 screenshot()
  • 一個 cdp()(僅 Chrome)
  • 一個“簡單”操作 — click()、type()、press()、scroll()、scrollTo()、resize()(以及 WebKit 後端的 reload()/goBack()/goForward())共享此槽位

在操作槽位被佔用時啟動第二個操作會同步丟擲 ERR_INVALID_STATE — 它不會排隊。實際上,請對每次呼叫使用 await。

不同檢視之間的操作完全獨立,並會並行執行 — 每個檢視都有自己的渲染器行程。


參考

new Bun.WebView(options?)

選項型別預設值描述
widthnumber800視口寬度(CSS 畫素)。範圍 1-16384。
heightnumber600視口高度(CSS 畫素)。範圍 1-16384。
urlstring—立即開始導航到該 URL。
headlessbooleantrue僅實現 true;false 會丟擲異常。
backend"webkit" | "chrome" | objectmacOS 為 "webkit",其他為 "chrome"渲染引擎。
consoletypeof console | (type, ...args) => void—捕獲頁面側的 console.* 呼叫。見 控制台捕獲。
dataStore"ephemeral" | { directory: string }"ephemeral"cookies / localStorage / IndexedDB 的儲存。見 持久化儲存。

backend 物件形式

選項型別描述
type"chrome" | "webkit"必填。 使用哪個引擎。
pathstring(僅限 chrome)Chrome/Chromium 執行檔的路徑。強制進入生成模式。
argvstring[](僅限 chrome)額外的啟動引數,會在預設引數之後追加。強制進入生成模式。
urlstring | false(僅限 chrome)現有 Chrome 的 DevTools 端點 ws:// URL;或傳 false 跳過自動探測並始終生成。見上文。
stdout"inherit" | "ignore"把子行程的 stdout 轉發到 Bun。預設 "ignore"。
stderr"inherit" | "ignore"把子行程的 stderr 轉發到 Bun。預設 "ignore"。

例項屬性

屬性型別描述
urlstring (readonly)當前 URL。導航完成後更新。首次導航前為空字串。
titlestring (readonly)頁面 <title>。導航完成後更新。
loadingboolean (readonly)當正在進行導航時為 true。
onNavigated((url: string, title: string) => void) | null每次成功導航後觸發:在 navigate() promise 解析前觸發。
onNavigationFailed((error: Error) => void) | null每次失敗導航後觸發:在 navigate() promise 拒絕前觸發。

例項方法

方法傳回值描述
navigate(url)Promise<void>載入 URL。在主框架的 load 事件觸發時解析。
evaluate(script)Promise<unknown>在頁面中執行 JS 表示式,並傳回其經過 JSON 序列化的結果。
screenshot(options?)Promise<Blob | Buffer | string | {name, size}>擷取視口。參見螢幕截圖。
click(x, y, options?)Promise<void>在視口座標處執行原生點選。
click(selector, options?)Promise<void>等待元素可操作,然後點選其中心。
type(text)Promise<void>使用 InsertText 編輯命令將文本插入聚焦的元素。
press(key, options?)Promise<void>按下命名的虛擬按鍵或單字元組合鍵。
scroll(dx, dy)Promise<void>在視口中心觸發原生 wheel 事件。dx/dy 必須是有限值。
scrollTo(selector, options?)Promise<void>等待元素存在,然後執行 scrollIntoView。
resize(width, height)Promise<void>更改視口大小。每個維度的範圍為 1-16384。
goBack()Promise<void>在會話歷史記錄中後退。在起始位置時不執行任何操作。
goForward()Promise<void>在會話歷史記錄中前進。在末尾時不執行任何操作。
reload()Promise<void>重新載入當前頁面。
cdp(method, params?)Promise<unknown>(僅限 Chrome)向此標籤頁傳送原始 CDP 命令。參見原始 CDP。
addEventListener(type, fn)void繼承自 EventTarget。使用 Chrome 時,type 可以是 CDP 事件名稱;event.data 是經過解析的 params。
close()void銷燬頁面。拒絕待處理的 promise。冪等。

click() 選項

選項型別預設值描述
button"left" | "right" | "middle""left"滑鼠按鍵。
modifiers("Shift" | "Control" | "Alt" | "Meta")[][]點選時按住的修飾鍵。
clickCount1 | 2 | 31雙擊/三擊的點選次數。
timeoutnumber30000(僅選擇器過載)等待可操作性的最長毫秒數。

press() 選項

選項型別預設值描述
modifiers("Shift" | "Control" | "Alt" | "Meta")[][]按下按鍵時按住的修飾鍵。

scrollTo() 選項

選項型別預設值描述
block"start" | "center" | "end" | "nearest""center"滾動後的垂直對齊方式。
timeoutnumber30000等待元素存在的最長毫秒數。

screenshot() 選項

選項型別預設值描述
format"png" | "jpeg" | "webp""png"圖片格式。"webp" 需要 Chrome 後端。
qualitynumber800-100。僅 JPEG/WebP;PNG 會忽略。
encoding"blob" | "buffer" | "base64" | "shmem""blob"傳回型別編碼。Windows 不支援 "shmem"。

靜態方法

方法描述
WebView.closeAll()SIGKILL 每個瀏覽器子行程。下一 tick 上拒絕所有待處理 promise。退出時自動呼叫。