@finesoft/front 0.1.45 → 0.1.47

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/index.mjs CHANGED
@@ -1,5 +1,4 @@
1
- import { a as dynamicImport, c as injectSSRContent, i as createInternalFetch, n as createSSRApp, o as SSR_PLACEHOLDERS, s as injectCSRShell } from "./app-FO_8yAY7.mjs";
2
- import { n as parseAcceptLanguage } from "./locale-iP9ABD4H.mjs";
1
+ import { n as parseAcceptLanguage } from "./locale-CvU-U6aP.mjs";
3
2
  import { Hono } from "hono";
4
3
  //#region ../core/src/actions/types.ts
5
4
  /**
@@ -1457,6 +1456,30 @@ function createSSRRender(config) {
1457
1456
  });
1458
1457
  }
1459
1458
  //#endregion
1459
+ //#region ../ssr/src/inject.ts
1460
+ /**
1461
+ * injectSSRContent — 将 SSR 渲染结果注入 HTML 模板
1462
+ */
1463
+ /** SSR HTML 模板占位符常量 */
1464
+ const SSR_PLACEHOLDERS = {
1465
+ LANG: "<!--ssr-lang-->",
1466
+ HEAD: "<!--ssr-head-->",
1467
+ BODY: "<!--ssr-body-->",
1468
+ DATA: "<!--ssr-data-->"
1469
+ };
1470
+ function injectSSRContent(options) {
1471
+ const { template, locale, head, css, html, serializedData } = options;
1472
+ const cssTag = css ? `<style>${css}</style>` : "";
1473
+ return template.replace(SSR_PLACEHOLDERS.LANG, locale).replace(SSR_PLACEHOLDERS.HEAD, `${head}\n${cssTag}`).replace(SSR_PLACEHOLDERS.BODY, html).replace(SSR_PLACEHOLDERS.DATA, `<script id="serialized-server-data" type="application/json">${serializedData}<\/script>`);
1474
+ }
1475
+ /**
1476
+ * CSR 空壳注入 — 只替换 lang,清空 body/head/data 占位符
1477
+ * 用于 renderMode === "csr" 的路由
1478
+ */
1479
+ function injectCSRShell(template, locale) {
1480
+ return template.replace(SSR_PLACEHOLDERS.LANG, locale).replace(SSR_PLACEHOLDERS.HEAD, "").replace(SSR_PLACEHOLDERS.BODY, "").replace(SSR_PLACEHOLDERS.DATA, "");
1481
+ }
1482
+ //#endregion
1460
1483
  //#region ../ssr/src/server-data.ts
1461
1484
  const HTML_REPLACEMENTS = {
1462
1485
  "<": "\\u003C",
@@ -1470,6 +1493,29 @@ function serializeServerData(data) {
1470
1493
  return JSON.stringify(data).replace(HTML_ESCAPE_PATTERN, (match) => HTML_REPLACEMENTS[match] ?? match);
1471
1494
  }
1472
1495
  //#endregion
1496
+ //#region ../server/src/dynamic-import.ts
1497
+ /** Cache for stable (non-file://) modules — avoids redundant resolution. */
1498
+ const moduleCache = /* @__PURE__ */ new Map();
1499
+ const rawImport = new Function("u", "return import(u)");
1500
+ const debugEnabled = typeof process !== "undefined" && process.env?.FINESOFT_DEBUG === "1";
1501
+ function logDebug(msg) {
1502
+ if (debugEnabled) console.debug(`[finesoft:dynamic-import] ${msg}`);
1503
+ }
1504
+ async function dynamicImport(specifier) {
1505
+ const cacheable = !specifier.startsWith("file:") && !specifier.startsWith("/");
1506
+ if (cacheable) {
1507
+ const cached = moduleCache.get(specifier);
1508
+ if (cached) {
1509
+ logDebug(`cache hit → ${specifier}`);
1510
+ return cached;
1511
+ }
1512
+ }
1513
+ logDebug(`importing → ${specifier}`);
1514
+ const mod = await rawImport(specifier);
1515
+ if (cacheable) moduleCache.set(specifier, mod);
1516
+ return mod;
1517
+ }
1518
+ //#endregion
1473
1519
  //#region ../server/src/proxy.ts
1474
1520
  /**
1475
1521
  * 校验代理路径,防止 SSRF(协议相对 URL 绕过)。
@@ -1584,6 +1630,30 @@ const BUILD_TOOL_EXTERNALS = [
1584
1630
  "lightningcss"
1585
1631
  ];
1586
1632
  /**
1633
+ * Common Node.js built-in modules. Listed explicitly so that Rolldown's
1634
+ * vite-resolve plugin does not emit "Automatically externalized" warnings.
1635
+ */
1636
+ const NODE_BUILTINS = [
1637
+ "node:async_hooks",
1638
+ "node:buffer",
1639
+ "node:crypto",
1640
+ "node:fs",
1641
+ "node:http",
1642
+ "node:http2",
1643
+ "node:module",
1644
+ "node:net",
1645
+ "node:os",
1646
+ "node:path",
1647
+ "node:stream",
1648
+ "node:url",
1649
+ "node:util",
1650
+ "node:zlib",
1651
+ "crypto",
1652
+ "http",
1653
+ "http2",
1654
+ "stream"
1655
+ ];
1656
+ /**
1587
1657
  * 生成 SSR serverless/edge 入口源码
1588
1658
  *
1589
1659
  * 内联 parseAcceptLanguage / injectSSR 以避免
@@ -1738,13 +1808,13 @@ async function buildBundle(ctx, opts) {
1738
1808
  build: {
1739
1809
  ssr: opts.entry,
1740
1810
  outDir: opts.outDir,
1741
- emptyOutDir: true,
1811
+ emptyOutDir: opts.emptyOutDir ?? true,
1742
1812
  target: opts.target ?? "node18",
1743
1813
  rollupOptions: { output: { entryFileNames: opts.fileName ?? "index.mjs" } }
1744
1814
  },
1745
1815
  ssr: {
1746
1816
  noExternal: opts.noExternal !== false,
1747
- external: opts.external ?? BUILD_TOOL_EXTERNALS
1817
+ external: [...opts.external ?? BUILD_TOOL_EXTERNALS, ...NODE_BUILTINS]
1748
1818
  },
1749
1819
  resolve: ctx.resolvedResolve,
1750
1820
  css: ctx.resolvedCss
@@ -1765,10 +1835,7 @@ function copyStaticAssets(ctx, destDir, opts) {
1765
1835
  */
1766
1836
  async function prerenderRoutes(ctx) {
1767
1837
  const { fs, path, root, vite } = ctx;
1768
- const { pathToFileURL } = await import(
1769
- /* @vite-ignore */
1770
- "node:url"
1771
- );
1838
+ const { pathToFileURL } = await dynamicImport("node:url");
1772
1839
  const routesExport = ctx.bootstrapEntry ?? "src/lib/bootstrap.ts";
1773
1840
  let routes = [];
1774
1841
  if (fs.existsSync(path.resolve(root, routesExport))) {
@@ -1998,7 +2065,8 @@ serve({ fetch: app.fetch, port }, (info) => {
1998
2065
  await buildBundle(ctx, {
1999
2066
  entry: ".node-entry.tmp.mjs",
2000
2067
  outDir: path.resolve(root, "dist/server"),
2001
- target: "node18"
2068
+ target: "node18",
2069
+ emptyOutDir: false
2002
2070
  });
2003
2071
  } finally {
2004
2072
  fs.rmSync(tempEntry, { force: true });
@@ -2038,10 +2106,7 @@ function staticAdapter(opts = {}) {
2038
2106
  force: true
2039
2107
  });
2040
2108
  fs.mkdirSync(outputDir, { recursive: true });
2041
- const { pathToFileURL } = await import(
2042
- /* @vite-ignore */
2043
- "node:url"
2044
- );
2109
+ const { pathToFileURL } = await dynamicImport("node:url");
2045
2110
  const ssrPath = pathToFileURL(path.resolve(root, "dist/server/ssr.js")).href;
2046
2111
  const ssrModule = await dynamicImport(ssrPath);
2047
2112
  ctx.copyStaticAssets(outputDir, { excludeHtml: true });
@@ -2079,10 +2144,7 @@ async function extractRoutesWithModes(ctx, opts) {
2079
2144
  const paths = [];
2080
2145
  const defs = [];
2081
2146
  try {
2082
- const { pathToFileURL } = await import(
2083
- /* @vite-ignore */
2084
- "node:url"
2085
- );
2147
+ const { pathToFileURL } = await dynamicImport("node:url");
2086
2148
  await ctx.vite.build({
2087
2149
  root: ctx.root,
2088
2150
  build: {
@@ -2288,7 +2350,138 @@ function detectPlatform() {
2288
2350
  return "node";
2289
2351
  }
2290
2352
  //#endregion
2353
+ //#region ../server/src/internal-fetch.ts
2354
+ /**
2355
+ * createInternalFetch — SSR 内部路由回环 fetch 包装器
2356
+ *
2357
+ * 将相对路径(/api/…)请求转为 Hono app.fetch 内存调用,
2358
+ * 绝对 URL 和非字符串 input 走 globalThis.fetch(真实网络)。
2359
+ *
2360
+ * 递归深度保护采用请求头传递:每次 SSR 回环在请求头中写入深度值,
2361
+ * SSR catch-all 读取深度判断是否超限。对比闭包计数器方案:
2362
+ * - 并发安全:无共享可变状态
2363
+ * - 跨渲染准确:深度随请求在 Hono 路由链中传递
2364
+ */
2365
+ const SSR_DEPTH_HEADER = "x-ssr-depth";
2366
+ /**
2367
+ * 创建请求级 internal fetch
2368
+ *
2369
+ * @param appFetch - Hono app.fetch(父级路由)
2370
+ * @param depth - 当前 SSR 深度(由 catch-all handler 从请求头读取后 +1 传入)
2371
+ */
2372
+ function createInternalFetch(appFetch, depth = 1) {
2373
+ return ((input, init) => {
2374
+ if (typeof input === "string" && input.startsWith("/")) {
2375
+ const request = new Request(`http://localhost${input}`, init);
2376
+ request.headers.set(SSR_DEPTH_HEADER, String(depth));
2377
+ return Promise.resolve(appFetch(request));
2378
+ }
2379
+ return globalThis.fetch(input, init);
2380
+ });
2381
+ }
2382
+ //#endregion
2383
+ //#region ../server/src/app.ts
2384
+ /**
2385
+ * createSSRApp — 创建 Hono SSR 应用
2386
+ *
2387
+ * 提供 SSR 通配路由,读取模板、加载 SSR 模块、渲染。
2388
+ * 应用层可在此之上追加自定义路由(API 代理等)。
2389
+ */
2390
+ /**
2391
+ * 匹配 Vite 配置级别的 renderMode 覆盖。
2392
+ * 精确路径优先,然后 glob 模式。
2393
+ */
2394
+ function matchRenderModeOverride(url, renderModes) {
2395
+ if (!renderModes) return null;
2396
+ const path = url.split("?")[0];
2397
+ if (renderModes[path]) return renderModes[path];
2398
+ for (const [pattern, mode] of Object.entries(renderModes)) if (pattern.includes("*")) {
2399
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
2400
+ if (new RegExp("^" + escaped.replace(/\*/g, ".*") + "$").test(path)) return mode;
2401
+ }
2402
+ return null;
2403
+ }
2404
+ function createSSRApp(options) {
2405
+ const { root, vite, isProduction, ssrEntryPath = "/src/ssr.ts", ssrProductionModule, supportedLocales, defaultLocale, parentFetch, renderModes } = options;
2406
+ const app = new Hono();
2407
+ /** ISR 内存缓存(prerender 路由首次请求后缓存,LRU 驱逐) */
2408
+ const ISR_CACHE_MAX = 1e3;
2409
+ const isrCache = /* @__PURE__ */ new Map();
2410
+ function isrSet(key, val) {
2411
+ if (isrCache.size >= ISR_CACHE_MAX) {
2412
+ const first = isrCache.keys().next().value;
2413
+ if (first !== void 0) isrCache.delete(first);
2414
+ }
2415
+ isrCache.set(key, val);
2416
+ }
2417
+ /** 生产环境模板缓存(模板不变,避免每请求重复读盘) */
2418
+ let templateCache;
2419
+ async function readTemplate(url) {
2420
+ if (!isProduction && vite) {
2421
+ const { readFileSync } = await dynamicImport("node:fs");
2422
+ const raw = readFileSync((await dynamicImport("node:path")).resolve(root, "index.html"), "utf-8");
2423
+ return vite.transformIndexHtml(url, raw);
2424
+ }
2425
+ if (templateCache) return templateCache;
2426
+ if (typeof globalThis.Deno !== "undefined") {
2427
+ const base = import.meta.url;
2428
+ templateCache = globalThis.Deno.readTextFileSync(new URL("../dist/client/index.html", base));
2429
+ return templateCache;
2430
+ }
2431
+ const { readFileSync } = await dynamicImport("node:fs");
2432
+ templateCache = readFileSync((await dynamicImport("node:path")).resolve(root, "dist/client/index.html"), "utf-8");
2433
+ return templateCache;
2434
+ }
2435
+ async function loadSSRModule() {
2436
+ if (!isProduction && vite) return await vite.ssrLoadModule(ssrEntryPath);
2437
+ if (ssrProductionModule) return dynamicImport(ssrProductionModule);
2438
+ const path = await dynamicImport("node:path");
2439
+ const { pathToFileURL } = await dynamicImport("node:url");
2440
+ const absPath = pathToFileURL(path.resolve(root, "dist/server/ssr.js")).href;
2441
+ return dynamicImport(absPath);
2442
+ }
2443
+ app.get("*", async (c) => {
2444
+ const ssrDepth = parseInt(c.req.header("x-ssr-depth") ?? "0", 10);
2445
+ if (ssrDepth >= 5) return c.text("SSR recursion loop detected", 508);
2446
+ const url = c.req.path + (c.req.url.includes("?") ? "?" + c.req.url.split("?")[1] : "");
2447
+ try {
2448
+ const template = await readTemplate(url);
2449
+ const { render, serializeServerData } = await loadSSRModule();
2450
+ const locale = parseAcceptLanguage(c.req.header("accept-language"), supportedLocales, defaultLocale);
2451
+ const overrideMode = matchRenderModeOverride(url, renderModes);
2452
+ if (overrideMode === "csr") return c.html(injectCSRShell(template, locale));
2453
+ const cacheKey = `${locale}:${url}`;
2454
+ const cached = isrCache.get(cacheKey);
2455
+ if (cached) return c.html(cached);
2456
+ const requestFetch = parentFetch ? createInternalFetch(parentFetch, ssrDepth + 1) : void 0;
2457
+ const ssrContext = { request: c.req.raw };
2458
+ if (requestFetch) ssrContext.fetch = requestFetch;
2459
+ const { html: appHtml, head, css, serverData, renderMode, redirect: middlewareRedirect } = await render(url, locale, ssrContext);
2460
+ if (middlewareRedirect) return c.redirect(middlewareRedirect.url, middlewareRedirect.status);
2461
+ if (renderMode === "csr") return c.html(injectCSRShell(template, locale));
2462
+ const finalHtml = injectSSRContent({
2463
+ template,
2464
+ locale,
2465
+ head,
2466
+ css,
2467
+ html: appHtml,
2468
+ serializedData: serializeServerData(serverData)
2469
+ });
2470
+ if (renderMode === "prerender" || overrideMode === "prerender") isrSet(cacheKey, finalHtml);
2471
+ return c.html(finalHtml);
2472
+ } catch (e) {
2473
+ if (!isProduction && vite) vite.ssrFixStacktrace(e);
2474
+ console.error("[SSR Error]", e);
2475
+ return c.text("Internal Server Error", 500);
2476
+ }
2477
+ });
2478
+ return app;
2479
+ }
2480
+ //#endregion
2291
2481
  //#region ../server/src/runtime.ts
2482
+ /**
2483
+ * runtime — 运行时检测 + 项目根路径推导
2484
+ */
2292
2485
  /** 检测当前运行时环境 */
2293
2486
  function detectRuntime() {
2294
2487
  return {
@@ -2310,14 +2503,8 @@ async function resolveRoot(importMetaUrl, levelsUp = 0) {
2310
2503
  for (let i = 0; i < levelsUp; i++) url = new URL("..", url);
2311
2504
  return url.pathname;
2312
2505
  }
2313
- const path = await import(
2314
- /* @vite-ignore */
2315
- "node:path"
2316
- );
2317
- const { fileURLToPath } = await import(
2318
- /* @vite-ignore */
2319
- "node:url"
2320
- );
2506
+ const path = await dynamicImport("node:path");
2507
+ const { fileURLToPath } = await dynamicImport("node:url");
2321
2508
  let dir = path.normalize(path.dirname(fileURLToPath(importMetaUrl)));
2322
2509
  for (let i = 0; i < levelsUp; i++) dir = path.resolve(dir, "..");
2323
2510
  return dir;
@@ -2348,24 +2535,15 @@ async function startServer(options) {
2348
2535
  if (!isProduction) {
2349
2536
  let devVite = vite;
2350
2537
  if (!devVite) {
2351
- const { createServer: createViteServer } = await import(
2352
- /* @vite-ignore */
2353
- "vite"
2354
- );
2538
+ const { createServer: createViteServer } = await dynamicImport("vite");
2355
2539
  devVite = await createViteServer({
2356
2540
  root,
2357
2541
  server: { middlewareMode: true },
2358
2542
  appType: "custom"
2359
2543
  });
2360
2544
  }
2361
- const { getRequestListener } = await import(
2362
- /* @vite-ignore */
2363
- "@hono/node-server"
2364
- );
2365
- const { createServer } = await import(
2366
- /* @vite-ignore */
2367
- "node:http"
2368
- );
2545
+ const { getRequestListener } = await dynamicImport("@hono/node-server");
2546
+ const { createServer } = await dynamicImport("node:http");
2369
2547
  const listener = getRequestListener(app.fetch);
2370
2548
  createServer((req, res) => {
2371
2549
  devVite.middlewares(req, res, () => listener(req, res));
@@ -2376,14 +2554,8 @@ async function startServer(options) {
2376
2554
  }
2377
2555
  if (isDeno) globalThis.Deno.serve({ port }, app.fetch);
2378
2556
  else if (isBun) {} else {
2379
- const { serveStatic } = await import(
2380
- /* @vite-ignore */
2381
- "@hono/node-server/serve-static"
2382
- );
2383
- const path = await import(
2384
- /* @vite-ignore */
2385
- "node:path"
2386
- );
2557
+ const { serveStatic } = await dynamicImport("@hono/node-server/serve-static");
2558
+ const path = await dynamicImport("node:path");
2387
2559
  const prodApp = new Hono();
2388
2560
  const clientDir = path.resolve(root, "dist/client");
2389
2561
  prodApp.use("/*", serveStatic({
@@ -2391,10 +2563,7 @@ async function startServer(options) {
2391
2563
  rewriteRequestPath: (path) => path.endsWith("/") ? "/__nosuchfile__" : path
2392
2564
  }));
2393
2565
  prodApp.route("/", app);
2394
- const { serve } = await import(
2395
- /* @vite-ignore */
2396
- "@hono/node-server"
2397
- );
2566
+ const { serve } = await dynamicImport("@hono/node-server");
2398
2567
  serve({
2399
2568
  fetch: prodApp.fetch,
2400
2569
  port
@@ -2427,28 +2596,16 @@ async function startServer(options) {
2427
2596
  async function createServer(config = {}) {
2428
2597
  const { root: rootOverride, locales, defaultLocale, port = Number(process.env.PORT) || 3e3, setup, proxies, ssr } = config;
2429
2598
  const root = rootOverride ?? process.cwd();
2430
- const { existsSync } = await import(
2431
- /* @vite-ignore */
2432
- "node:fs"
2433
- );
2434
- const envPath = (await import(
2435
- /* @vite-ignore */
2436
- "node:path"
2437
- )).resolve(root, ".env");
2599
+ const { existsSync } = await dynamicImport("node:fs");
2600
+ const envPath = (await dynamicImport("node:path")).resolve(root, ".env");
2438
2601
  if (existsSync(envPath)) try {
2439
- const { config: dotenvConfig } = await import(
2440
- /* @vite-ignore */
2441
- "dotenv"
2442
- );
2602
+ const { config: dotenvConfig } = await dynamicImport("dotenv");
2443
2603
  dotenvConfig({ path: envPath });
2444
2604
  } catch {}
2445
2605
  const runtime = detectRuntime();
2446
2606
  let vite;
2447
2607
  if (!runtime.isProduction && !runtime.isVercel) {
2448
- const { createServer: createViteServer } = await import(
2449
- /* @vite-ignore */
2450
- "vite"
2451
- );
2608
+ const { createServer: createViteServer } = await dynamicImport("vite");
2452
2609
  vite = await createViteServer({
2453
2610
  root,
2454
2611
  server: { middlewareMode: true },
@@ -2526,9 +2683,9 @@ function finesoftFrontViteConfig(options = {}) {
2526
2683
  const CSS_EXTENSIONS = /\.(css|scss|less|sass|styl|stylus|pcss|postcss)($|\?)/;
2527
2684
  return {
2528
2685
  name: "finesoft-front",
2529
- config(userConfig, env) {
2686
+ config(userConfig) {
2530
2687
  const overrides = { appType: "custom" };
2531
- if (env.command === "build" && !process.env.__FINESOFT_SUB_BUILD__) overrides.build = { outDir: userConfig.build?.outDir ?? "dist/client" };
2688
+ if (!process.env.__FINESOFT_SUB_BUILD__) overrides.build = { outDir: userConfig.build?.outDir ?? "dist/client" };
2532
2689
  return overrides;
2533
2690
  },
2534
2691
  configResolved(config) {
@@ -2578,15 +2735,8 @@ function finesoftFrontViteConfig(options = {}) {
2578
2735
  },
2579
2736
  configureServer(server) {
2580
2737
  return async () => {
2581
- const { Hono: HonoClass } = await import(
2582
- /* @vite-ignore */
2583
- "hono"
2584
- );
2585
- const { createSSRApp } = await import("./app-FO_8yAY7.mjs").then((n) => n.t);
2586
- const { getRequestListener } = await import(
2587
- /* @vite-ignore */
2588
- "@hono/node-server"
2589
- );
2738
+ const { Hono: HonoClass } = await dynamicImport("hono");
2739
+ const { getRequestListener } = await dynamicImport("@hono/node-server");
2590
2740
  const app = new HonoClass();
2591
2741
  if (options.proxies?.length) registerProxyRoutes(app, options.proxies);
2592
2742
  if (typeof options.setup === "function") await options.setup(app);
@@ -2613,27 +2763,12 @@ function finesoftFrontViteConfig(options = {}) {
2613
2763
  },
2614
2764
  configurePreviewServer(server) {
2615
2765
  return async () => {
2616
- const { readFileSync } = await import(
2617
- /* @vite-ignore */
2618
- "node:fs"
2619
- );
2620
- const path = await import(
2621
- /* @vite-ignore */
2622
- "node:path"
2623
- );
2624
- const { pathToFileURL } = await import(
2625
- /* @vite-ignore */
2626
- "node:url"
2627
- );
2628
- const { Hono: HonoClass } = await import(
2629
- /* @vite-ignore */
2630
- "hono"
2631
- );
2632
- const { parseAcceptLanguage } = await import("./locale-iP9ABD4H.mjs").then((n) => n.t);
2633
- const { getRequestListener } = await import(
2634
- /* @vite-ignore */
2635
- "@hono/node-server"
2636
- );
2766
+ const { readFileSync } = await dynamicImport("node:fs");
2767
+ const path = await dynamicImport("node:path");
2768
+ const { pathToFileURL } = await dynamicImport("node:url");
2769
+ const { Hono: HonoClass } = await dynamicImport("hono");
2770
+ const { parseAcceptLanguage } = await import("./locale-CvU-U6aP.mjs").then((n) => n.t);
2771
+ const { getRequestListener } = await dynamicImport("@hono/node-server");
2637
2772
  const app = new HonoClass();
2638
2773
  const isrCache = /* @__PURE__ */ new Map();
2639
2774
  if (options.proxies?.length) registerProxyRoutes(app, options.proxies);
@@ -2687,18 +2822,9 @@ function finesoftFrontViteConfig(options = {}) {
2687
2822
  if (resolvedCommand !== "build") return;
2688
2823
  process.env.__FINESOFT_SUB_BUILD__ = "1";
2689
2824
  try {
2690
- const vite = await import(
2691
- /* @vite-ignore */
2692
- "vite"
2693
- );
2694
- const fs = await import(
2695
- /* @vite-ignore */
2696
- "node:fs"
2697
- );
2698
- const path = await import(
2699
- /* @vite-ignore */
2700
- "node:path"
2701
- );
2825
+ const vite = await dynamicImport("vite");
2826
+ const fs = await dynamicImport("node:fs");
2827
+ const path = await dynamicImport("node:path");
2702
2828
  console.log("\n Building SSR bundle...\n");
2703
2829
  await vite.build({
2704
2830
  root,
@@ -2706,6 +2832,7 @@ function finesoftFrontViteConfig(options = {}) {
2706
2832
  ssr: ssrEntry,
2707
2833
  outDir: "dist/server"
2708
2834
  },
2835
+ ssr: { external: NODE_BUILTINS },
2709
2836
  resolve: resolvedResolve,
2710
2837
  css: resolvedCss
2711
2838
  });