UNPKG

vite-plugin-react-server

Version:
110 lines (108 loc) 2.69 kB
import * as React from "react"; // @ts-ignore import { renderToPipeableStream } from "react-server-dom-esm/server.node"; import type { PipeableStreamOptions } from "../worker/types.js"; import type { Logger } from "vite"; import type { CreateHandlerOptions, CssCollectorProps, CssContent, InlineCssCollectorProps, } from "../types.js"; export function createRscStream<InlineCSS extends boolean = true>({ Html, Page, props, loader = (id) => import(id).then((m) => m.default), moduleRootPath, moduleBasePath, moduleBaseURL, logger, cssFiles = [], route, url, pipableStreamOptions, htmlProps, inlineCss = true as InlineCSS, CssCollector, root, }: { Html: CreateHandlerOptions["Html"]; Page: React.ComponentType<any>; loader: (id: string) => Promise<any>; props: any; moduleBase: string; moduleRootPath: string; moduleBasePath: string; moduleBaseURL: string; logger: Logger; route: string; url: string; pipableStreamOptions?: PipeableStreamOptions; htmlProps?: any; root: string; inlineCss?: InlineCSS; cssFiles?: (string | CssContent)[]; } & (InlineCSS extends true ? { CssCollector: React.FC<InlineCssCollectorProps>; } : { CssCollector: React.FC<CssCollectorProps>; })) { const htmlIsFragment = Html == React.Fragment; if (!htmlIsFragment) { if (!htmlProps) { htmlProps = {}; } if (!("moduleBaseURL" in htmlProps)) { htmlProps["moduleBaseURL"] = moduleBaseURL; } if (!("moduleBasePath" in htmlProps)) { htmlProps["moduleBasePath"] = moduleBasePath; } if (!("moduleRootPath" in htmlProps)) { htmlProps["moduleRootPath"] = moduleRootPath; } if (!("url" in htmlProps)) { htmlProps["url"] = url; } if (!("route" in htmlProps)) { htmlProps["route"] = route; } if (!("pageProps" in htmlProps)) { htmlProps["pageProps"] = props; } } const withCss = React.createElement( CssCollector as any, (inlineCss === true ? { cssFiles: cssFiles, route, moduleBaseURL, moduleBasePath, moduleRootPath, root, loader, } : { cssFiles: cssFiles, route, moduleBaseURL }) as any, React.createElement(Page, props) ); // Otherwise wrap with Html component const content = htmlIsFragment ? withCss : React.createElement(Html, htmlProps, withCss); try { return renderToPipeableStream( content, moduleBasePath, pipableStreamOptions ); } catch (error) { logger.error(`Failed to create stream for ${route}.`, { error: error as Error, }); return null; } }