import React from 'react'; import { renderToString } from 'react-dom/server'; import type { Manifest } from 'vite'; import { logger } from '@crackle/core/logger'; import type { RenderAllPagesFn } from '../types'; import { createRouteMap, nodePageModules, Page } from './shared'; const getImportsFromManifest = (manifest: Manifest, pageName: string) => { const scriptImports = new Set(); const cssImports = new Set(); const getImportsForFilename = (fileName: string | undefined) => { if (!fileName) { throw new Error('Filename undefined'); } const manifestEntry = manifest[fileName]; for (const css of manifestEntry.css ?? []) { cssImports.add(css); } scriptImports.add(manifestEntry.file); for (const staticImport of manifestEntry.imports ?? []) { getImportsForFilename(staticImport); } }; const manifestChunks = Object.values(manifest); const entry = manifestChunks.find((chunk) => chunk.isEntry)!; getImportsForFilename(entry.src); if (!entry.dynamicImports) { throw new Error('No dynamic imports on entry'); } const pageImport = entry.dynamicImports.find((importFileName) => pageName.includes(importFileName), ); getImportsForFilename(pageImport); return { scriptImports, cssImports, entry: entry.file }; }; const generateScriptPreloadTags = ( scriptImports: Set, publicPath: string, ) => Array.from(scriptImports).map((scriptImport) => ( )); const generateCssTags = (cssImports: Set, publicPath: string) => Array.from(cssImports).map((css) => ( )); export const renderAllPages: RenderAllPagesFn = async ( manifest, publicPath, ) => { const totalPages = Object.keys(nodePageModules).length; const noun = totalPages === 1 ? 'page' : 'pages'; logger.start(`Rendering \`${totalPages} ${noun}\`...`); const pageModules = []; for (const [pageName, pageModule] of Object.entries(nodePageModules)) { const { route } = pageModule.routeData(); const { scriptImports, cssImports, entry } = getImportsFromManifest( manifest, pageName, ); const headTags = [ ...generateCssTags(cssImports, publicPath), ...generateScriptPreloadTags(scriptImports, publicPath), ]; const html = renderToString( } pageData={{ routeMap: createRouteMap() }} > {React.createElement(pageModule.default)} , ); pageModules.push({ route, html }); logger.log(` └─ [${pageModules.length}/${totalPages}] \`${route}\``); } return pageModules; };