UNPKG

vite-ssr

Version:

Vite utility for server side rendering

187 lines (186 loc) 7.67 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.printServerInfo = exports.createSsrServer = exports.createSSRDevHandler = void 0; const fs_1 = require("fs"); const path_1 = __importDefault(require("path")); const perf_hooks_1 = require("perf_hooks"); const vite_1 = require("vite"); const chalk_1 = __importDefault(require("chalk")); const config_1 = require("../config"); // This cannot be imported from utils due to ESM <> CJS issues const isRedirect = ({ status = 0 } = {}) => status >= 300 && status < 400; const createSSRDevHandler = (server, options = {}) => { // Fix, because newer versions of vite's inlineConfig contains "ssr" property which type is object let { ssr, ...otherOptions } = server.config.inlineConfig; if (typeof ssr != 'string') { ssr = undefined; } options = { ...{ ssr, ...otherOptions }, ...options, }; const pluginOptions = (0, config_1.getPluginOptions)(server.config); const resolve = (p) => path_1.default.resolve(server.config.root, p); async function getIndexTemplate(url) { // Template should be fresh in every request const indexHtml = await fs_1.promises.readFile(pluginOptions.input || resolve('index.html'), 'utf-8'); return await server.transformIndexHtml(url, indexHtml); } function writeHead(response, params = {}) { if (params.status) { response.statusCode = params.status; } if (params.statusText) { response.statusMessage = params.statusText; } if (params.headers) { for (const [key, value] of Object.entries(params.headers)) { response.setHeader(key, value); } } } const handleSsrRequest = async (request, response, next) => { if (request.method !== 'GET' || request.originalUrl === '/favicon.ico') { return next(); } let template; try { template = await getIndexTemplate(request.originalUrl); } catch (error) { server.ssrFixStacktrace(error); return next(error); } try { const entryPoint = options.ssr || (await (0, config_1.getEntryPoint)(server.config, template)); let resolvedEntryPoint = await server.ssrLoadModule(resolve(entryPoint)); resolvedEntryPoint = resolvedEntryPoint.default || resolvedEntryPoint; const render = resolvedEntryPoint.render || resolvedEntryPoint; const protocol = // @ts-ignore request.protocol || (request.headers.referer || '').split(':')[0] || 'http'; const url = protocol + '://' + request.headers.host + request.originalUrl; // This context might contain initialState provided by other plugins const context = (options.getRenderContext && (await options.getRenderContext({ url, request, response, resolvedEntryPoint, }))) || {}; // This is used by Vitedge writeHead(response, context); if (isRedirect(context)) { return response.end(); } const result = await render(url, { request, response, template, ...context, }); writeHead(response, result); if (isRedirect(result)) { return response.end(); } response.setHeader('Content-Type', 'text/html'); response.end(result.html); } catch (error) { // Send back template HTML to inject ViteErrorOverlay response.setHeader('Content-Type', 'text/html'); response.end(template); // Wait until browser injects ViteErrorOverlay // custom element from the previous template setTimeout(() => next(error), 250); server.ssrFixStacktrace(error); } }; return handleSsrRequest; }; exports.createSSRDevHandler = createSSRDevHandler; async function createSsrServer({ force, ...options } = {}) { var _a, _b; // Enable SSR in the plugin process.env.__DEV_MODE_SSR = 'true'; if (force) { (_a = options.optimizeDeps) !== null && _a !== void 0 ? _a : (options.optimizeDeps = {}); options.optimizeDeps.force = force; } const viteServer = await (0, vite_1.createServer)({ ...options, server: options.server || { ...options }, }); if (options.polyfills !== false) { if (!globalThis.fetch) { const fetch = await Promise.resolve().then(() => __importStar(require('node-fetch'))); // @ts-ignore globalThis.fetch = fetch.default || fetch; } } const isMiddlewareMode = // @ts-ignore (options === null || options === void 0 ? void 0 : options.middlewareMode) || ((_b = options === null || options === void 0 ? void 0 : options.server) === null || _b === void 0 ? void 0 : _b.middlewareMode); return new Proxy(viteServer, { get(target, prop, receiver) { if (prop === 'listen') { return async (port) => { const server = await target.listen(port); if (!isMiddlewareMode) { printServerInfo(server); } return server; }; } return Reflect.get(target, prop, receiver); }, }); } exports.createSsrServer = createSsrServer; function printServerInfo(server) { const info = server.config.logger.info; let ssrReadyMessage = '\n -- SSR mode'; if (Object.prototype.hasOwnProperty.call(server, 'printUrls')) { info(chalk_1.default.cyan(`\n vite v${require('vite/package.json').version}`) + chalk_1.default.green(` dev server running at:\n`), { clear: !server.config.logger.hasWarned }); // @ts-ignore server.printUrls(); // @ts-ignore if (globalThis.__ssr_start_time) { ssrReadyMessage += chalk_1.default.cyan(` ready in ${Math.round( // @ts-ignore perf_hooks_1.performance.now() - globalThis.__ssr_start_time)}ms.`); } } info(ssrReadyMessage + '\n'); } exports.printServerInfo = printServerInfo;