import fs from 'node:fs'; import path from 'node:path'; import http from 'node:http'; import { fileURLToPath } from 'node:url'; import express from 'express'; import puppeteer from 'puppeteer'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const ROOT = path.resolve(__dirname, '..'); const DIST = path.join(ROOT, 'dist'); const routes = JSON.parse(fs.readFileSync(path.join(DIST, 'routes.json'), 'utf8')); const app = express(); app.use(express.static(DIST)); app.get('*', (_req, res) => res.sendFile(path.join(DIST, 'index.html'))); const server = http.createServer(app); async function start() { await new Promise((resolve) => server.listen(0, resolve)); const port = server.address().port; const baseUrl = `http://127.0.0.1:${port}`; const launchOpts = { headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }; if (process.env.PUPPETEER_EXECUTABLE_PATH) { launchOpts.executablePath = process.env.PUPPETEER_EXECUTABLE_PATH; } const browser = await puppeteer.launch(launchOpts); for (const route of routes) { const page = await browser.newPage(); const url = `${baseUrl}${route}`; try { await page.goto(url, { waitUntil: 'networkidle0', timeout: 15000 }); } catch (e) { console.warn(`prerender warn ${route}: ${e.message}`); } const html = await page.content(); const outDir = path.join(DIST, route); fs.mkdirSync(outDir, { recursive: true }); fs.writeFileSync(path.join(outDir, 'index.html'), html); console.log(`prerender: ${route}`); await page.close(); } await browser.close(); server.close(); } start().catch((e) => { console.error(e); process.exit(1); });