UNPKG

@modern-js/server-core

Version:

A Progressive React Framework for modern web development.

160 lines (159 loc) • 6.07 kB
import path from "path"; import { fileReader } from "@modern-js/runtime-utils/fileReader"; import { fs, LOADABLE_STATS_FILE, MAIN_ENTRY_NAME, NESTED_ROUTE_SPEC_FILE, ROUTE_MANIFEST_FILE, SERVER_BUNDLE_DIRECTORY, compatibleRequire, isProd } from "@modern-js/utils"; import { uniqueKeyByRoute } from "../../../utils"; async function getHtmlTemplates(pwd, routes) { const htmlRoutes = routes.filter((route) => route.entryName); const htmls = await Promise.all(htmlRoutes.map(async (route) => { let html; try { var _this; const htmlPath = path.join(pwd, route.entryPath); html = (_this = await fileReader.readFile(htmlPath, "utf-8")) === null || _this === void 0 ? void 0 : _this.toString(); } catch (e) { } return [ uniqueKeyByRoute(route), html ]; }) || []); const templates = Object.fromEntries(htmls); return templates; } function injectTemplates(pwd, routes, htmlTemplatePromise) { return async (c, next) => { if (routes && !c.get("templates")) { const templates = await (htmlTemplatePromise || getHtmlTemplates(pwd, routes)); c.set("templates", templates); } await next(); }; } const loadBundle = async (filepath, logger) => { if (!await fs.pathExists(filepath)) { return void 0; } try { const module = await compatibleRequire(filepath, false); return module; } catch (e) { logger.error(`Load ${filepath} bundle failed, error = %s`, e instanceof Error ? e.stack || e.message : e); return void 0; } }; async function getServerManifest(pwd, routes, logger) { const loaderBundles = {}; const renderBundles = {}; await Promise.all(routes.filter((route) => Boolean(route.bundle)).map(async (route) => { const entryName = route.entryName || MAIN_ENTRY_NAME; const renderBundlePath = path.join(pwd, route.bundle || ""); const loaderBundlePath = path.join(pwd, SERVER_BUNDLE_DIRECTORY, `${entryName}-server-loaders.js`); const renderBundle = await loadBundle(renderBundlePath, logger); const loaderBundle = await loadBundle(loaderBundlePath, logger); renderBundle && (renderBundles[entryName] = renderBundle); loaderBundle && (loaderBundles[entryName] = (loaderBundle === null || loaderBundle === void 0 ? void 0 : loaderBundle.loadModules) ? await (loaderBundle === null || loaderBundle === void 0 ? void 0 : loaderBundle.loadModules()) : loaderBundle); })); const loadableUri = path.join(pwd, LOADABLE_STATS_FILE); const loadableStats = await compatibleRequire(loadableUri).catch((_) => ({})); const routesManifestUri = path.join(pwd, ROUTE_MANIFEST_FILE); const routeManifest = await compatibleRequire(routesManifestUri).catch((_) => ({})); const nestedRoutesJsonPath = path.join(pwd, NESTED_ROUTE_SPEC_FILE); const nestedRoutesJson = await compatibleRequire(nestedRoutesJsonPath).catch((_) => ({})); return { loaderBundles, renderBundles, loadableStats, routeManifest, nestedRoutesJson }; } function injectServerManifest(pwd, routes, manifestPromise) { return async (c, next) => { if (routes && !c.get("serverManifest")) { const logger = c.get("logger"); const serverManifest = await (manifestPromise || getServerManifest(pwd, routes, logger)); c.set("serverManifest", serverManifest); } await next(); }; } async function getRscServerManifest(pwd) { const rscServerManifest = await compatibleRequire(path.join(pwd, "bundles", "react-server-manifest.json")).catch((_) => void 0); return rscServerManifest; } async function getClientManifest(pwd) { const rscClientManifest = await compatibleRequire(path.join(pwd, "react-client-manifest.json")).catch((_) => void 0); return rscClientManifest; } async function getRscSSRManifest(pwd) { const rscSSRManifest = await compatibleRequire(path.join(pwd, "react-ssr-manifest.json")).catch((_) => void 0); return rscSSRManifest; } const injectRscManifestPlugin = () => ({ name: "@modern-js/plugin-inject-rsc-manifest", setup(api) { return { async prepare() { var _config_server; const { middlewares, distDirectory: pwd } = api.useAppContext(); const config = api.useConfigContext(); if (!((_config_server = config.server) === null || _config_server === void 0 ? void 0 : _config_server.rsc)) { return; } middlewares.push({ name: "inject-rsc-manifest", handler: async (c, next) => { if (!c.get("rscServerManifest")) { const rscServerManifest = await getRscServerManifest(pwd); c.set("rscServerManifest", rscServerManifest); } if (!c.get("rscClientManifest")) { const rscClientManifest = await getClientManifest(pwd); c.set("rscClientManifest", rscClientManifest); } if (!c.get("rscSSRManifest")) { const rscSSRManifest = await getRscSSRManifest(pwd); c.set("rscSSRManifest", rscSSRManifest); } await next(); } }); } }; } }); const injectResourcePlugin = () => ({ name: "@modern-js/plugin-inject-resource", setup(api) { return { async prepare() { const { middlewares, routes, distDirectory: pwd } = api.useAppContext(); let htmlTemplatePromise; let manifestPromise; if (isProd()) { manifestPromise = getServerManifest(pwd, routes || [], console); htmlTemplatePromise = getHtmlTemplates(pwd, routes || []); } middlewares.push({ name: "inject-server-manifest", handler: injectServerManifest(pwd, routes, manifestPromise) }); middlewares.push({ name: "inject-html", handler: injectTemplates(pwd, routes, htmlTemplatePromise) }); } }; } }); export { getClientManifest, getHtmlTemplates, getRscSSRManifest, getRscServerManifest, getServerManifest, injectResourcePlugin, injectRscManifestPlugin, injectServerManifest, injectTemplates };