@nuxthub/core
Version:
Build full-stack Nuxt applications on Cloudflare, with zero configuration.
96 lines (95 loc) • 2.87 kB
JavaScript
import cfPuppeteer, { PuppeteerWorkers } from "@cloudflare/puppeteer";
import { createError } from "h3";
import { useNitroApp, useEvent } from "#imports";
function getBrowserBinding(name = "BROWSER") {
return process.env[name] || globalThis.__env__?.[name] || globalThis[name];
}
let _browserPromise = null;
let _browser = null;
export async function hubBrowser(options = {}) {
const puppeteer = await getPuppeteer();
const nitroApp = useNitroApp();
const event = useEvent();
if (puppeteer instanceof PuppeteerWorkers) {
const binding = getBrowserBinding();
if (!binding) {
throw createError("Missing Cloudflare Browser binding (BROWSER)");
}
let browser = null;
const sessionId = await getRandomSession(puppeteer, binding);
if (sessionId) {
try {
browser = await puppeteer.connect(binding, sessionId);
} catch (e) {
}
}
if (!browser) {
browser = await puppeteer.launch(binding, {
// keep_alive is in milliseconds
// https://developers.cloudflare.com/browser-rendering/platform/puppeteer/#keep-alive
keep_alive: (options.keepAlive || 60) * 1e3
});
}
const page2 = await browser.newPage();
const unregister2 = nitroApp.hooks.hook("afterResponse", async (closingEvent) => {
if (event !== closingEvent) return;
unregister2();
await page2?.close().catch(() => {
});
browser?.disconnect();
});
return {
browser,
page: page2
};
}
if (!_browserPromise) {
_browserPromise = puppeteer.launch();
nitroApp.hooks.hook("close", async () => {
const browser = _browser || await _browserPromise;
browser?.close();
_browserPromise = null;
_browser = null;
});
}
if (!_browser) {
_browser = await _browserPromise;
_browser.disconnect = () => Promise.resolve();
}
const page = await _browser.newPage();
const unregister = nitroApp.hooks.hook("afterResponse", async (closingEvent) => {
if (event !== closingEvent) return;
unregister();
await page?.close().catch(() => {
});
});
return {
browser: _browser,
page
};
}
async function getRandomSession(puppeteer, binding) {
const sessions = await puppeteer.sessions(binding);
const sessionsIds = sessions.filter((v) => !v.connectionId).map((v) => v.sessionId);
if (!sessionsIds.length) {
return null;
}
return sessionsIds[Math.floor(Math.random() * sessionsIds.length)];
}
let _puppeteer;
async function getPuppeteer() {
if (_puppeteer) {
return _puppeteer;
}
if (import.meta.dev) {
const _pkg = "puppeteer";
_puppeteer = await import(_pkg).catch(() => {
throw new Error(
"Package `puppeteer` not found, please install it with: `npx nypm i puppeteer`"
);
});
} else {
_puppeteer = cfPuppeteer;
}
return _puppeteer;
}