就 3 行:
bash
await using view = new Bun.WebView();
await view.navigate("https://example.com");
await Bun.write("out.png", await view.screenshot());
bash
bun run demo.ts
完事儿。
痛点:装 Puppeteer 太烦
想截个网页图。
npm i puppeteer。
300MB Chromium 下起来。
Linux 还得装 libatk``libnss3 一堆系统包。
折腾半小时,截图没拿到。
Bun.WebView 就是来治这个的。
Bun v1.3.12 内置,啥都不用装。
简单在哪
macOS: 用系统 WKWebView,零配置。
Linux/Windows: 自动找本地 Chrome / Edge / Chromium。
事件是原生的。
view.click()、view.type() 派发的是操作系统级事件。
isTrusted 一定为 true。
网站识别不出你是机器人。
装一下 Bun
需要 v1.3.12 以上:
bash
curl -fsSL https://bun.sh/install | bash
bun --version
完事儿后 bun run demo.ts 就能跑。
再多 3 行:拿页面数据
bash
const view = new Bun.WebView();
await view.navigate("https://example.com");
const title = await view.evaluate("document.title");
console.log(title);
evaluate 在页面里跑 JS。
直接返回 JSON 可序列化的值。
Promise 自动 await。
bash
// 跑个 fetch
const data = await view.evaluate(`
fetch("/api/list").then(r => r.json())
`);
模拟真人操作
bash
await view.click("input[name='q']");
await view.type("Bun WebView 真香");
await view.press("Enter");
click 会自动等。
等元素挂载、可见、稳定、不被遮挡。
type 是真键盘事件。
不是直接改 input.value。
Vue、React 监听器照样能触发。
bash
// 双击 + Shift
await view.click("a.link", {
button: "left",
count: 2,
modifiers: ["Shift"],
timeout: 5000,
});
滚动、改窗口也都简单:
bash
await view.scroll(0, 600); // 向下滚 600 像素
await view.resize(1920, 1080); // 改窗口大小
截图的几种姿势
全页截图:
bash
await Bun.write("full.png",
await view.screenshot({ format: "png", fullPage: true })
);
指定元素:
bash
const header = await view.screenshot({
format: "jpeg",
quality: 85,
selector: "header.banner",
});
await Bun.write("header.jpg", header);
支持 png、jpeg、webp。
WebP 通常比 PNG 小 30% 以上。
返回的是 Buffer。
塞进任何地方都行。
后端手动指定
不靠默认查找的话:
bash
const view = new Bun.WebView({
backend: {
type: "chrome",
path: "/usr/bin/google-chrome",
},
});
调试时连已有 Chrome 更省事:
bash
chrome --remote-debugging-port=9222
bash
const view = new Bun.WebView({
backend: {
type: "chrome",
url: "ws://127.0.0.1:9222/devtools/browser/xxx",
},
});
启动一次 Chrome,后台挂着。
不必每次跑都新开。
实战:抓一批文章标题
bash
// crawl.ts
const urls = [
"https://bun.sh/blog",
"https://bun.sh/docs",
"https://bun.sh/docs/cli/run",
];
await using view = new Bun.WebView();
for (const url of urls) {
await view.navigate(url);
const title = await view.evaluate(
`document.querySelector("h1")?.textContent || document.title`
);
console.log(`${url} -> ${title}`);
}
每个 view 共享一个浏览器子进程。
开多个 view 等于开多个标签页。
比 Puppeteer 启动快多了。
想保存登录态
dataStore 一行就够:
bash
const view = new Bun.WebView({
dataStore: { directory: "./browser-profile" },
});
cookies、localStorage 都存盘。
登录一次,下次直接用。
抓页面日志
前端报错想看?
bash
const view = new Bun.WebView({
console: (type, ...args) => {
console.log(`[页面 ${type}]`, ...args);
},
});
console.log、console.error 全部捕获。
比开 DevTools 还方便。
需要 CDP 原生命令也行
bash
// 发命令
const result = await view.cdp("Page.getLayoutMetrics");
console.log(result);
// 订阅事件
const off = view.cdpSubscribe("Network.requestWillBeSent", (params) => {
console.log("请求 URL:", params.request.url);
});
await view.navigate("https://example.com");
off(); // 取消订阅
网络拦截、性能监控、Cookie 操控这些,CDP 能干的全能干。
注意事项
Bun.WebView 还在实验阶段。
API 以后可能变。
用前确认 Bun ≥ 1.3.12。
Linux 上要装 Chrome:
bash
sudo apt install google-chrome-stable
macOS 自带 WebKit,零配置。
还有个坑:
每次跑完会留临时目录。
Linux 在 /tmp/bun-chrome-xxx。
用 await using 自动释放。
否则磁盘可能爆掉。
总结一下
Bun.WebView 就干了这一件事:
让截图和浏览器自动化变简单。
-
• 3 行代码截图
-
• macOS 零配置
-
• 原生事件,反爬不了
-
• 跟 Playwright 像的 API
Puppeteer、Playwright 不是不能装。
但能少装就少装,能少配就少配。
用 Bun.WebView 就图个省事儿。
觉得有用?点个在看、转发。
评论区聊聊,你拿 Bun.WebView 干了啥?
下篇写Bun.S3 全家桶。
下篇见。 👋
