vite-react-ssg 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/node.mjs CHANGED
@@ -1,18 +1,15 @@
1
1
  import { join, isAbsolute, parse, dirname } from 'node:path';
2
2
  import { createRequire } from 'node:module';
3
- import { gray, yellow, blue, dim, cyan, red, green, bold, reset, bgLightCyan } from 'kolorist';
3
+ import { gray, yellow, blue, dim, cyan, red, green, reset, bold, bgLightCyan } from 'kolorist';
4
4
  import fs from 'fs-extra';
5
- import { resolveConfig, build as build$1, mergeConfig, version as version$1, createServer } from 'vite';
5
+ import { resolveConfig, build as build$1, mergeConfig, version as version$1, createServer, send } from 'vite';
6
6
  import { JSDOM } from 'jsdom';
7
- import { s as serializeState } from './shared/vite-react-ssg.a009fbf1.mjs';
7
+ import { s as serializeState } from './shared/vite-react-ssg.579feabb.mjs';
8
8
  import { readFileSync } from 'node:fs';
9
9
  import React from 'react';
10
10
  import { HelmetProvider } from 'react-helmet-async';
11
11
  import { Writable } from 'node:stream';
12
12
  import { renderToPipeableStream } from 'react-dom/server';
13
- import https from 'node:https';
14
- import express from 'express';
15
- import { certificateFor } from '@childrentime/devcert';
16
13
 
17
14
  function getDefaultExportFromCjs (x) {
18
15
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
@@ -857,10 +854,18 @@ async function routesToPaths(routes) {
857
854
  if (!routes || routes.length === 0)
858
855
  return { paths: ["/"], pathToEntry };
859
856
  const paths = /* @__PURE__ */ new Set();
860
- const lazyPaths = /* @__PURE__ */ new Set();
861
857
  const getPaths = async (routes2, prefix = "") => {
862
858
  prefix = prefix.replace(/\/$/g, "");
863
- for (const route of routes2) {
859
+ for (let route of routes2) {
860
+ if (route.lazy) {
861
+ const lazyData = await route.lazy();
862
+ if (lazyData) {
863
+ route = {
864
+ ...route,
865
+ ...lazyData
866
+ };
867
+ }
868
+ }
864
869
  let path = route.path;
865
870
  path = handlePath(path, prefix, route.entry);
866
871
  if (route.getStaticPaths && isDynamicSegmentsRoute(path)) {
@@ -871,8 +876,6 @@ async function routesToPaths(routes) {
871
876
  await getPaths(route.children, staticPath);
872
877
  }
873
878
  }
874
- if (route.lazy)
875
- lazyPaths.add(route.index ? prefix : path ?? "");
876
879
  if (route.index)
877
880
  addEntry(prefix, route.entry);
878
881
  if (Array.isArray(route.children))
@@ -880,7 +883,7 @@ async function routesToPaths(routes) {
880
883
  }
881
884
  };
882
885
  await getPaths(routes);
883
- return { paths: Array.from(paths), pathToEntry, lazyPaths: Array.from(lazyPaths) };
886
+ return { paths: Array.from(paths), pathToEntry };
884
887
  function handlePath(path, prefix, entry) {
885
888
  if (path != null) {
886
889
  path = prefix && !path.startsWith("/") ? `${prefix}${path ? `/${path}` : ""}` : path;
@@ -894,31 +897,6 @@ async function routesToPaths(routes) {
894
897
  return path;
895
898
  }
896
899
  }
897
- function createFetchRequest(req) {
898
- const origin = `${req.protocol}://${req.get("host")}`;
899
- const url = new URL(req.originalUrl || req.url, origin);
900
- const controller = new AbortController();
901
- req.on("close", () => controller.abort());
902
- const headers = new Headers();
903
- for (const [key, values] of Object.entries(req.headers)) {
904
- if (values) {
905
- if (Array.isArray(values)) {
906
- for (const value of values)
907
- headers.append(key, value);
908
- } else {
909
- headers.set(key, values);
910
- }
911
- }
912
- }
913
- const init = {
914
- method: req.method,
915
- headers,
916
- signal: controller.signal
917
- };
918
- if (req.method !== "GET" && req.method !== "HEAD")
919
- init.body = req.body;
920
- return new Request(url.href, init);
921
- }
922
900
  async function resolveAlias(config, entry) {
923
901
  const resolver = config.createResolver();
924
902
  const result = await resolver(entry, config.root);
@@ -951,10 +929,6 @@ function withTrailingSlash(path) {
951
929
  return `${path}/`;
952
930
  return path;
953
931
  }
954
- const postfixRE = /[?#].*$/s;
955
- function cleanUrl(url) {
956
- return url.replace(postfixRE, "");
957
- }
958
932
  const dynamicRE = /[:*?]/;
959
933
  function isDynamicSegmentsRoute(route) {
960
934
  if (!route)
@@ -1054,17 +1028,6 @@ async function render(routesOrApp, request, styleCollector, basename) {
1054
1028
  const { htmlAttributes, bodyAttributes, metaAttributes, styleTag } = extractHelmet(helmetContext, styleCollector);
1055
1029
  return { appHTML, htmlAttributes, bodyAttributes, metaAttributes, styleTag, routerContext: context };
1056
1030
  }
1057
- async function preLoad(routes, paths) {
1058
- if (!paths || paths.length === 0)
1059
- return routes;
1060
- const { createStaticHandler } = await import('react-router-dom/server.js');
1061
- const { dataRoutes, query } = createStaticHandler(routes);
1062
- await Promise.all(paths.map(async (path) => {
1063
- const request = createRequest(path);
1064
- return query(request);
1065
- }));
1066
- return dataRoutes;
1067
- }
1068
1031
  function extractHelmet(context, styleCollector) {
1069
1032
  const { helmet } = context;
1070
1033
  const htmlAttributes = helmet.htmlAttributes.toString();
@@ -1080,56 +1043,6 @@ function extractHelmet(context, styleCollector) {
1080
1043
  return { htmlAttributes, bodyAttributes, metaAttributes, styleTag };
1081
1044
  }
1082
1045
 
1083
- function renderPreloadLinks(document, modules, ssrManifest) {
1084
- const seen = /* @__PURE__ */ new Set();
1085
- const preloadLinks = [];
1086
- Array.from(modules).forEach((id) => {
1087
- const files = ssrManifest[id] || [];
1088
- files.forEach((file) => {
1089
- if (!preloadLinks.includes(file))
1090
- preloadLinks.push(file);
1091
- });
1092
- });
1093
- if (preloadLinks) {
1094
- preloadLinks.forEach((file) => {
1095
- if (!seen.has(file)) {
1096
- seen.add(file);
1097
- renderPreloadLink(document, file);
1098
- }
1099
- });
1100
- }
1101
- }
1102
- function renderPreloadLink(document, file) {
1103
- if (file.endsWith(".js")) {
1104
- appendLink(document, {
1105
- rel: "modulepreload",
1106
- crossOrigin: "",
1107
- href: file
1108
- });
1109
- } else if (file.endsWith(".css")) {
1110
- appendLink(document, {
1111
- rel: "stylesheet",
1112
- href: file
1113
- });
1114
- }
1115
- }
1116
- function createLink$1(document) {
1117
- return document.createElement("link");
1118
- }
1119
- function setAttrs(el, attrs) {
1120
- const keys = Object.keys(attrs);
1121
- for (const key of keys)
1122
- el.setAttribute(key, attrs[key]);
1123
- }
1124
- function appendLink(document, attrs) {
1125
- const exits = document.head.querySelector(`link[href='${attrs.file}']`);
1126
- if (exits)
1127
- return;
1128
- const link = createLink$1(document);
1129
- setAttrs(link, attrs);
1130
- document.head.appendChild(link);
1131
- }
1132
-
1133
1046
  async function renderHTML({
1134
1047
  rootContainerId,
1135
1048
  indexHTML,
@@ -1173,7 +1086,7 @@ async function renderHTML({
1173
1086
  return renderedOutput;
1174
1087
  }
1175
1088
  async function detectEntry(root) {
1176
- const scriptSrcReg = /<script(?:.*?)src=["'](.+?)["'](?!<)(?:.*)\>(?:[\n\r\s]*?)(?:<\/script>)/img;
1089
+ const scriptSrcReg = /<script(?:.*?)src=["'](.+?)["'](?!<)(?:.*)\>(?:[\n\r\s]*?)(?:<\/script>)/gim;
1177
1090
  const html = await fs.readFile(join(root, "index.html"), "utf-8");
1178
1091
  const scripts = [...html.matchAll(scriptSrcReg)];
1179
1092
  const [, entry] = scripts.find((matchResult) => {
@@ -1183,10 +1096,61 @@ async function detectEntry(root) {
1183
1096
  }) || [];
1184
1097
  return entry || "src/main.ts";
1185
1098
  }
1186
- function createLink(href) {
1099
+ function createLink$1(href) {
1187
1100
  return `<link rel="stylesheet" href="${href}">`;
1188
1101
  }
1189
1102
 
1103
+ function renderPreloadLinks(document, modules, ssrManifest) {
1104
+ const seen = /* @__PURE__ */ new Set();
1105
+ const preloadLinks = [];
1106
+ Array.from(modules).forEach((id) => {
1107
+ const files = ssrManifest[id] || [];
1108
+ files.forEach((file) => {
1109
+ if (!preloadLinks.includes(file))
1110
+ preloadLinks.push(file);
1111
+ });
1112
+ });
1113
+ if (preloadLinks) {
1114
+ preloadLinks.forEach((file) => {
1115
+ if (!seen.has(file)) {
1116
+ seen.add(file);
1117
+ renderPreloadLink(document, file);
1118
+ }
1119
+ });
1120
+ }
1121
+ }
1122
+ function renderPreloadLink(document, file) {
1123
+ if (file.endsWith(".js")) {
1124
+ appendLink(document, {
1125
+ rel: "modulepreload",
1126
+ crossOrigin: "",
1127
+ href: file
1128
+ });
1129
+ } else if (file.endsWith(".css")) {
1130
+ appendLink(document, {
1131
+ rel: "stylesheet",
1132
+ href: file,
1133
+ crossOrigin: ""
1134
+ });
1135
+ }
1136
+ }
1137
+ function createLink(document) {
1138
+ return document.createElement("link");
1139
+ }
1140
+ function setAttrs(el, attrs) {
1141
+ const keys = Object.keys(attrs);
1142
+ for (const key of keys)
1143
+ el.setAttribute(key, attrs[key]);
1144
+ }
1145
+ function appendLink(document, attrs) {
1146
+ const exits = document.head.querySelector(`link[href='${attrs.file}']`);
1147
+ if (exits)
1148
+ return;
1149
+ const link = createLink(document);
1150
+ setAttrs(link, attrs);
1151
+ document.head.appendChild(link);
1152
+ }
1153
+
1190
1154
  function DefaultIncludedRoutes(paths, _routes) {
1191
1155
  return paths.filter((i) => !i.includes(":") && !i.includes("*"));
1192
1156
  }
@@ -1268,9 +1232,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1268
1232
  const { createRoot, includedRoutes: serverEntryIncludedRoutes } = format === "esm" ? await import(serverEntry) : _require(serverEntry);
1269
1233
  const includedRoutes = serverEntryIncludedRoutes || configIncludedRoutes;
1270
1234
  const { routes } = await createRoot(false);
1271
- const { lazyPaths } = await routesToPaths(routes);
1272
- const dataRoutes = await preLoad([...routes || []], lazyPaths);
1273
- const { paths, pathToEntry } = await routesToPaths(dataRoutes);
1235
+ const { paths, pathToEntry } = await routesToPaths(routes);
1274
1236
  let routesPaths = includeAllRoutes ? paths : await includedRoutes(paths, routes || []);
1275
1237
  routesPaths = DefaultIncludedRoutes(routesPaths);
1276
1238
  routesPaths = Array.from(new Set(routesPaths));
@@ -1310,8 +1272,10 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1310
1272
  renderPreloadLinks(jsdom.window.document, modules, ssrManifest);
1311
1273
  const html = jsdom.serialize();
1312
1274
  let transformed = await onPageRendered?.(path, html, appCtx) || html;
1313
- if (critters)
1275
+ if (critters) {
1314
1276
  transformed = await crittersQueue.add(() => critters.process(transformed));
1277
+ transformed = transformed.replace(/<link\srel="stylesheet"/g, '<link rel="stylesheet" crossorigin');
1278
+ }
1315
1279
  if (styleTag)
1316
1280
  transformed = transformed.replace("<head>", `<head>${styleTag}`);
1317
1281
  const formatted = await formatHtml(transformed, formatting);
@@ -1361,9 +1325,14 @@ async function formatHtml(html, formatting) {
1361
1325
  minifyCSS: true
1362
1326
  });
1363
1327
  } else if (formatting === "prettify") {
1364
- const prettier = (await import('prettier/esm/standalone.mjs')).default;
1365
- const parserHTML = (await import('prettier/esm/parser-html.mjs')).default;
1366
- return prettier.format(html, { semi: false, parser: "html", plugins: [parserHTML] });
1328
+ try {
1329
+ const prettier = (await import('prettier/esm/standalone.mjs')).default;
1330
+ const parserHTML = (await import('prettier/esm/parser-html.mjs')).default;
1331
+ return prettier.format(html, { semi: false, parser: "html", plugins: [parserHTML] });
1332
+ } catch (e) {
1333
+ console.error(`${gray("[vite-react-ssg]")} ${red(`Error formatting html: ${e?.message}`)}`);
1334
+ return html;
1335
+ }
1367
1336
  }
1368
1337
  return html;
1369
1338
  }
@@ -1385,114 +1354,48 @@ function collectModules(manifest, entry, mods = /* @__PURE__ */ new Set()) {
1385
1354
  return mods;
1386
1355
  }
1387
1356
 
1388
- const SHORTCUTS = [
1389
- {
1390
- key: "u",
1391
- description: "show server url",
1392
- action(vite, _) {
1393
- vite.config.logger.info("");
1394
- printServerInfo(vite, true);
1395
- }
1396
- },
1397
- {
1398
- key: "c",
1399
- description: "clear console",
1400
- action(vite, _) {
1401
- vite.config.logger.clearScreen("error");
1402
- }
1403
- },
1404
- {
1405
- key: "q",
1406
- description: "quit",
1407
- action(_, server) {
1408
- server.close(() => process.exit());
1409
- }
1357
+ function invariant(value, message) {
1358
+ if (value === false || value === null || typeof value === "undefined") {
1359
+ console.error(
1360
+ "The following error is a bug in Remix; please open an issue! https://github.com/remix-run/remix/issues/new"
1361
+ );
1362
+ throw new Error(message);
1410
1363
  }
1411
- ];
1412
- function bindShortcuts(viteServer, server) {
1413
- if (!process.stdin.isTTY || process.env.CI)
1414
- return;
1415
- viteServer.config.logger.info(
1416
- dim(green(" \u279C")) + dim(" press ") + bold("h") + dim(" to show help")
1417
- );
1418
- const shortcuts = SHORTCUTS;
1419
- let actionRunning = false;
1420
- const onInput = async (input) => {
1421
- if (input === "" || input === "") {
1422
- try {
1423
- await server.close();
1424
- } finally {
1425
- process.exit(1);
1426
- }
1427
- return;
1428
- }
1429
- if (actionRunning)
1430
- return;
1431
- if (input === "h") {
1432
- viteServer.config.logger.info(
1433
- [
1434
- "",
1435
- bold(" Shortcuts"),
1436
- ...shortcuts.map(
1437
- (shortcut2) => dim(" press ") + bold(shortcut2.key) + dim(` to ${shortcut2.description}`)
1438
- )
1439
- ].join("\n")
1440
- );
1441
- }
1442
- const shortcut = shortcuts.find((shortcut2) => shortcut2.key === input);
1443
- if (!shortcut)
1444
- return;
1445
- actionRunning = true;
1446
- await shortcut.action(viteServer, server);
1447
- actionRunning = false;
1448
- };
1449
- process.stdin.setRawMode(true);
1450
- process.stdin.on("data", onInput).setEncoding("utf8").resume();
1451
- server.on("close", () => {
1452
- process.stdin.off("data", onInput).pause();
1453
- });
1454
1364
  }
1455
1365
 
1456
- function baseMiddleware(rawBase) {
1457
- return (req, res, next) => {
1458
- const url = req.url;
1459
- const pathname = cleanUrl(url);
1460
- const base = rawBase;
1461
- if (pathname.startsWith(base))
1462
- return next();
1463
- if (pathname === "/" || pathname === "/index.html") {
1464
- res.writeHead(302, {
1465
- Location: base + url.slice(pathname.length)
1466
- });
1467
- res.end();
1468
- return;
1469
- }
1470
- const redirectPath = withTrailingSlash(url) !== base ? joinUrlSegments(base, url) : base;
1471
- if (req.headers.accept?.includes("text/html")) {
1472
- res.writeHead(404, {
1473
- "Content-Type": "text/html"
1474
- });
1475
- res.end(
1476
- `The server is configured with a public base URL of ${base} - did you mean to visit <a href="${redirectPath}">${redirectPath}</a> instead?`
1477
- );
1478
- } else {
1479
- res.writeHead(404, {
1480
- "Content-Type": "text/plain"
1481
- });
1482
- res.end(
1483
- `The server is configured with a public base URL of ${base} - did you mean to visit ${redirectPath} instead?`
1484
- );
1366
+ function fromNodeHeaders(nodeHeaders) {
1367
+ const headers = new Headers();
1368
+ for (const [key, values] of Object.entries(nodeHeaders)) {
1369
+ if (values) {
1370
+ if (Array.isArray(values)) {
1371
+ for (const value of values)
1372
+ headers.append(key, value);
1373
+ } else {
1374
+ headers.set(key, values);
1375
+ }
1485
1376
  }
1377
+ }
1378
+ return headers;
1379
+ }
1380
+ function fromNodeRequest(nodeReq) {
1381
+ const origin = nodeReq.headers.origin && nodeReq.headers.origin !== "null" ? nodeReq.headers.origin : `http://${nodeReq.headers.host}`;
1382
+ invariant(
1383
+ nodeReq.originalUrl,
1384
+ "Expected `nodeReq.originalUrl` to be defined"
1385
+ );
1386
+ const url = new URL(nodeReq.originalUrl, origin);
1387
+ const init = {
1388
+ method: nodeReq.method,
1389
+ headers: fromNodeHeaders(nodeReq.headers)
1486
1390
  };
1391
+ return new Request(url.href, init);
1487
1392
  }
1488
1393
 
1489
- async function dev(ssgOptions = {}, viteConfig = {}) {
1394
+ async function dev(ssgOptions = {}, viteConfig = {}, customOptions) {
1490
1395
  const mode = process.env.MODE || process.env.NODE_ENV || ssgOptions.mode || "development";
1491
1396
  const config = await resolveConfig(viteConfig, "serve", mode, mode);
1492
1397
  const cwd = process.cwd();
1493
1398
  const root = config.root || cwd;
1494
- const httpsOptions = config.server.https;
1495
- setBase(config.rawBase);
1496
1399
  const {
1497
1400
  entry = await detectEntry(root),
1498
1401
  onBeforePageRender,
@@ -1504,21 +1407,12 @@ async function dev(ssgOptions = {}, viteConfig = {}) {
1504
1407
  const template = await fs.readFile(join(root, "index.html"), "utf-8");
1505
1408
  let viteServer;
1506
1409
  globalThis.__ssr_start_time = performance.now();
1507
- createServer$1().then(async (app) => {
1508
- const port = viteServer.config.server.port || 5173;
1509
- if (httpsOptions) {
1510
- const localHttpsOptions = typeof httpsOptions === "boolean" ? await certificateFor(["localhost"]) : httpsOptions;
1511
- const server = https.createServer(localHttpsOptions, app);
1512
- server.listen(port, () => {
1513
- printServerInfo(viteServer, false, true);
1514
- bindShortcuts(viteServer, server);
1515
- });
1516
- } else {
1517
- const server = app.listen(port, () => {
1518
- printServerInfo(viteServer);
1519
- bindShortcuts(viteServer, server);
1520
- });
1521
- }
1410
+ createServer$1().catch((err) => {
1411
+ console.error(
1412
+ `${red(`failed to start server. error:`)}
1413
+ ${err.stack}`
1414
+ );
1415
+ process.exit(1);
1522
1416
  });
1523
1417
  async function createServer$1() {
1524
1418
  process.env.__DEV_MODE_SSR = "true";
@@ -1526,108 +1420,105 @@ async function dev(ssgOptions = {}, viteConfig = {}) {
1526
1420
  const { jsdomGlobal } = await import('./chunks/jsdomGlobal.mjs');
1527
1421
  jsdomGlobal();
1528
1422
  }
1529
- const app = express();
1530
1423
  viteServer = await createServer({
1531
- // ...options,
1532
- server: { middlewareMode: true },
1533
- appType: "custom"
1534
- });
1535
- app.use(baseMiddleware(getBase()));
1536
- app.use((req, res, next) => {
1537
- viteServer.middlewares.handle(req, res, next);
1538
- });
1539
- app.use("*", async (req, res) => {
1540
- try {
1541
- const url = req.originalUrl;
1542
- const indexHTML = await viteServer.transformIndexHtml(url, template);
1543
- const createRoot = await viteServer.ssrLoadModule(ssrEntry).then((m) => m.createRoot);
1544
- const appCtx = await createRoot(false, url);
1545
- const { routes, getStyleCollector, base: base2, app: app2 } = appCtx;
1546
- const transformedIndexHTML = await onBeforePageRender?.(url, indexHTML, appCtx) || indexHTML;
1547
- const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1548
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await render(app2 ?? [...routes], createFetchRequest(req), styleCollector, base2);
1549
- metaAttributes.push(styleTag);
1550
- const matchesEntries = routerContext?.matches.map((match) => match.route.entry).filter((entry2) => !!entry2).map((entry2) => entry2[0] === "/" ? entry2 : `/${entry2}`) ?? [];
1551
- const mods = await Promise.all(
1552
- [entry, ...matchesEntries].map(async (entry2) => await viteServer.moduleGraph.getModuleByUrl(entry2))
1553
- );
1554
- const assetsUrls = /* @__PURE__ */ new Set();
1555
- const collectAssets = async (mod) => {
1556
- if (!mod || !mod?.ssrTransformResult)
1557
- return;
1558
- const { deps = [], dynamicDeps = [] } = mod?.ssrTransformResult;
1559
- const allDeps = [...deps, ...dynamicDeps];
1560
- for (const dep of allDeps) {
1561
- if (dep.endsWith(".css")) {
1562
- assetsUrls.add(dep);
1563
- } else if (dep.endsWith(".ts") || dep.endsWith(".tsx")) {
1564
- const depModule = await viteServer.moduleGraph.getModuleByUrl(dep);
1565
- depModule && await collectAssets(depModule);
1566
- }
1424
+ ...viteConfig,
1425
+ plugins: [
1426
+ ...viteConfig.plugins ?? [],
1427
+ {
1428
+ name: "vite-react-ssg:dev-server-remix",
1429
+ configureServer(server) {
1430
+ return () => {
1431
+ server.middlewares.use(async (req, res, _next) => {
1432
+ try {
1433
+ const url = req.originalUrl;
1434
+ const indexHTML = await viteServer.transformIndexHtml(url, template);
1435
+ const createRoot = await viteServer.ssrLoadModule(ssrEntry).then((m) => m.createRoot);
1436
+ const appCtx = await createRoot(false, url);
1437
+ const { routes, getStyleCollector, base, app } = appCtx;
1438
+ const transformedIndexHTML = await onBeforePageRender?.(url, indexHTML, appCtx) || indexHTML;
1439
+ const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1440
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await render(app ?? [...routes], fromNodeRequest(req), styleCollector, base);
1441
+ metaAttributes.push(styleTag);
1442
+ const matchesEntries = routerContext?.matches.map((match) => match.route.entry).filter((entry2) => !!entry2).map((entry2) => entry2[0] === "/" ? entry2 : `/${entry2}`) ?? [];
1443
+ const mods = await Promise.all(
1444
+ [ssrEntry, entry, ...matchesEntries].map(async (entry2) => await viteServer.moduleGraph.getModuleByUrl(entry2))
1445
+ );
1446
+ const assetsUrls = /* @__PURE__ */ new Set();
1447
+ const collectAssets = async (mod) => {
1448
+ if (!mod || !mod?.ssrTransformResult)
1449
+ return;
1450
+ const { deps = [], dynamicDeps = [] } = mod?.ssrTransformResult;
1451
+ const allDeps = [...deps, ...dynamicDeps];
1452
+ for (const dep of allDeps) {
1453
+ if (dep.endsWith(".css")) {
1454
+ assetsUrls.add(dep);
1455
+ } else if (dep.endsWith(".ts") || dep.endsWith(".tsx")) {
1456
+ const depModule = await viteServer.moduleGraph.getModuleByUrl(dep);
1457
+ depModule && await collectAssets(depModule);
1458
+ }
1459
+ }
1460
+ };
1461
+ await Promise.all(mods.map(async (mod) => collectAssets(mod)));
1462
+ const preloadLink = [...assetsUrls].map((item) => createLink$1(joinUrlSegments(config.base, item)));
1463
+ metaAttributes.push(...preloadLink);
1464
+ const renderedHTML = await renderHTML({
1465
+ rootContainerId,
1466
+ appHTML,
1467
+ indexHTML: transformedIndexHTML,
1468
+ metaAttributes,
1469
+ bodyAttributes,
1470
+ htmlAttributes,
1471
+ initialState: null
1472
+ });
1473
+ const transformed = await onPageRendered?.(url, renderedHTML, appCtx) || renderedHTML;
1474
+ res.statusCode = 200;
1475
+ res.setHeader("Content-Type", "text/html");
1476
+ const isDev = "pluginContainer" in server;
1477
+ const headers = isDev ? server.config.server.headers : server.config.preview.headers;
1478
+ send(req, res, transformed, "html", { headers });
1479
+ } catch (e) {
1480
+ viteServer.ssrFixStacktrace(e);
1481
+ console.error(`[vite-react-ssg] error: ${e.stack}`);
1482
+ res.statusCode = 500;
1483
+ res.end(e.stack);
1484
+ }
1485
+ });
1486
+ };
1567
1487
  }
1568
- };
1569
- await Promise.all(mods.map(async (mod) => collectAssets(mod)));
1570
- const preloadLink = [...assetsUrls].map((item) => createLink(item));
1571
- metaAttributes.push(...preloadLink);
1572
- const renderedHTML = await renderHTML({
1573
- rootContainerId,
1574
- appHTML,
1575
- indexHTML: transformedIndexHTML,
1576
- metaAttributes,
1577
- bodyAttributes,
1578
- htmlAttributes,
1579
- initialState: null
1580
- });
1581
- const transformed = await onPageRendered?.(url, renderedHTML, appCtx) || renderedHTML;
1582
- res.status(200).set({ "Content-Type": "text/html" }).end(transformed);
1583
- } catch (e) {
1584
- viteServer.ssrFixStacktrace(e);
1585
- console.error(`[vite-react-ssg] error: ${e.stack}`);
1586
- res.status(500).end(e.stack);
1587
- }
1488
+ }
1489
+ ]
1588
1490
  });
1589
- return app;
1491
+ await viteServer.listen();
1492
+ printServerInfo(viteServer, !!customOptions);
1493
+ viteServer.bindCLIShortcuts({ print: true });
1494
+ return viteServer;
1590
1495
  }
1591
1496
  }
1592
- async function printServerInfo(server, onlyUrl = false, https2 = false) {
1497
+ async function printServerInfo(server, onlyUrl = false) {
1498
+ if (onlyUrl)
1499
+ return server.printUrls();
1593
1500
  const info = server.config.logger.info;
1594
- const port = server.config.server.port || 5173;
1595
- const protocol = https2 ? "https" : "http";
1596
- const url = `${protocol}://localhost:${port}/${removeLeadingSlash(getBase())}`;
1597
- if (!onlyUrl) {
1598
- let ssrReadyMessage = " -- SSR";
1599
- if (globalThis.__ssr_start_time) {
1600
- ssrReadyMessage += ` ready in ${reset(bold(`${Math.round(
1601
- // @ts-expect-error global var
1602
- performance.now() - globalThis.__ssr_start_time
1603
- )}ms`))}`;
1604
- }
1605
- info(
1606
- `
1501
+ let ssrReadyMessage = " -- SSR";
1502
+ if (globalThis.__ssr_start_time) {
1503
+ ssrReadyMessage += ` ready in ${reset(bold(`${Math.round(
1504
+ // @ts-expect-error global var
1505
+ performance.now() - globalThis.__ssr_start_time
1506
+ )}ms`))}`;
1507
+ }
1508
+ info(
1509
+ `
1607
1510
  ${bgLightCyan(` VITE-REACT-SSG v${version} `)}`,
1608
- { clear: !server.config.logger.hasWarned }
1609
- );
1610
- info(
1611
- `${cyan(`
1511
+ { clear: !server.config.logger.hasWarned }
1512
+ );
1513
+ info(
1514
+ `${cyan(`
1612
1515
  VITE v${version$1}`) + dim(ssrReadyMessage)}
1613
1516
  `
1614
- );
1615
- }
1517
+ );
1616
1518
  info(
1617
1519
  green(" dev server running at:")
1618
1520
  );
1619
- printUrls(url, info);
1620
- }
1621
- function printUrls(url, info) {
1622
- const colorUrl = (url2) => cyan(url2.replace(/:(\d+)\//, (_, port) => `:${bold(port)}/`));
1623
- info(` ${green("\u279C")} ${bold("Local")}: ${colorUrl(url)}`);
1624
- }
1625
- let base = "";
1626
- function getBase() {
1627
- return base;
1628
- }
1629
- function setBase(newBase) {
1630
- base = newBase;
1521
+ server.printUrls();
1631
1522
  }
1632
1523
 
1633
1524
  export { build, dev };
@@ -1,4 +1,4 @@
1
- const UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
1
+ const UNSAFE_CHARS_REGEXP = /[<>/\u2028\u2029]/g;
2
2
  const ESCAPED_CHARS = {
3
3
  "<": "\\u003C",
4
4
  ">": "\\u003E",
@@ -110,9 +110,9 @@ interface ViteReactSSGContext<HasRouter extends boolean = true> {
110
110
  routerOptions: HasRouter extends true ? RouterOptions : undefined;
111
111
  initialState: Record<string, any>;
112
112
  isClient: boolean;
113
- onSSRAppRendered(cb: Function): void;
114
- triggerOnSSRAppRendered(route: string, appHTML: string, appCtx: ViteReactSSGContext): Promise<unknown[]>;
115
- transformState?(state: any): any;
113
+ onSSRAppRendered: (cb: Function) => void;
114
+ triggerOnSSRAppRendered: (route: string, appHTML: string, appCtx: ViteReactSSGContext) => Promise<unknown[]>;
115
+ transformState?: (state: any) => any;
116
116
  /**
117
117
  * Current router path on SSG, `undefined` on client side.
118
118
  */