vite-react-ssg 0.7.0-beta.1 → 0.7.0

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.cjs CHANGED
@@ -850,19 +850,8 @@ function getSize(str) {
850
850
  return `${(str.length / 1024).toFixed(2)} KiB`;
851
851
  }
852
852
  async function routesToPaths(routes) {
853
- const pathToEntry = {};
854
- function addEntry(path, entry) {
855
- if (!entry)
856
- return;
857
- if (entry[0] === "/")
858
- entry = entry.slice(1);
859
- if (pathToEntry[path])
860
- pathToEntry[path].add(entry);
861
- else
862
- pathToEntry[path] = /* @__PURE__ */ new Set([entry]);
863
- }
864
853
  if (!routes || routes.length === 0)
865
- return { paths: ["/"], pathToEntry };
854
+ return { paths: ["/"] };
866
855
  const paths = /* @__PURE__ */ new Set();
867
856
  const getPaths = async (routes2, prefix = "") => {
868
857
  prefix = prefix.replace(/\/$/g, "");
@@ -877,32 +866,28 @@ async function routesToPaths(routes) {
877
866
  }
878
867
  }
879
868
  let path = route.path;
880
- path = handlePath(path, prefix, route.entry);
869
+ path = handlePath(path, prefix);
881
870
  if (route.getStaticPaths && isDynamicSegmentsRoute(path)) {
882
871
  const staticPaths = await route.getStaticPaths();
883
872
  for (let staticPath of staticPaths) {
884
- staticPath = handlePath(staticPath, prefix, route.entry);
873
+ staticPath = handlePath(staticPath, prefix);
885
874
  if (Array.isArray(route.children))
886
875
  await getPaths(route.children, staticPath);
887
876
  }
888
877
  }
889
- if (route.index)
890
- addEntry(prefix, route.entry);
878
+ if (route.index && !path) {
879
+ paths.add("/");
880
+ }
891
881
  if (Array.isArray(route.children))
892
882
  await getPaths(route.children, path);
893
883
  }
894
884
  };
895
885
  await getPaths(routes);
896
- return { paths: Array.from(paths), pathToEntry };
897
- function handlePath(path, prefix, entry) {
886
+ return { paths: Array.from(paths) };
887
+ function handlePath(path, prefix) {
898
888
  if (path != null) {
899
889
  path = prefix && !path.startsWith("/") ? `${prefix}${path ? `/${path}` : ""}` : path;
900
890
  paths.add(path);
901
- addEntry(path, entry);
902
- if (pathToEntry[prefix]) {
903
- const pathCopy = path;
904
- pathToEntry[prefix].forEach((entry2) => addEntry(pathCopy, entry2));
905
- }
906
891
  }
907
892
  return path;
908
893
  }
@@ -1096,18 +1081,10 @@ function createLink$1(href) {
1096
1081
  return `<link rel="stylesheet" href="${href}">`;
1097
1082
  }
1098
1083
 
1099
- function renderPreloadLinks(document, modules, ssrManifest) {
1084
+ function renderPreloadLinks(document, assets) {
1100
1085
  const seen = /* @__PURE__ */ new Set();
1101
- const preloadLinks = [];
1102
- Array.from(modules).forEach((id) => {
1103
- const files = ssrManifest[id] || [];
1104
- files.forEach((file) => {
1105
- if (!preloadLinks.includes(file))
1106
- preloadLinks.push(file);
1107
- });
1108
- });
1109
- if (preloadLinks) {
1110
- preloadLinks.forEach((file) => {
1086
+ if (assets) {
1087
+ assets.forEach((file) => {
1111
1088
  if (!seen.has(file)) {
1112
1089
  seen.add(file);
1113
1090
  renderPreloadLink(document, file);
@@ -1128,6 +1105,21 @@ function renderPreloadLink(document, file) {
1128
1105
  href: file,
1129
1106
  crossOrigin: ""
1130
1107
  });
1108
+ } else if (file.endsWith(".woff") || file.endsWith(".woff2") || file.endsWith(".ttf")) {
1109
+ appendLink(document, {
1110
+ rel: "preload",
1111
+ as: "font",
1112
+ type: "font/woff2",
1113
+ href: file,
1114
+ crossOrigin: ""
1115
+ });
1116
+ } else if (file.endsWith(".png") || file.endsWith(".jpg") || file.endsWith(".jpeg") || file.endsWith(".webp") || file.endsWith(".gif") || file.endsWith(".ico") || file.endsWith(".svg")) {
1117
+ appendLink(document, {
1118
+ rel: "preload",
1119
+ as: "image",
1120
+ href: file,
1121
+ crossOrigin: ""
1122
+ });
1131
1123
  }
1132
1124
  }
1133
1125
  function createLink(document) {
@@ -1147,6 +1139,69 @@ function appendLink(document, attrs) {
1147
1139
  document.head.appendChild(link);
1148
1140
  }
1149
1141
 
1142
+ const DYNAMIC_IMPORT_REGEX = /import\("([^)]+)"\)/g;
1143
+ function collectAssets({
1144
+ routes,
1145
+ locationArg,
1146
+ base,
1147
+ serverManifest,
1148
+ manifest,
1149
+ ssrManifest
1150
+ }) {
1151
+ const matches = reactRouterDom.matchRoutes([...routes], locationArg, base);
1152
+ const routeEntries = matches?.map((item) => item.route.entry).filter(Boolean) ?? [];
1153
+ const dynamicImports = /* @__PURE__ */ new Set();
1154
+ matches?.forEach((item) => {
1155
+ let lazyStr = "";
1156
+ if (item.route.lazy) {
1157
+ lazyStr += item.route.lazy.toString();
1158
+ }
1159
+ if (item.route.Component?._payload?._result) {
1160
+ lazyStr += item.route.Component._payload._result.toString();
1161
+ }
1162
+ const match = lazyStr.matchAll(DYNAMIC_IMPORT_REGEX);
1163
+ for (const m of match) {
1164
+ dynamicImports.add(m[1].split("/").at(-1) ?? "");
1165
+ }
1166
+ });
1167
+ const entries = /* @__PURE__ */ new Set();
1168
+ routeEntries.forEach((e) => entries.add(e));
1169
+ const manifestEntries = [...Object.entries(serverManifest)];
1170
+ dynamicImports.forEach((name) => {
1171
+ const result = manifestEntries.find(([_, value]) => value.file.endsWith(name));
1172
+ if (result) {
1173
+ entries.add(result[0]);
1174
+ }
1175
+ });
1176
+ const modules = collectModulesForEntries(manifest, entries);
1177
+ const assets = /* @__PURE__ */ new Set();
1178
+ Array.from(modules).forEach((id) => {
1179
+ const files = ssrManifest[id] || [];
1180
+ files.forEach((file) => {
1181
+ assets.add(file);
1182
+ });
1183
+ });
1184
+ return assets;
1185
+ }
1186
+ function collectModulesForEntries(manifest, entries) {
1187
+ const mods = /* @__PURE__ */ new Set();
1188
+ if (!entries)
1189
+ return mods;
1190
+ for (const entry of entries)
1191
+ collectModules(manifest, entry, mods);
1192
+ return mods;
1193
+ }
1194
+ function collectModules(manifest, entry, mods = /* @__PURE__ */ new Set()) {
1195
+ if (!entry)
1196
+ return mods;
1197
+ mods.add(entry);
1198
+ manifest[entry]?.dynamicImports?.forEach((item) => {
1199
+ collectModules(manifest, item, mods);
1200
+ });
1201
+ return mods;
1202
+ }
1203
+
1204
+ const dotVitedir = Number.parseInt(vite.version) >= 5 ? [".vite"] : [];
1150
1205
  function DefaultIncludedRoutes(paths, _routes) {
1151
1206
  return paths.filter((i) => !i.includes(":") && !i.includes("*"));
1152
1207
  }
@@ -1178,6 +1233,13 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1178
1233
  } = Object.assign({}, config.ssgOptions || {}, ssgOptions);
1179
1234
  if (fs__default.existsSync(ssgOut))
1180
1235
  await fs__default.remove(ssgOut);
1236
+ const clientLogger = vite.createLogger();
1237
+ const loggerWarn = clientLogger.warn;
1238
+ clientLogger.warn = (msg, options) => {
1239
+ if (msg.includes("vite:resolve") && msg.includes("externalized for browser compatibility"))
1240
+ return;
1241
+ loggerWarn(msg, options);
1242
+ };
1181
1243
  buildLog("Build for client...");
1182
1244
  await vite.build(vite.mergeConfig(viteConfig, {
1183
1245
  build: {
@@ -1195,6 +1257,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1195
1257
  }
1196
1258
  }
1197
1259
  },
1260
+ customLogger: clientLogger,
1198
1261
  mode: config.mode,
1199
1262
  ssr: { noExternal: ["vite-react-ssg"] }
1200
1263
  }));
@@ -1208,6 +1271,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1208
1271
  await vite.build(vite.mergeConfig(viteConfig, {
1209
1272
  build: {
1210
1273
  ssr: ssrEntry,
1274
+ manifest: true,
1211
1275
  outDir: ssgOut,
1212
1276
  minify: false,
1213
1277
  cssCodeSplit: false,
@@ -1227,11 +1291,12 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1227
1291
  const prefix = format === "esm" && process.platform === "win32" ? "file://" : "";
1228
1292
  const ext = format === "esm" ? ".mjs" : ".cjs";
1229
1293
  const serverEntry = node_path.join(prefix, ssgOut, node_path.parse(ssrEntry).name + ext);
1294
+ const serverManifest = JSON.parse(await fs__default.readFile(node_path.join(ssgOut, ...dotVitedir, "manifest.json"), "utf-8"));
1230
1295
  const _require = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (document.currentScript && document.currentScript.src || new URL('node.cjs', document.baseURI).href)));
1231
1296
  const { createRoot, includedRoutes: serverEntryIncludedRoutes } = format === "esm" ? await import(serverEntry) : _require(serverEntry);
1232
1297
  const includedRoutes = serverEntryIncludedRoutes || configIncludedRoutes;
1233
1298
  const { routes } = await createRoot(false);
1234
- const { paths, pathToEntry } = await routesToPaths(routes);
1299
+ const { paths } = await routesToPaths(routes);
1235
1300
  let routesPaths = includeAllRoutes ? paths : await includedRoutes(paths, routes || []);
1236
1301
  routesPaths = DefaultIncludedRoutes(routesPaths);
1237
1302
  routesPaths = Array.from(new Set(routesPaths));
@@ -1239,7 +1304,6 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1239
1304
  const critters = crittersOptions !== false ? await getCritters(outDir, { publicPath: configBase, ...crittersOptions }) : void 0;
1240
1305
  if (critters)
1241
1306
  console.log(`${kolorist.gray("[vite-react-ssg]")} ${kolorist.blue("Critical CSS generation enabled via `critters`")}`);
1242
- const dotVitedir = Number.parseInt(vite.version) >= 5 ? [".vite"] : [];
1243
1307
  const ssrManifest = JSON.parse(await fs__default.readFile(node_path.join(out, ...dotVitedir, "ssr-manifest.json"), "utf-8"));
1244
1308
  const manifest = JSON.parse(await fs__default.readFile(node_path.join(out, ...dotVitedir, "manifest.json"), "utf-8"));
1245
1309
  let indexHTML = await fs__default.readFile(node_path.join(out, "index.html"), "utf-8");
@@ -1256,6 +1320,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1256
1320
  const transformedIndexHTML = await onBeforePageRender?.(path, indexHTML, appCtx) || indexHTML;
1257
1321
  const fetchUrl = `${remixRouter.withTrailingSlash(base)}${remixRouter.removeLeadingSlash(path)}`;
1258
1322
  const request = createRequest(fetchUrl);
1323
+ const assets = !app ? collectAssets({ routes: [...routes2], locationArg: fetchUrl, base, serverManifest, manifest, ssrManifest }) : /* @__PURE__ */ new Set();
1259
1324
  const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await render(app ?? [...routes2], request, styleCollector, base);
1260
1325
  staticLoaderDataManifest[path] = routerContext?.loaderData;
1261
1326
  await triggerOnSSRAppRendered?.(path, appHTML, appCtx);
@@ -1269,8 +1334,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1269
1334
  initialState: null
1270
1335
  });
1271
1336
  const jsdom = new JSDOM.JSDOM(renderedHTML);
1272
- const modules = collectModulesForEntrys(manifest, pathToEntry?.[path]);
1273
- renderPreloadLinks(jsdom.window.document, modules, ssrManifest);
1337
+ renderPreloadLinks(jsdom.window.document, assets);
1274
1338
  const html = jsdom.serialize();
1275
1339
  let transformed = await onPageRendered?.(path, html, appCtx) || html;
1276
1340
  transformed = transformed.replace(SCRIPT_COMMENT_PLACEHOLDER, `window.__VITE_REACT_SSG_HASH__ = '${hash}'`);
@@ -1295,7 +1359,12 @@ ${err.stack}`);
1295
1359
  });
1296
1360
  }
1297
1361
  await queue.start().onIdle();
1298
- await fs__default.writeFile(node_path.join(out, `static-loader-data-manifest-${hash}.json`), JSON.stringify(staticLoaderDataManifest, null, 2));
1362
+ buildLog("Generating static loader data manifest...");
1363
+ const staticLoaderDataManifestString = JSON.stringify(staticLoaderDataManifest, null, 0);
1364
+ await fs__default.writeFile(node_path.join(out, `static-loader-data-manifest-${hash}.json`), staticLoaderDataManifestString);
1365
+ config.logger.info(
1366
+ `${kolorist.dim(`${outDir}/`)}${kolorist.cyan(`static-loader-data-manifest-${hash}.json`.padEnd(15, " "))} ${kolorist.dim(getSize(staticLoaderDataManifestString))}`
1367
+ );
1299
1368
  await fs__default.remove(node_path.join(root, ".vite-react-ssg-temp"));
1300
1369
  const pwaPlugin = config.plugins.find((i) => i.name === "vite-plugin-pwa")?.api;
1301
1370
  if (pwaPlugin && !pwaPlugin.disabled && pwaPlugin.generateSW) {
@@ -1339,23 +1408,6 @@ async function formatHtml(html, formatting) {
1339
1408
  }
1340
1409
  return html;
1341
1410
  }
1342
- function collectModulesForEntrys(manifest, entrys) {
1343
- const mods = /* @__PURE__ */ new Set();
1344
- if (!entrys)
1345
- return mods;
1346
- for (const entry of entrys)
1347
- collectModules(manifest, entry, mods);
1348
- return mods;
1349
- }
1350
- function collectModules(manifest, entry, mods = /* @__PURE__ */ new Set()) {
1351
- if (!entry)
1352
- return mods;
1353
- mods.add(entry);
1354
- manifest[entry]?.dynamicImports?.forEach((item) => {
1355
- collectModules(manifest, item, mods);
1356
- });
1357
- return mods;
1358
- }
1359
1411
 
1360
1412
  function invariant(value, message) {
1361
1413
  if (value === false || value === null || typeof value === "undefined") {
@@ -1471,11 +1523,10 @@ function ssrServerPlugin({
1471
1523
  const indexHTML = await server.transformIndexHtml(url, template);
1472
1524
  const transformedIndexHTML = await onBeforePageRender?.(url, indexHTML, appCtx) || indexHTML;
1473
1525
  const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1474
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await render(app ?? [...routes], fromNodeRequest(req), styleCollector, base);
1526
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag } = await render(app ?? [...routes], fromNodeRequest(req), styleCollector, base);
1475
1527
  metaAttributes.push(styleTag);
1476
- const matchesEntries = routerContext?.matches.map((match) => match.route.entry).filter((entry2) => !!entry2).map((entry2) => entry2[0] === "/" ? entry2 : `/${entry2}`) ?? [];
1477
1528
  const mods = await Promise.all(
1478
- [ssrEntry, entry, ...matchesEntries].map(async (entry2) => await server.moduleGraph.getModuleByUrl(entry2))
1529
+ [ssrEntry, entry].map(async (entry2) => await server.moduleGraph.getModuleByUrl(entry2))
1479
1530
  );
1480
1531
  const assetsUrls = /* @__PURE__ */ new Set();
1481
1532
  const collectAssets = async (mod) => {
@@ -1484,7 +1535,7 @@ function ssrServerPlugin({
1484
1535
  const { deps = [], dynamicDeps = [] } = mod?.ssrTransformResult;
1485
1536
  const allDeps = [...deps, ...dynamicDeps];
1486
1537
  for (const dep of allDeps) {
1487
- if (dep.endsWith(".css")) {
1538
+ if (dep.endsWith(".css") || dep.endsWith(".scss") || dep.endsWith(".sass") || dep.endsWith(".less")) {
1488
1539
  assetsUrls.add(dep);
1489
1540
  } else if (dep.endsWith(".ts") || dep.endsWith(".tsx")) {
1490
1541
  const depModule = await server.moduleGraph.getModuleByUrl(dep);
package/dist/node.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { InlineConfig } from 'vite';
2
- import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.870c683b.cjs';
2
+ import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.4d155759.cjs';
3
3
  import 'critters';
4
4
  import 'react';
5
5
  import 'react-router-dom';
package/dist/node.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { InlineConfig } from 'vite';
2
- import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.870c683b.mjs';
2
+ import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.4d155759.mjs';
3
3
  import 'critters';
4
4
  import 'react';
5
5
  import 'react-router-dom';
package/dist/node.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { InlineConfig } from 'vite';
2
- import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.870c683b.js';
2
+ import { b as ViteReactSSGOptions } from './shared/vite-react-ssg.4d155759.js';
3
3
  import 'critters';
4
4
  import 'react';
5
5
  import 'react-router-dom';
package/dist/node.mjs CHANGED
@@ -2,7 +2,7 @@ import { join, isAbsolute, parse, dirname } from 'node:path';
2
2
  import { createRequire } from 'node:module';
3
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, send, createServer } from 'vite';
5
+ import { resolveConfig, createLogger, build as build$1, mergeConfig, version as version$1, send, createServer } from 'vite';
6
6
  import { JSDOM } from 'jsdom';
7
7
  import { s as serializeState } from './shared/vite-react-ssg.579feabb.mjs';
8
8
  import { a as withTrailingSlash, r as removeLeadingSlash, c as convertRoutesToDataRoutes, j as joinUrlSegments } from './shared/vite-react-ssg.054e813a.mjs';
@@ -843,19 +843,8 @@ function getSize(str) {
843
843
  return `${(str.length / 1024).toFixed(2)} KiB`;
844
844
  }
845
845
  async function routesToPaths(routes) {
846
- const pathToEntry = {};
847
- function addEntry(path, entry) {
848
- if (!entry)
849
- return;
850
- if (entry[0] === "/")
851
- entry = entry.slice(1);
852
- if (pathToEntry[path])
853
- pathToEntry[path].add(entry);
854
- else
855
- pathToEntry[path] = /* @__PURE__ */ new Set([entry]);
856
- }
857
846
  if (!routes || routes.length === 0)
858
- return { paths: ["/"], pathToEntry };
847
+ return { paths: ["/"] };
859
848
  const paths = /* @__PURE__ */ new Set();
860
849
  const getPaths = async (routes2, prefix = "") => {
861
850
  prefix = prefix.replace(/\/$/g, "");
@@ -870,32 +859,28 @@ async function routesToPaths(routes) {
870
859
  }
871
860
  }
872
861
  let path = route.path;
873
- path = handlePath(path, prefix, route.entry);
862
+ path = handlePath(path, prefix);
874
863
  if (route.getStaticPaths && isDynamicSegmentsRoute(path)) {
875
864
  const staticPaths = await route.getStaticPaths();
876
865
  for (let staticPath of staticPaths) {
877
- staticPath = handlePath(staticPath, prefix, route.entry);
866
+ staticPath = handlePath(staticPath, prefix);
878
867
  if (Array.isArray(route.children))
879
868
  await getPaths(route.children, staticPath);
880
869
  }
881
870
  }
882
- if (route.index)
883
- addEntry(prefix, route.entry);
871
+ if (route.index && !path) {
872
+ paths.add("/");
873
+ }
884
874
  if (Array.isArray(route.children))
885
875
  await getPaths(route.children, path);
886
876
  }
887
877
  };
888
878
  await getPaths(routes);
889
- return { paths: Array.from(paths), pathToEntry };
890
- function handlePath(path, prefix, entry) {
879
+ return { paths: Array.from(paths) };
880
+ function handlePath(path, prefix) {
891
881
  if (path != null) {
892
882
  path = prefix && !path.startsWith("/") ? `${prefix}${path ? `/${path}` : ""}` : path;
893
883
  paths.add(path);
894
- addEntry(path, entry);
895
- if (pathToEntry[prefix]) {
896
- const pathCopy = path;
897
- pathToEntry[prefix].forEach((entry2) => addEntry(pathCopy, entry2));
898
- }
899
884
  }
900
885
  return path;
901
886
  }
@@ -1089,18 +1074,10 @@ function createLink$1(href) {
1089
1074
  return `<link rel="stylesheet" href="${href}">`;
1090
1075
  }
1091
1076
 
1092
- function renderPreloadLinks(document, modules, ssrManifest) {
1077
+ function renderPreloadLinks(document, assets) {
1093
1078
  const seen = /* @__PURE__ */ new Set();
1094
- const preloadLinks = [];
1095
- Array.from(modules).forEach((id) => {
1096
- const files = ssrManifest[id] || [];
1097
- files.forEach((file) => {
1098
- if (!preloadLinks.includes(file))
1099
- preloadLinks.push(file);
1100
- });
1101
- });
1102
- if (preloadLinks) {
1103
- preloadLinks.forEach((file) => {
1079
+ if (assets) {
1080
+ assets.forEach((file) => {
1104
1081
  if (!seen.has(file)) {
1105
1082
  seen.add(file);
1106
1083
  renderPreloadLink(document, file);
@@ -1121,6 +1098,21 @@ function renderPreloadLink(document, file) {
1121
1098
  href: file,
1122
1099
  crossOrigin: ""
1123
1100
  });
1101
+ } else if (file.endsWith(".woff") || file.endsWith(".woff2") || file.endsWith(".ttf")) {
1102
+ appendLink(document, {
1103
+ rel: "preload",
1104
+ as: "font",
1105
+ type: "font/woff2",
1106
+ href: file,
1107
+ crossOrigin: ""
1108
+ });
1109
+ } else if (file.endsWith(".png") || file.endsWith(".jpg") || file.endsWith(".jpeg") || file.endsWith(".webp") || file.endsWith(".gif") || file.endsWith(".ico") || file.endsWith(".svg")) {
1110
+ appendLink(document, {
1111
+ rel: "preload",
1112
+ as: "image",
1113
+ href: file,
1114
+ crossOrigin: ""
1115
+ });
1124
1116
  }
1125
1117
  }
1126
1118
  function createLink(document) {
@@ -1140,6 +1132,69 @@ function appendLink(document, attrs) {
1140
1132
  document.head.appendChild(link);
1141
1133
  }
1142
1134
 
1135
+ const DYNAMIC_IMPORT_REGEX = /import\("([^)]+)"\)/g;
1136
+ function collectAssets({
1137
+ routes,
1138
+ locationArg,
1139
+ base,
1140
+ serverManifest,
1141
+ manifest,
1142
+ ssrManifest
1143
+ }) {
1144
+ const matches = matchRoutes([...routes], locationArg, base);
1145
+ const routeEntries = matches?.map((item) => item.route.entry).filter(Boolean) ?? [];
1146
+ const dynamicImports = /* @__PURE__ */ new Set();
1147
+ matches?.forEach((item) => {
1148
+ let lazyStr = "";
1149
+ if (item.route.lazy) {
1150
+ lazyStr += item.route.lazy.toString();
1151
+ }
1152
+ if (item.route.Component?._payload?._result) {
1153
+ lazyStr += item.route.Component._payload._result.toString();
1154
+ }
1155
+ const match = lazyStr.matchAll(DYNAMIC_IMPORT_REGEX);
1156
+ for (const m of match) {
1157
+ dynamicImports.add(m[1].split("/").at(-1) ?? "");
1158
+ }
1159
+ });
1160
+ const entries = /* @__PURE__ */ new Set();
1161
+ routeEntries.forEach((e) => entries.add(e));
1162
+ const manifestEntries = [...Object.entries(serverManifest)];
1163
+ dynamicImports.forEach((name) => {
1164
+ const result = manifestEntries.find(([_, value]) => value.file.endsWith(name));
1165
+ if (result) {
1166
+ entries.add(result[0]);
1167
+ }
1168
+ });
1169
+ const modules = collectModulesForEntries(manifest, entries);
1170
+ const assets = /* @__PURE__ */ new Set();
1171
+ Array.from(modules).forEach((id) => {
1172
+ const files = ssrManifest[id] || [];
1173
+ files.forEach((file) => {
1174
+ assets.add(file);
1175
+ });
1176
+ });
1177
+ return assets;
1178
+ }
1179
+ function collectModulesForEntries(manifest, entries) {
1180
+ const mods = /* @__PURE__ */ new Set();
1181
+ if (!entries)
1182
+ return mods;
1183
+ for (const entry of entries)
1184
+ collectModules(manifest, entry, mods);
1185
+ return mods;
1186
+ }
1187
+ function collectModules(manifest, entry, mods = /* @__PURE__ */ new Set()) {
1188
+ if (!entry)
1189
+ return mods;
1190
+ mods.add(entry);
1191
+ manifest[entry]?.dynamicImports?.forEach((item) => {
1192
+ collectModules(manifest, item, mods);
1193
+ });
1194
+ return mods;
1195
+ }
1196
+
1197
+ const dotVitedir = Number.parseInt(version$1) >= 5 ? [".vite"] : [];
1143
1198
  function DefaultIncludedRoutes(paths, _routes) {
1144
1199
  return paths.filter((i) => !i.includes(":") && !i.includes("*"));
1145
1200
  }
@@ -1171,6 +1226,13 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1171
1226
  } = Object.assign({}, config.ssgOptions || {}, ssgOptions);
1172
1227
  if (fs.existsSync(ssgOut))
1173
1228
  await fs.remove(ssgOut);
1229
+ const clientLogger = createLogger();
1230
+ const loggerWarn = clientLogger.warn;
1231
+ clientLogger.warn = (msg, options) => {
1232
+ if (msg.includes("vite:resolve") && msg.includes("externalized for browser compatibility"))
1233
+ return;
1234
+ loggerWarn(msg, options);
1235
+ };
1174
1236
  buildLog("Build for client...");
1175
1237
  await build$1(mergeConfig(viteConfig, {
1176
1238
  build: {
@@ -1188,6 +1250,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1188
1250
  }
1189
1251
  }
1190
1252
  },
1253
+ customLogger: clientLogger,
1191
1254
  mode: config.mode,
1192
1255
  ssr: { noExternal: ["vite-react-ssg"] }
1193
1256
  }));
@@ -1201,6 +1264,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1201
1264
  await build$1(mergeConfig(viteConfig, {
1202
1265
  build: {
1203
1266
  ssr: ssrEntry,
1267
+ manifest: true,
1204
1268
  outDir: ssgOut,
1205
1269
  minify: false,
1206
1270
  cssCodeSplit: false,
@@ -1220,11 +1284,12 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1220
1284
  const prefix = format === "esm" && process.platform === "win32" ? "file://" : "";
1221
1285
  const ext = format === "esm" ? ".mjs" : ".cjs";
1222
1286
  const serverEntry = join(prefix, ssgOut, parse(ssrEntry).name + ext);
1287
+ const serverManifest = JSON.parse(await fs.readFile(join(ssgOut, ...dotVitedir, "manifest.json"), "utf-8"));
1223
1288
  const _require = createRequire(import.meta.url);
1224
1289
  const { createRoot, includedRoutes: serverEntryIncludedRoutes } = format === "esm" ? await import(serverEntry) : _require(serverEntry);
1225
1290
  const includedRoutes = serverEntryIncludedRoutes || configIncludedRoutes;
1226
1291
  const { routes } = await createRoot(false);
1227
- const { paths, pathToEntry } = await routesToPaths(routes);
1292
+ const { paths } = await routesToPaths(routes);
1228
1293
  let routesPaths = includeAllRoutes ? paths : await includedRoutes(paths, routes || []);
1229
1294
  routesPaths = DefaultIncludedRoutes(routesPaths);
1230
1295
  routesPaths = Array.from(new Set(routesPaths));
@@ -1232,7 +1297,6 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1232
1297
  const critters = crittersOptions !== false ? await getCritters(outDir, { publicPath: configBase, ...crittersOptions }) : void 0;
1233
1298
  if (critters)
1234
1299
  console.log(`${gray("[vite-react-ssg]")} ${blue("Critical CSS generation enabled via `critters`")}`);
1235
- const dotVitedir = Number.parseInt(version$1) >= 5 ? [".vite"] : [];
1236
1300
  const ssrManifest = JSON.parse(await fs.readFile(join(out, ...dotVitedir, "ssr-manifest.json"), "utf-8"));
1237
1301
  const manifest = JSON.parse(await fs.readFile(join(out, ...dotVitedir, "manifest.json"), "utf-8"));
1238
1302
  let indexHTML = await fs.readFile(join(out, "index.html"), "utf-8");
@@ -1249,6 +1313,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1249
1313
  const transformedIndexHTML = await onBeforePageRender?.(path, indexHTML, appCtx) || indexHTML;
1250
1314
  const fetchUrl = `${withTrailingSlash(base)}${removeLeadingSlash(path)}`;
1251
1315
  const request = createRequest(fetchUrl);
1316
+ const assets = !app ? collectAssets({ routes: [...routes2], locationArg: fetchUrl, base, serverManifest, manifest, ssrManifest }) : /* @__PURE__ */ new Set();
1252
1317
  const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await render(app ?? [...routes2], request, styleCollector, base);
1253
1318
  staticLoaderDataManifest[path] = routerContext?.loaderData;
1254
1319
  await triggerOnSSRAppRendered?.(path, appHTML, appCtx);
@@ -1262,8 +1327,7 @@ async function build(ssgOptions = {}, viteConfig = {}) {
1262
1327
  initialState: null
1263
1328
  });
1264
1329
  const jsdom = new JSDOM(renderedHTML);
1265
- const modules = collectModulesForEntrys(manifest, pathToEntry?.[path]);
1266
- renderPreloadLinks(jsdom.window.document, modules, ssrManifest);
1330
+ renderPreloadLinks(jsdom.window.document, assets);
1267
1331
  const html = jsdom.serialize();
1268
1332
  let transformed = await onPageRendered?.(path, html, appCtx) || html;
1269
1333
  transformed = transformed.replace(SCRIPT_COMMENT_PLACEHOLDER, `window.__VITE_REACT_SSG_HASH__ = '${hash}'`);
@@ -1288,7 +1352,12 @@ ${err.stack}`);
1288
1352
  });
1289
1353
  }
1290
1354
  await queue.start().onIdle();
1291
- await fs.writeFile(join(out, `static-loader-data-manifest-${hash}.json`), JSON.stringify(staticLoaderDataManifest, null, 2));
1355
+ buildLog("Generating static loader data manifest...");
1356
+ const staticLoaderDataManifestString = JSON.stringify(staticLoaderDataManifest, null, 0);
1357
+ await fs.writeFile(join(out, `static-loader-data-manifest-${hash}.json`), staticLoaderDataManifestString);
1358
+ config.logger.info(
1359
+ `${dim(`${outDir}/`)}${cyan(`static-loader-data-manifest-${hash}.json`.padEnd(15, " "))} ${dim(getSize(staticLoaderDataManifestString))}`
1360
+ );
1292
1361
  await fs.remove(join(root, ".vite-react-ssg-temp"));
1293
1362
  const pwaPlugin = config.plugins.find((i) => i.name === "vite-plugin-pwa")?.api;
1294
1363
  if (pwaPlugin && !pwaPlugin.disabled && pwaPlugin.generateSW) {
@@ -1332,23 +1401,6 @@ async function formatHtml(html, formatting) {
1332
1401
  }
1333
1402
  return html;
1334
1403
  }
1335
- function collectModulesForEntrys(manifest, entrys) {
1336
- const mods = /* @__PURE__ */ new Set();
1337
- if (!entrys)
1338
- return mods;
1339
- for (const entry of entrys)
1340
- collectModules(manifest, entry, mods);
1341
- return mods;
1342
- }
1343
- function collectModules(manifest, entry, mods = /* @__PURE__ */ new Set()) {
1344
- if (!entry)
1345
- return mods;
1346
- mods.add(entry);
1347
- manifest[entry]?.dynamicImports?.forEach((item) => {
1348
- collectModules(manifest, item, mods);
1349
- });
1350
- return mods;
1351
- }
1352
1404
 
1353
1405
  function invariant(value, message) {
1354
1406
  if (value === false || value === null || typeof value === "undefined") {
@@ -1464,11 +1516,10 @@ function ssrServerPlugin({
1464
1516
  const indexHTML = await server.transformIndexHtml(url, template);
1465
1517
  const transformedIndexHTML = await onBeforePageRender?.(url, indexHTML, appCtx) || indexHTML;
1466
1518
  const styleCollector = getStyleCollector ? await getStyleCollector() : null;
1467
- const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag, routerContext } = await render(app ?? [...routes], fromNodeRequest(req), styleCollector, base);
1519
+ const { appHTML, bodyAttributes, htmlAttributes, metaAttributes, styleTag } = await render(app ?? [...routes], fromNodeRequest(req), styleCollector, base);
1468
1520
  metaAttributes.push(styleTag);
1469
- const matchesEntries = routerContext?.matches.map((match) => match.route.entry).filter((entry2) => !!entry2).map((entry2) => entry2[0] === "/" ? entry2 : `/${entry2}`) ?? [];
1470
1521
  const mods = await Promise.all(
1471
- [ssrEntry, entry, ...matchesEntries].map(async (entry2) => await server.moduleGraph.getModuleByUrl(entry2))
1522
+ [ssrEntry, entry].map(async (entry2) => await server.moduleGraph.getModuleByUrl(entry2))
1472
1523
  );
1473
1524
  const assetsUrls = /* @__PURE__ */ new Set();
1474
1525
  const collectAssets = async (mod) => {
@@ -1477,7 +1528,7 @@ function ssrServerPlugin({
1477
1528
  const { deps = [], dynamicDeps = [] } = mod?.ssrTransformResult;
1478
1529
  const allDeps = [...deps, ...dynamicDeps];
1479
1530
  for (const dep of allDeps) {
1480
- if (dep.endsWith(".css")) {
1531
+ if (dep.endsWith(".css") || dep.endsWith(".scss") || dep.endsWith(".sass") || dep.endsWith(".less")) {
1481
1532
  assetsUrls.add(dep);
1482
1533
  } else if (dep.endsWith(".ts") || dep.endsWith(".tsx")) {
1483
1534
  const depModule = await server.moduleGraph.getModuleByUrl(dep);
@@ -140,6 +140,8 @@ interface CommonRouteOptions {
140
140
  /**
141
141
  * Used to obtain static resources through manifest
142
142
  *
143
+ * **You are not required to use this field. It is only necessary when "prehydration style loss" occurs.**
144
+ *
143
145
  * @example `src/pages/home.tsx`
144
146
  */
145
147
  entry?: string;
@@ -140,6 +140,8 @@ interface CommonRouteOptions {
140
140
  /**
141
141
  * Used to obtain static resources through manifest
142
142
  *
143
+ * **You are not required to use this field. It is only necessary when "prehydration style loss" occurs.**
144
+ *
143
145
  * @example `src/pages/home.tsx`
144
146
  */
145
147
  entry?: string;
@@ -140,6 +140,8 @@ interface CommonRouteOptions {
140
140
  /**
141
141
  * Used to obtain static resources through manifest
142
142
  *
143
+ * **You are not required to use this field. It is only necessary when "prehydration style loss" occurs.**
144
+ *
143
145
  * @example `src/pages/home.tsx`
144
146
  */
145
147
  entry?: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "vite-react-ssg",
3
3
  "type": "module",
4
- "version": "0.7.0-beta.1",
4
+ "version": "0.7.0",
5
5
  "packageManager": "pnpm@9.4.0",
6
6
  "description": "",
7
7
  "author": "Riri <Daydreamerriri@outlook.com>",