← Browser Run / browser-run / features
Повторное использование сеансов
По умолчанию каждый запрос Browser Sessions запускает новый экземпляр браузера. Повторное использование сессий устраняет время холодного старта и повышает производительность за счёт подключения к уже существующему браузеру вместо запуска нового.
Эта функция применяется к Browser Sessions (Puppeteer, Playwright, а также CDP). Быстрые действия автоматически управляют жизненным циклом сессии.
Есть два подхода к повторному использованию сеансов:
- Отключение и повторное подключение (рассматривается на этой странице): используйте
browser.disconnect()вместоbrowser.close()чтобы браузер оставался активным, а затем повторно подключиться к нему при следующем запросе. Подходит для нагрузок без сохранения состояния, где годится любая доступная сессия браузера. - Durable Objects: сохраняйте долгоживущий браузер внутри Durable Object для управления состоянием сеанса. Это оптимально, когда нужно сохранять состояние между запросами или направлять определённых пользователей к определённым экземплярам браузера.
1. Создайте проект Worker
Cloudflare Workers предоставляет бессерверную среду выполнения, которая позволяет создавать новые приложения или дополнять существующие без настройки и обслуживания инфраструктуры. Ваше Worker-приложение служит контейнером для взаимодействия с headless-браузером и выполнения таких действий, как создание скриншотов.
Создайте новый проект Worker с именем browser-worker выполнив:
npm create cloudflare@latest -- browser-workerДля настройки выберите следующие параметры:
- Для С чего вы хотите начать?, выберите
Hello World example. - Для Какой шаблон вы хотите использовать?, выберите
Worker only. - Для Какой язык вы хотите использовать?, выберите
TypeScript. - Для Хотите использовать git для контроля версий?, выберите
Yes. - Для Хотите развернуть приложение?, выберите
No(мы внесём некоторые изменения перед развёртыванием).
2. Установка Puppeteer
В вашем browser-worker директории установите пакет Cloudflare форк Puppeteer:
npm i -D @cloudflare/puppeteer3. Настройка конфигурационный файл Wrangler
{
"$schema": "./node_modules/wrangler/config-schema.json",
"name": "browser-worker",
"main": "src/index.ts",
// Set this to today's date
"compatibility_date": "2026-08-28",
"compatibility_flags": ["nodejs_compat"],
"browser": {
"binding": "MYBROWSER",
},
}"$schema" = "./node_modules/wrangler/config-schema.json"
name = "browser-worker"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"
compatibility_flags = [ "nodejs_compat" ]
[browser]
binding = "MYBROWSER"4. Код
Приведённый ниже скрипт сначала получает список текущих активных сеансов. Если среди них есть сеансы без подключения от worker, скрипт выбирает случайный идентификатор сеанса и пытается подключиться (puppeteer.connect(..)) к нему. Если это не удаётся или изначально не было запущенных сеансов, запускается новый сеанс браузера (puppeteer.launch(..)). Затем он переходит на сайт и получает DOM. После этого он отключается (browser.disconnect()), делая соединение доступным для других Workers.
Учитывайте, что если браузер простаивает, то есть не получает никаких команд, дольше текущего лимит, она закроется автоматически, поэтому у вас должно быть достаточно запросов в минуту, чтобы поддерживать её активной.
import puppeteer from "@cloudflare/puppeteer";
export default {
async fetch(request, env) {
const url = new URL(request.url);
let reqUrl = url.searchParams.get("url") || "https://example.com";
reqUrl = new URL(reqUrl).toString(); // normalize
// Pick random session from open sessions
let sessionId = await this.getRandomSession(env.MYBROWSER);
let browser, launched;
if (sessionId) {
try {
browser = await puppeteer.connect(env.MYBROWSER, sessionId);
} catch (e) {
// another worker may have connected first
console.log(`Failed to connect to ${sessionId}. Error ${e}`);
}
}
if (!browser) {
// No open sessions, launch new session
browser = await puppeteer.launch(env.MYBROWSER);
launched = true;
}
sessionId = browser.sessionId(); // get current session id
// Do your work here
const page = await browser.newPage();
const response = await page.goto(reqUrl);
const html = await response.text();
// All work done, so free connection (IMPORTANT!)
browser.disconnect();
return new Response(
`${launched ? "Launched" : "Connected to"} ${sessionId} \n-----\n` + html,
{
headers: {
"content-type": "text/plain",
},
},
);
},
// Pick random free session
// Other custom logic could be used instead
async getRandomSession(endpoint) {
const sessions = await puppeteer.sessions(endpoint);
console.log(`Sessions: ${JSON.stringify(sessions)}`);
const sessionsIds = sessions
.filter((v) => {
return !v.connectionId; // remove sessions with workers connected to them
})
.map((v) => {
return v.sessionId;
});
if (sessionsIds.length === 0) {
return;
}
const sessionId =
sessionsIds[Math.floor(Math.random() * sessionsIds.length)];
return sessionId;
},
};import puppeteer from "@cloudflare/puppeteer";
interface Env {
MYBROWSER: Fetcher;
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
let reqUrl = url.searchParams.get("url") || "https://example.com";
reqUrl = new URL(reqUrl).toString(); // normalize
// Pick random session from open sessions
let sessionId = await this.getRandomSession(env.MYBROWSER);
let browser, launched;
if (sessionId) {
try {
browser = await puppeteer.connect(env.MYBROWSER, sessionId);
} catch (e) {
// another worker may have connected first
console.log(`Failed to connect to ${sessionId}. Error ${e}`);
}
}
if (!browser) {
// No open sessions, launch new session
browser = await puppeteer.launch(env.MYBROWSER);
launched = true;
}
sessionId = browser.sessionId(); // get current session id
// Do your work here
const page = await browser.newPage();
const response = await page.goto(reqUrl);
const html = await response!.text();
// All work done, so free connection (IMPORTANT!)
browser.disconnect();
return new Response(
`${launched ? "Launched" : "Connected to"} ${sessionId} \n-----\n` + html,
{
headers: {
"content-type": "text/plain",
},
},
);
},
// Pick random free session
// Other custom logic could be used instead
async getRandomSession(endpoint: puppeteer.BrowserWorker): Promise<string> {
const sessions: puppeteer.ActiveSession[] =
await puppeteer.sessions(endpoint);
console.log(`Sessions: ${JSON.stringify(sessions)}`);
const sessionsIds = sessions
.filter((v) => {
return !v.connectionId; // remove sessions with workers connected to them
})
.map((v) => {
return v.sessionId;
});
if (sessionsIds.length === 0) {
return;
}
const sessionId =
sessionsIds[Math.floor(Math.random() * sessionsIds.length)];
return sessionId!;
},
};Помимо puppeteer.sessions(), мы добавили другие методы, упрощающие Управление сессиями.
5. Тестирование
Запустите npx wrangler dev чтобы протестировать Worker локально.
Для тестирования перейдите по следующему URL-адресу:
<LOCAL_HOST_URL>/?url=https://example.com6. Разверните
Запустите npx wrangler deploy чтобы развернуть Worker в глобальной сети Cloudflare, а затем перейдите по следующему URL-адресу:
<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev/?url=https://example.com