triston-notes/Cards/dev/Create SSR Vite Preact App.md
2023-10-21 18:52:54 -05:00

2.6 KiB

up:: TypeScript X:: JavaScript tags::

Create SSR Vite Preact App

Initialization

To create the scaffolding of a preact vite ssr app you run the command:

npm create vite@latest

Which will start the CLI process.

You will be asked to choose a boilerplate startup, you should go to "other". This will prompt you to install an "extras" package; select yes. Choose the srr project for Preact

Server file

In the server file we have some setup to do

Constants

const isProduction = process.env.NODE_ENV === 'production'
const port = process.env.PORT || 5173
const base = process.env.BASE || '/'

Cached production assets

const templateHtml = isProduction ? await fs.readFile('./dist/client/index.html', 'utf-8') : ''
const ssrManifest = isProduction ? await fs.readFile('./dist/client/ssr-manifest.json', 'utf-8') : undefined

Create HTTP Server

const app = express()

Add vite or respective production middlewares

 let vite
 if (!isProduction) {
	const { createServer } = await import('vite')
    vite = await createServer({
         server: { middlewareMode: true },
         appType: 'custom',
         base
       })
    app.use(vite.middlewares)
} else {
	const compression = (await import('compression')).default
	const sirv = (await import('sirv')).default
	app.use(compression())
	app.use(base, sirv('./dist/client', { extensions: [] }))
}

Serve HTML

app.use('*', async (req, res) => {
	try {
	    const url = req.originalUrl.replace(base, '')
  
	    let template
	    let render
        if (!isProduction) {
			  // Always read fresh template in development
			  template = await fs.readFile('./index.html', 'utf-8')
			  template = await vite.transformIndexHtml(url, template)
			  render = (await vite.ssrLoadModule('/src/entry-server.tsx')).render
        } else {
	          template = templateHtml
	          render = (await import('./dist/server/entry-server.js')).render
        }
   
         const rendered = await render(url, ssrManifest)
   
         const html = template
           .replace(`<!--app-head-->`, rendered.head ?? '')
           .replace(`<!--app-html-->`, rendered.html ?? '')
   
         res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
       } catch (e) {
	        vite?.ssrFixStacktrace(e)
	         console.log(e.stack)
	         res.status(500).end(e.stack)
       }
     })

Start HTTP Server

 app.listen(port, () => {
    console.log(`Server started at http://localhost:${port}`)
})

Add API support

Add api support to vite ssr app