UNPKG

@benpsnyder/analogjs-esm-vite-plugin-nitro

Version:

A Vite plugin for adding a nitro API server

118 lines 4.67 kB
// SSR dev server, middleware and error page source modified from // https://github.com/solidjs/solid-start/blob/main/packages/start/dev/server.js import { normalizePath, } from 'vite'; import { resolve } from 'node:path'; import { readFileSync } from 'node:fs'; import { createEvent, sendWebResponse } from 'h3'; import { createRouter as createRadixRouter, toRouteMatcher } from 'radix3'; import { defu } from 'defu'; import { registerDevServerMiddleware } from '../utils/register-dev-middleware.js'; export function devServerPlugin(options) { const workspaceRoot = options?.workspaceRoot || process.cwd(); const sourceRoot = options?.sourceRoot ?? 'src'; const index = options.index || 'index.html'; let config; let root; let isTest = false; return { name: 'analogjs-dev-ssr-plugin', config(userConfig, { mode }) { config = userConfig; root = normalizePath(resolve(workspaceRoot, config.root || '.') || '.'); isTest = isTest ? isTest : mode === 'test'; return { resolve: { alias: { '~analog/entry-server': options.entryServer || `${root}/${sourceRoot}/main.server.ts`, }, }, }; }, configureServer(viteServer) { if (isTest) { return; } return async () => { remove_html_middlewares(viteServer.middlewares); registerDevServerMiddleware(root, sourceRoot, viteServer); viteServer.middlewares.use(async (req, res) => { let template = readFileSync(resolve(viteServer.config.root, index), 'utf-8'); template = await viteServer.transformIndexHtml(req.originalUrl, template); const _routeRulesMatcher = toRouteMatcher(createRadixRouter({ routes: options.routeRules })); const _getRouteRules = (path) => defu({}, ..._routeRulesMatcher.matchAll(path).reverse()); try { let result; // Check for route rules explicitly disabling SSR if (_getRouteRules(req.originalUrl).ssr === false) { result = template; } else { const entryServer = (await viteServer.ssrLoadModule('~analog/entry-server'))['default']; result = await entryServer(req.originalUrl, template, { req, res, }); } if (result instanceof Response) { sendWebResponse(createEvent(req, res), result); return; } res.setHeader('Content-Type', 'text/html'); res.end(result); } catch (e) { viteServer && viteServer.ssrFixStacktrace(e); res.statusCode = 500; res.end(` <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Error</title> <script type="module"> import { ErrorOverlay } from '/@vite/client' document.body.appendChild(new ErrorOverlay(${JSON.stringify(prepareError(req, e)).replace(/</g, '\\u003c')})) </script> </head> <body> </body> </html> `); } }); }; }, }; } /** * Removes Vite internal middleware * * @param server */ function remove_html_middlewares(server) { const html_middlewares = [ 'viteIndexHtmlMiddleware', 'vite404Middleware', 'viteSpaFallbackMiddleware', ]; for (let i = server.stack.length - 1; i > 0; i--) { // @ts-ignore if (html_middlewares.includes(server.stack[i].handle.name)) { server.stack.splice(i, 1); } } } /** * Formats error for SSR message in error overlay * @param req * @param error * @returns */ function prepareError(req, error) { const e = error; return { message: `An error occured while server rendering ${req.url}:\n\n\t${typeof e === 'string' ? e : e.message} `, stack: typeof e === 'string' ? '' : e.stack, }; } //# sourceMappingURL=dev-server-plugin.js.map