import express from 'express' import fs from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import { ViteDevServer } from 'vite' const __dirname = path.dirname(fileURLToPath(import.meta.url)) const isTest = process.env.VITEST process.env.MY_CUSTOM_SECRET = 'API_KEY_qwertyuiop' export async function createServer(root: string = process.cwd(), isProd: boolean = process.env.NODE_ENV === 'production', hmrPort?: number) { console.log(`isProd: ${isProd}`) const resolve = (p: string) => path.resolve(__dirname, p) const indexProd = isProd ? fs.readFileSync(resolve('dist/client/index.html'), 'utf-8') : '' const app = express() /** * @type {import('vite').ViteDevServer} */ let vite: ViteDevServer if (!isProd) { vite = await (await import('vite')).createServer({ root, logLevel: isTest ? 'error' : 'info', server: { middlewareMode: true, watch: { // During tests we edit the files too fast and sometimes chokidar // misses change events, so enforce polling for consistency usePolling: true, interval: 100, }, hmr: { port: hmrPort, }, }, appType: 'custom', }) // use vite's connect instance as middleware app.use(vite.middlewares) } else { app.use((await import('compression')).default()) app.use( (await import('serve-static')).default(resolve('dist/client'), { index: false, }), ) } app.use('*', async (req, res) => { try { const url = req.originalUrl let template: string, render: any if (!isProd) { // always read fresh template in dev template = fs.readFileSync(resolve('index.html'), 'utf-8') template = await vite.transformIndexHtml(url, template) render = (await vite.ssrLoadModule('/src/entry-server.tsx')).render } else { template = indexProd // @ts-ignore render = (await import('./dist/server/entry-server.js')).render } const context: any = {} const appHtml: any = render(url, context) if (context.url) { // Somewhere a `` was rendered return res.redirect(301, context.url) } const html = template.replace(``, appHtml) res.status(200).set({ 'Content-Type': 'text/html' }).end(html) } catch (e: any) { !isProd && vite.ssrFixStacktrace(e) console.log(e.stack) res.status(500).end(e.stack) } }) // @ts-ignore return { app, vite } } if (!isTest) { createServer().then(({ app }) => app.listen(5173, () => { console.log('http://localhost:5173') }), ) }