import fs from 'fs';
import path from 'path';
const args = process.argv.slice(2);
if (args.length < 2) {
console.log(`
Preact SSR Bundle Builder
Usage:
node examples/build-preact-bundle.js <input> <output>
Arguments:
input Path to Vite SSR build output (IIFE format)
output Output path for Rusty SSR bundle
Example:
node examples/build-preact-bundle.js dist/server/entry.js ssr-bundle.js
`);
process.exit(1);
}
const inputPath = args[0];
const outputPath = args[1];
if (!fs.existsSync(inputPath)) {
console.error(`Error: Input file not found: ${inputPath}`);
process.exit(1);
}
const ssrCode = fs.readFileSync(inputPath, 'utf-8');
const wrappedBundle = `
// ============ Preact SSR Bundle ============
// Generated by: node examples/build-preact-bundle.js
// Source: ${inputPath}
// ============================================
${ssrCode}
// ============ Rusty SSR Integration ============
/**
* Global render function called by Rust V8 engine
*
* @param {string} url - URL path to render
* @param {object|string} data - Data from Rust (JSON)
* @returns {string} Complete HTML document
*/
globalThis.renderPage = async function(url, data) {
try {
// Parse data if string
const props = typeof data === 'string' ? JSON.parse(data) : (data || {});
// Build context for Preact SSR
const context = {
url: url,
data: props,
headers: {},
userAgent: 'Rusty-SSR/1.0',
};
// Call your SSR render function
// Assumes SSRBundle.renderToString returns { html, head?, initialData? }
const result = await SSRBundle.renderToString(context);
// Build complete HTML document
// CUSTOMIZE THIS for your project!
const html = \`<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Preact App</title>
\${result.head || ''}
<!-- Add your CSS links here -->
</head>
<body>
<div id="app">\${result.html}</div>
<script>window.__INITIAL_DATA__ = \${JSON.stringify(result.initialData || props)}</script>
<!-- Add your client bundle here -->
</body>
</html>\`;
return html;
} catch (error) {
console.error('[Preact SSR] Error:', error);
// Return error page instead of crashing
return \`<!DOCTYPE html>
<html>
<head><title>SSR Error</title></head>
<body>
<h1>Server Render Error</h1>
<pre>\${error.stack || error.message}</pre>
</body>
</html>\`;
}
};
console.log('[Preact SSR] Bundle loaded and ready');
`;
const outputDir = path.dirname(outputPath);
if (outputDir && outputDir !== '.' && !fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
fs.writeFileSync(outputPath, wrappedBundle);
console.log(`
Preact SSR Bundle Created
Input: ${inputPath} (${(ssrCode.length / 1024).toFixed(2)} KB)
Output: ${outputPath} (${(wrappedBundle.length / 1024).toFixed(2)} KB)
Global: renderPage(url, data)
Next steps:
1. Customize the HTML template in the generated bundle
2. Add your CSS/JS asset paths
3. Start Rusty SSR: cargo run --example basic
`);