diff --git a/scripts/prerender.mjs b/scripts/prerender.mjs index 492360d9..c3a88ecf 100644 --- a/scripts/prerender.mjs +++ b/scripts/prerender.mjs @@ -80,16 +80,47 @@ const routes = [ { path: '/login', file: 'login/index.html' }, ]; +function hasMissingBrowserRuntime(error) { + const message = String(error?.message || error || ''); + const normalized = message.toLowerCase(); + return ( + normalized.includes('failed to launch the browser process') && + (normalized.includes('error loading shared library') || + normalized.includes('error while loading shared libraries') || + normalized.includes('cannot open shared object file') || + normalized.includes('symbol not found')) + ); +} + async function prerender() { + if (process.env.SKIP_PRERENDER === '1') { + console.log('SKIP_PRERENDER=1, skipping prerender step.'); + return; + } + console.log('Starting prerender server...'); await new Promise((resolve) => server.listen(port, resolve)); console.log(`Server running at http://localhost:${port}`); - const browser = await puppeteer.launch({ - headless: 'new', - args: ['--no-sandbox', '--disable-setuid-sandbox'], - }); + const strictPrerender = process.env.PRERENDER_STRICT === '1'; + let browser; + + try { + browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox', '--disable-setuid-sandbox'], + }); + } catch (error) { + server.close(); + if (!strictPrerender && hasMissingBrowserRuntime(error)) { + console.warn('\nSkipping prerender: browser runtime dependencies are unavailable in this build environment.'); + console.warn('Install required Chromium/Puppeteer system libraries (for example, libnss3/libatk/libx11) to enable prerendering.'); + console.warn('Set PRERENDER_STRICT=1 to fail the build instead.'); + return; + } + throw error; + } try { for (const route of routes) { @@ -148,4 +179,3 @@ prerender().catch((err) => { server.close(); process.exit(1); }); -