vinext 1.0.0-beta.12 → 1.0.0-beta.13

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.
Files changed (132) hide show
  1. package/README.md +39 -12
  2. package/dist/build/action-owner-manifest.js +23 -5
  3. package/dist/build/lifecycle.d.ts +42 -0
  4. package/dist/build/lifecycle.js +246 -0
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +0 -3
  7. package/dist/build/pages-client-assets-module.js +1 -13
  8. package/dist/build/precompress.js +1 -1
  9. package/dist/build/prerender-paths.d.ts +1 -1
  10. package/dist/build/prerender-paths.js +6 -6
  11. package/dist/build/prerender-server-pool.js +1 -1
  12. package/dist/build/prerender.d.ts +1 -1
  13. package/dist/build/prerender.js +5 -5
  14. package/dist/build/preview-credentials.d.ts +1 -1
  15. package/dist/build/preview-credentials.js +2 -2
  16. package/dist/build/report.js +1 -1
  17. package/dist/build/run-prerender.d.ts +2 -2
  18. package/dist/build/run-prerender.js +5 -5
  19. package/dist/build/standalone.js +2 -2
  20. package/dist/cli-args.d.ts +5 -13
  21. package/dist/cli-args.js +2 -45
  22. package/dist/cli-dev-config.d.ts +6 -2
  23. package/dist/cli-dev-config.js +160 -3
  24. package/dist/cli.js +104 -439
  25. package/dist/config/config-matchers.js +1 -1
  26. package/dist/config/next-config.d.ts +2 -2
  27. package/dist/config/next-config.js +5 -5
  28. package/dist/config/prerender.d.ts +3 -0
  29. package/dist/config/prerender.js +8 -2
  30. package/dist/entries/app-browser-entry.js +1 -1
  31. package/dist/entries/app-rsc-entry.js +1 -1
  32. package/dist/entries/pages-client-entry.d.ts +1 -0
  33. package/dist/entries/pages-client-entry.js +17 -2
  34. package/dist/index.d.ts +6 -8
  35. package/dist/index.js +262 -101
  36. package/dist/init-cloudflare.d.ts +3 -2
  37. package/dist/init-cloudflare.js +117 -5
  38. package/dist/init-platform.d.ts +2 -0
  39. package/dist/init-platform.js +9 -3
  40. package/dist/init.d.ts +7 -5
  41. package/dist/init.js +41 -22
  42. package/dist/plugins/dynamic-preload-metadata.js +1 -1
  43. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  44. package/dist/plugins/fonts.js +1 -1
  45. package/dist/plugins/ignore-dynamic-requests.js +1 -1
  46. package/dist/plugins/import-meta-url.js +1 -1
  47. package/dist/plugins/instrumentation-client.js +1 -1
  48. package/dist/plugins/og-assets.js +32 -13
  49. package/dist/plugins/og-harfbuzz.d.ts +24 -0
  50. package/dist/plugins/og-harfbuzz.js +260 -0
  51. package/dist/plugins/optimize-imports.js +1 -1
  52. package/dist/plugins/require-condition-resolution.js +2 -2
  53. package/dist/plugins/require-context.js +2 -2
  54. package/dist/plugins/typeof-window.js +1 -1
  55. package/dist/plugins/use-cache-callable.d.ts +0 -2
  56. package/dist/plugins/use-cache-callable.js +8 -16
  57. package/dist/plugins/worker-image-imports.js +1 -1
  58. package/dist/routing/app-route-graph.js +1 -1
  59. package/dist/routing/app-router.js +1 -1
  60. package/dist/routing/pages-router.js +1 -1
  61. package/dist/server/app-action-forwarding.js +1 -1
  62. package/dist/server/app-browser-error.js +1 -1
  63. package/dist/server/app-elements-wire.js +2 -2
  64. package/dist/server/app-middleware.js +1 -1
  65. package/dist/server/app-optimistic-routing.js +1 -1
  66. package/dist/server/app-page-dispatch.js +1 -1
  67. package/dist/server/app-page-element-builder.js +3 -2
  68. package/dist/server/app-page-probe.js +3 -3
  69. package/dist/server/app-request-stage-independent-entry.js +2 -2
  70. package/dist/server/app-route-handler-dispatch.js +1 -1
  71. package/dist/server/app-route-handler-runtime.js +1 -1
  72. package/dist/server/app-router-entry.js +2 -2
  73. package/dist/server/app-rsc-handler.d.ts +1 -1
  74. package/dist/server/app-rsc-handler.js +4 -4
  75. package/dist/server/app-rsc-response-stage.js +1 -1
  76. package/dist/server/app-rsc-route-matching.js +1 -1
  77. package/dist/server/app-server-action-execution.js +4 -4
  78. package/dist/server/artifact-compatibility.js +1 -1
  79. package/dist/server/client-reuse-manifest.js +1 -1
  80. package/dist/server/dev-lockfile.d.ts +1 -1
  81. package/dist/server/dev-lockfile.js +4 -1
  82. package/dist/server/dev-server.d.ts +1 -1
  83. package/dist/server/dev-server.js +28 -6
  84. package/dist/server/dev-stack-sourcemap.js +1 -1
  85. package/dist/server/isr-cache.js +1 -1
  86. package/dist/server/metadata-route-response.js +8 -0
  87. package/dist/server/middleware-runtime.js +3 -3
  88. package/dist/server/pages-data-route.js +1 -1
  89. package/dist/server/pages-dev-hydration.d.ts +6 -0
  90. package/dist/server/pages-dev-hydration.js +19 -7
  91. package/dist/server/pages-page-data.js +2 -2
  92. package/dist/server/pages-page-handler.js +1 -1
  93. package/dist/server/pages-page-response.js +1 -1
  94. package/dist/server/pages-request-pipeline.js +3 -3
  95. package/dist/server/pages-request-stage-entry.js +3 -3
  96. package/dist/server/pages-revalidate.js +1 -1
  97. package/dist/server/prerender-route-params.js +1 -1
  98. package/dist/server/prod-server.js +7 -7
  99. package/dist/server/request-pipeline.js +2 -2
  100. package/dist/server/socket-error-backstop.js +1 -1
  101. package/dist/shims/cache-callable-runtime.d.ts +38 -0
  102. package/dist/shims/cache-callable-runtime.js +162 -11
  103. package/dist/shims/cache-runtime.d.ts +6 -8
  104. package/dist/shims/cache-runtime.js +82 -22
  105. package/dist/shims/font-local.js +1 -1
  106. package/dist/shims/form.js +1 -1
  107. package/dist/shims/headers.js +2 -2
  108. package/dist/shims/internal/app-page-props-cache-key.d.ts +29 -0
  109. package/dist/shims/internal/app-page-props-cache-key.js +53 -1
  110. package/dist/shims/internal/format-url-object.d.ts +7 -0
  111. package/dist/shims/internal/format-url-object.js +53 -0
  112. package/dist/shims/internal/normalize-router-href.d.ts +15 -0
  113. package/dist/shims/internal/normalize-router-href.js +41 -0
  114. package/dist/shims/internal/pages-data-target.d.ts +4 -1
  115. package/dist/shims/internal/pages-data-target.js +28 -35
  116. package/dist/shims/internal/route-pattern-for-warning.d.ts +2 -2
  117. package/dist/shims/internal/route-pattern-for-warning.js +3 -3
  118. package/dist/shims/link.js +31 -92
  119. package/dist/shims/metadata.js +5 -4
  120. package/dist/shims/navigation.js +2 -2
  121. package/dist/shims/router-state.js +1 -1
  122. package/dist/shims/router.d.ts +8 -7
  123. package/dist/shims/router.js +312 -148
  124. package/dist/shims/server.js +3 -3
  125. package/dist/utils/built-asset-url.js +1 -1
  126. package/dist/utils/project.d.ts +1 -11
  127. package/dist/utils/project.js +19 -28
  128. package/dist/utils/react-version.d.ts +3 -1
  129. package/dist/utils/react-version.js +19 -1
  130. package/dist/utils/vite-cli-invocation.d.ts +21 -0
  131. package/dist/utils/vite-cli-invocation.js +144 -0
  132. package/package.json +10 -2
package/README.md CHANGED
@@ -80,28 +80,39 @@ npm install react-server-dom-webpack
80
80
  npm install -D @vitejs/plugin-rsc
81
81
  ```
82
82
 
83
- Replace `next` with `vinext` in your scripts:
83
+ Add a Vite config:
84
+
85
+ ```ts
86
+ import { defineConfig } from "vite";
87
+ import vinext from "vinext";
88
+
89
+ export default defineConfig({
90
+ plugins: [vinext()],
91
+ });
92
+ ```
93
+
94
+ Then use Vite for development and builds:
84
95
 
85
96
  ```json
86
97
  {
87
98
  "scripts": {
88
- "dev": "vinext dev",
89
- "build": "vinext build",
99
+ "dev": "vite dev",
100
+ "build": "vite build",
90
101
  "start": "vinext start"
91
102
  }
92
103
  }
93
104
  ```
94
105
 
95
106
  ```bash
96
- vinext dev # Development server with HMR
97
- vinext build # Production build
107
+ npx vite dev # Development server with HMR
108
+ npx vite build # Production build
98
109
  npx @vinext/cloudflare deploy # Build and deploy to Cloudflare Workers
99
110
  ```
100
111
 
101
112
  With Vite+, use `vpx @vinext/cloudflare deploy`, or
102
113
  `vp exec vinext-cloudflare deploy` when running the locally installed bin.
103
114
 
104
- vinext auto-detects your `app/` or `pages/` directory, loads `next.config.js`, and configures Vite automatically. No `vite.config.ts` required for basic usage.
115
+ The `vinext()` plugin auto-detects your `app/` or `pages/` directory and loads `next.config.js`.
105
116
 
106
117
  Your existing `pages/`, `app/`, `next.config.js`, and `public/` directories work as-is. Run `vinext check` first to scan for known compatibility issues, or use `vinext init` to [automate the full migration](#migrating-an-existing-nextjs-project).
107
118
 
@@ -109,8 +120,8 @@ Your existing `pages/`, `app/`, `next.config.js`, and `public/` directories work
109
120
 
110
121
  | Command | Description |
111
122
  | ---------------------------------- | ----------------------------------------------------------------------- |
112
- | `vinext dev` | Start dev server with HMR |
113
- | `vinext build` | Production build (multi-environment for App Router: RSC + SSR + client) |
123
+ | `vite dev` | Start dev server with HMR |
124
+ | `vite build` | Production build (multi-environment for App Router: RSC + SSR + client) |
114
125
  | `vinext start` | Start local production server for testing |
115
126
  | `npx @vinext/cloudflare deploy` | Build and deploy to Cloudflare Workers |
116
127
  | `vp exec vinext-cloudflare deploy` | Build and deploy to Cloudflare Workers with Vite+ |
@@ -118,7 +129,13 @@ Your existing `pages/`, `app/`, `next.config.js`, and `public/` directories work
118
129
  | `vinext check` | Scan your Next.js app for compatibility issues before migrating |
119
130
  | `vinext lint` | Delegate to eslint or oxlint |
120
131
 
121
- Options: `-p / --port <port>`, `-H / --hostname <host>`, `--turbopack` (accepted, no-op).
132
+ `vinext dev` and `vinext build` remain as thin aliases for the project-local Vite commands.
133
+ They require a Vite config; if one is missing, run `vinext init`. Vite owns their options,
134
+ output, and exit behavior. For older configured projects, the aliases still preload dotenv
135
+ before Vite evaluates the config and add `"type": "module"` (renaming known CommonJS config
136
+ files to `.cjs`) when an unambiguous default Vite config requires the ESM migration. An explicit
137
+ `"type": "commonjs"` is never changed. Direct `vite dev` and `vite build` do not perform these
138
+ wrapper compatibility steps.
122
139
 
123
140
  `@vinext/cloudflare deploy` options: `--preview`, `--env <name>`, `--name <name>`, `--skip-build`, `--dry-run`, `--experimental-traffic-aware-warm-cache`.
124
141
 
@@ -127,7 +144,7 @@ user which target they want, then pass `--platform=cloudflare` or `--platform=no
127
144
 
128
145
  Other options: `--port <port>` (default: 3001), `--skip-check`, `--force`.
129
146
 
130
- If your `next.config.*` sets `output: "standalone"`, `vinext build` emits a self-hosting bundle at `dist/standalone/`. Start it with:
147
+ If your `next.config.*` sets `output: "standalone"`, `vite build` emits a self-hosting bundle at `dist/standalone/`. Start it with:
131
148
 
132
149
  ```bash
133
150
  node dist/standalone/server.js
@@ -643,6 +660,15 @@ One caveat: modules whose JSX is lowered earlier in the pipeline are not memoize
643
660
 
644
661
  vinext automatically loads dotenv files for `dev`, `build`, `start`, and `deploy`.
645
662
 
663
+ Vite evaluates all static config imports before plugin hooks, regardless of import order.
664
+ `vinext dev` and `vinext build` preload dotenv from the project root before handing off to Vite,
665
+ preserving the old CLI's config-time behavior. Direct `vite dev` and `vite build` do not. For
666
+ config-time values that work with either command, use Vite's
667
+ [`loadEnv(mode, process.cwd(), "")`](https://vite.dev/config/#using-environment-variables-in-config)
668
+ in a config factory and read its returned values rather than relying on `process.env` in a static
669
+ import. The empty prefix includes server-only variables; use your custom `envDir` in place of
670
+ `process.cwd()` if you have one.
671
+
646
672
  Load order matches Next.js (highest priority first):
647
673
 
648
674
  1. Existing `process.env` values (shell/CI)
@@ -653,8 +679,9 @@ Load order matches Next.js (highest priority first):
653
679
 
654
680
  Modes:
655
681
 
656
- - `vinext dev` uses `development`
657
- - `vinext build`, `vinext start`, and `@vinext/cloudflare deploy` use `production`
682
+ - `vite dev` uses `development`
683
+ - `vite build`, `vinext start`, and `@vinext/cloudflare deploy` use `production`
684
+ - `vinext dev` and `vinext build` use the corresponding mode, including `--mode` overrides
658
685
 
659
686
  Variable expansion (`$VAR` / `${VAR}`) is supported.
660
687
 
@@ -39,6 +39,17 @@ function actionOwnerRouteEntryIds(route) {
39
39
  ])
40
40
  ].filter((value) => typeof value === "string");
41
41
  }
42
+ function memoizeModuleInfo(getModuleInfo) {
43
+ const cache = /* @__PURE__ */ new Map();
44
+ return (id) => {
45
+ let info = cache.get(id);
46
+ if (info === void 0) {
47
+ info = getModuleInfo(id);
48
+ cache.set(id, info);
49
+ }
50
+ return info;
51
+ };
52
+ }
42
53
  function collectReachableActionReferences(options) {
43
54
  const canonicalizeModuleId = options.canonicalizeModuleId ?? ((id) => id);
44
55
  const clientReferenceImportIds = /* @__PURE__ */ new Set();
@@ -62,17 +73,18 @@ function collectReachableActionReferences(options) {
62
73
  };
63
74
  }
64
75
  function collectRscActionReachability(options) {
76
+ const getModuleInfo = memoizeModuleInfo(options.getModuleInfo);
65
77
  const routeReachability = new Map(options.routes.map((route) => [route.pattern, collectReachableActionReferences({
66
78
  canonicalizeModuleId: options.canonicalizeModuleId,
67
79
  clientReferenceMetaMap: options.clientReferenceMetaMap,
68
- getModuleInfo: options.getModuleInfo,
80
+ getModuleInfo,
69
81
  roots: actionOwnerRouteEntryIds(route),
70
82
  serverReferenceMetaMap: options.serverReferenceMetaMap
71
83
  })]));
72
84
  if (options.sharedRoots?.length) routeReachability.set("*", collectReachableActionReferences({
73
85
  canonicalizeModuleId: options.canonicalizeModuleId,
74
86
  clientReferenceMetaMap: options.clientReferenceMetaMap,
75
- getModuleInfo: options.getModuleInfo,
87
+ getModuleInfo,
76
88
  roots: options.sharedRoots,
77
89
  serverReferenceMetaMap: options.serverReferenceMetaMap
78
90
  }));
@@ -80,21 +92,27 @@ function collectRscActionReachability(options) {
80
92
  }
81
93
  async function resolveClientReferenceImportIds(options) {
82
94
  const canonicalizeModuleId = options.canonicalizeModuleId ?? ((id) => id);
95
+ const resolvedIdsByImportId = /* @__PURE__ */ new Map();
83
96
  for (const reachability of options.routeReachability.values()) {
84
97
  const resolvedImportIds = /* @__PURE__ */ new Set();
85
98
  for (const importId of reachability.clientReferenceImportIds) {
86
- const resolvedId = await options.resolveId(importId) ?? importId;
87
- resolvedImportIds.add(canonicalizeModuleId(resolvedId));
99
+ let resolvedId = resolvedIdsByImportId.get(importId);
100
+ if (resolvedId === void 0) {
101
+ resolvedId = canonicalizeModuleId(await options.resolveId(importId) ?? importId);
102
+ resolvedIdsByImportId.set(importId, resolvedId);
103
+ }
104
+ resolvedImportIds.add(resolvedId);
88
105
  }
89
106
  reachability.clientReferenceImportIds = resolvedImportIds;
90
107
  }
91
108
  }
92
109
  function addClientActionReachability(options) {
110
+ const getModuleInfo = memoizeModuleInfo(options.getModuleInfo);
93
111
  for (const reachability of options.routeReachability.values()) {
94
112
  const clientReachability = collectReachableActionReferences({
95
113
  canonicalizeModuleId: options.canonicalizeModuleId,
96
114
  clientReferenceMetaMap: options.clientReferenceMetaMap,
97
- getModuleInfo: options.getModuleInfo,
115
+ getModuleInfo,
98
116
  roots: [...reachability.clientReferenceImportIds],
99
117
  serverReferenceMetaMap: options.serverReferenceMetaMap
100
118
  });
@@ -0,0 +1,42 @@
1
+ import { VinextCacheConfig } from "../cache/cache-adapters-virtual.js";
2
+ import { ResolvedVinextPrerenderConfig, VinextRouteRootConfig } from "../config/prerender.js";
3
+ import { ResolvedNextConfig } from "../config/next-config.js";
4
+ import { runWithPreviewBuildCredentials } from "./preview-credentials.js";
5
+ import { Plugin, PluginOption, ResolvedConfig, UserConfig, ViteBuilder } from "vite";
6
+ //#region src/build/lifecycle.d.ts
7
+ export type BuildLifecycleContext = {
8
+ cacheConfig: VinextCacheConfig | null;
9
+ configNodeEnv?: string;
10
+ createPagesOnlyPlugins: (pagesClientAssetsModule: string | null) => PluginOption[];
11
+ emptyOutDir?: boolean;
12
+ hasAppDir: boolean;
13
+ hasPagesDir: boolean;
14
+ nextConfig: ResolvedNextConfig;
15
+ prerenderAll?: boolean;
16
+ prerenderConfig: ResolvedVinextPrerenderConfig | null;
17
+ prerenderConcurrency?: number;
18
+ prerenderSecret: string;
19
+ previewBuildCredentials?: Parameters<typeof runWithPreviewBuildCredentials>[1];
20
+ revalidateSecret: string;
21
+ root: string;
22
+ routeRootConfig: VinextRouteRootConfig | null;
23
+ rscBuildIdentity?: string;
24
+ rscCompatibilityId?: string;
25
+ deferPostBuild?: boolean;
26
+ skipHybridPagesBundle?: boolean;
27
+ };
28
+ export declare const VINEXT_BUILD_LIFECYCLE_CONFIG = "__vinextBuildLifecycle";
29
+ export type BuildLifecycleInvocation = {
30
+ onComplete?: () => void;
31
+ };
32
+ export declare function prepareBuildOutput(context: BuildLifecycleContext, emptyOutDir?: boolean | undefined): void;
33
+ export declare function createBuildLifecyclePlugins(options: {
34
+ createContext: () => BuildLifecycleContext;
35
+ isEnabled: (builder: ViteBuilder) => boolean;
36
+ onComplete?: () => void;
37
+ onPrepare?: () => void;
38
+ shouldDeferPostBuild?: () => boolean;
39
+ shouldPrepare: (config: UserConfig | ResolvedConfig) => boolean;
40
+ shouldBuildPlainPages: () => boolean;
41
+ }): Plugin[];
42
+ //#endregion
@@ -0,0 +1,246 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
+ import { flattenPluginOptions } from "../utils/plugin-options.js";
3
+ import { hasBuildIdentityResponseHeader, hasUncachedRequestRouting, hasVerbatimResponseVary, isConfiguredCdnResponsePolicyHeader } from "../cache/cache-adapters-virtual.js";
4
+ import { formatVinextPrerenderLabel, resolveVinextPrerenderDecision } from "../config/prerender.js";
5
+ import { resolveVinextPackageRoot } from "../utils/vinext-root.js";
6
+ import { cleanBuildOutput } from "./clean-output.js";
7
+ import { PAGES_CLIENT_ASSETS_MODULE } from "./pages-client-assets-module.js";
8
+ import { runWithPreviewBuildCredentials } from "./preview-credentials.js";
9
+ import { createRequire } from "node:module";
10
+ import fs from "node:fs";
11
+ import { pathToFileURL } from "node:url";
12
+ //#region src/build/lifecycle.ts
13
+ const VINEXT_BUILD_LIFECYCLE_CONFIG = "__vinextBuildLifecycle";
14
+ async function loadProjectViteApi(root) {
15
+ let vitePath;
16
+ try {
17
+ vitePath = createRequire(path.join(root, "package.json")).resolve("vite");
18
+ } catch {
19
+ vitePath = "vite";
20
+ }
21
+ return await (vitePath === "vite" ? import(vitePath) : import(pathToFileURL(vitePath).href));
22
+ }
23
+ function restoreEnvironment(previous) {
24
+ for (const [key, value] of previous) if (value === void 0) delete process.env[key];
25
+ else process.env[key] = value;
26
+ }
27
+ async function withEnvironment(values, callback) {
28
+ const previous = /* @__PURE__ */ new Map();
29
+ for (const [key, value] of Object.entries(values)) {
30
+ previous.set(key, process.env[key]);
31
+ if (value === void 0) delete process.env[key];
32
+ else process.env[key] = value;
33
+ }
34
+ try {
35
+ return await callback();
36
+ } finally {
37
+ restoreEnvironment(previous);
38
+ }
39
+ }
40
+ function isInternalBuildPlugin(plugin) {
41
+ return plugin.name.startsWith("vinext:") || plugin.name.startsWith("vite:react") || plugin.name === "rsc" || plugin.name.startsWith("rsc:") || plugin.name === "vite-rsc-load-module-dev-proxy" || plugin.name.startsWith("vite-plugin-cloudflare");
42
+ }
43
+ async function loadHybridUserConfig(root, mode, configFile, configNodeEnv) {
44
+ if (!configFile) return {};
45
+ const vite = await loadProjectViteApi(root);
46
+ const load = () => vite.loadConfigFromFile({
47
+ command: "build",
48
+ mode,
49
+ isSsrBuild: true
50
+ }, configFile, root);
51
+ const loaded = configNodeEnv ? await withEnvironment({ NODE_ENV: configNodeEnv }, load) : await load();
52
+ if (!loaded) return {};
53
+ const plugins = await flattenPluginOptions(loaded.config.plugins);
54
+ return {
55
+ ...loaded.config,
56
+ plugins: plugins.filter((plugin) => Boolean(plugin) && typeof plugin.name === "string" && !isInternalBuildPlugin(plugin)).map((plugin) => ({
57
+ ...plugin,
58
+ buildApp: void 0
59
+ }))
60
+ };
61
+ }
62
+ async function buildHybridPagesBundle(builder, context) {
63
+ const vite = await loadProjectViteApi(context.root);
64
+ const userConfig = await loadHybridUserConfig(context.root, builder.config.mode, builder.config.configFile, context.configNodeEnv);
65
+ if (builder.config.logLevel !== "silent") console.log(" Building Pages Router server (hybrid)...");
66
+ const userSsrEnvironment = userConfig.environments?.ssr;
67
+ const { build: _userSsrBuild, ...pagesEnvironment } = userSsrEnvironment ?? {};
68
+ const mergedBuild = vite.mergeConfig(userConfig.build ?? {}, userSsrEnvironment?.build ?? {});
69
+ const userOutput = mergedBuild.rolldownOptions?.output;
70
+ const appAssetsPath = path.resolve(context.root, builder.environments.rsc?.config.build.outDir ?? "dist/server", PAGES_CLIENT_ASSETS_MODULE);
71
+ const pagesClientAssetsModule = fs.existsSync(appAssetsPath) ? fs.readFileSync(appAssetsPath, "utf8") : null;
72
+ const pagesBuild = {
73
+ ...mergedBuild,
74
+ outDir: "dist/server",
75
+ emptyOutDir: false,
76
+ manifest: false,
77
+ ssr: "virtual:vinext-server-entry",
78
+ rolldownOptions: {
79
+ ...mergedBuild.rolldownOptions,
80
+ output: Array.isArray(userOutput) ? userOutput.map((output) => ({
81
+ ...output,
82
+ entryFileNames: "entry.js"
83
+ })) : {
84
+ ...userOutput,
85
+ entryFileNames: "entry.js"
86
+ }
87
+ }
88
+ };
89
+ const pagesConfig = {
90
+ ...userConfig,
91
+ root: context.root,
92
+ mode: builder.config.mode,
93
+ configFile: false,
94
+ plugins: [...userConfig.plugins ?? [], ...context.createPagesOnlyPlugins(pagesClientAssetsModule)],
95
+ builder: {
96
+ ...userConfig.builder,
97
+ buildApp: async (pagesBuilder) => {
98
+ await pagesBuilder.build(pagesBuilder.environments.ssr);
99
+ }
100
+ },
101
+ environments: { ssr: {
102
+ ...pagesEnvironment,
103
+ consumer: "server"
104
+ } },
105
+ resolve: {
106
+ ...userConfig.resolve,
107
+ dedupe: [
108
+ ...userConfig.resolve?.dedupe ?? [],
109
+ "react",
110
+ "react-dom",
111
+ "react/jsx-runtime",
112
+ "react/jsx-dev-runtime"
113
+ ]
114
+ },
115
+ customLogger: builder.config.logger,
116
+ build: pagesBuild
117
+ };
118
+ const createPagesBuilder = () => vite.createBuilder(pagesConfig);
119
+ await (context.configNodeEnv ? await withEnvironment({ NODE_ENV: context.configNodeEnv }, createPagesBuilder) : await createPagesBuilder()).buildApp();
120
+ }
121
+ function checkStandaloneBuildPrerequisite(context) {
122
+ if (!context.deferPostBuild && context.nextConfig.output === "standalone") {
123
+ const vinextDistDir = path.join(resolveVinextPackageRoot(), "dist");
124
+ if (!fs.existsSync(vinextDistDir)) throw new Error(`vinext dist/ not found at ${vinextDistDir}. Build the vinext package before creating standalone output.`);
125
+ }
126
+ }
127
+ function prepareBuildOutput(context, emptyOutDir = context.emptyOutDir) {
128
+ checkStandaloneBuildPrerequisite(context);
129
+ cleanBuildOutput({
130
+ root: context.root,
131
+ outDir: path.resolve(context.root, "dist"),
132
+ emptyOutDir
133
+ });
134
+ }
135
+ async function finalizeBuild(builder, context) {
136
+ if (context.hasAppDir && context.hasPagesDir && !context.skipHybridPagesBundle) await withEnvironment({
137
+ __VINEXT_SHARED_BUILD_ID: context.nextConfig.buildId,
138
+ __VINEXT_SHARED_PRERENDER_SECRET: context.prerenderSecret,
139
+ __VINEXT_SHARED_REVALIDATE_SECRET: context.revalidateSecret,
140
+ __VINEXT_SHARED_RSC_BUILD_IDENTITY: context.rscBuildIdentity,
141
+ __VINEXT_SHARED_RSC_COMPATIBILITY_ID: context.rscCompatibilityId
142
+ }, () => runWithPreviewBuildCredentials(() => buildHybridPagesBundle(builder, context), context.previewBuildCredentials));
143
+ if (context.deferPostBuild) return;
144
+ if (context.nextConfig.output === "standalone") {
145
+ const { emitStandaloneOutput } = await import("./standalone.js");
146
+ const standalone = emitStandaloneOutput({
147
+ root: context.root,
148
+ outDir: path.resolve(context.root, "dist")
149
+ });
150
+ console.log(` Generated standalone output in ${path.relative(context.root, standalone.standaloneDir)}/`);
151
+ console.log(" Start it with: node dist/standalone/server.js\n");
152
+ return;
153
+ }
154
+ const prerenderDecision = resolveVinextPrerenderDecision({
155
+ prerenderAllFlag: context.prerenderAll,
156
+ vinextPrerenderConfig: context.prerenderConfig,
157
+ nextOutput: context.nextConfig.output
158
+ });
159
+ let prerenderResult;
160
+ if (prerenderDecision) {
161
+ if (context.nextConfig.enablePrerenderSourceMaps) {
162
+ process.setSourceMapsEnabled(true);
163
+ Error.stackTraceLimit = Math.max(Error.stackTraceLimit, 50);
164
+ }
165
+ console.log(` ${formatVinextPrerenderLabel(prerenderDecision)}`);
166
+ const [{ emitPrerenderPathManifest }, { runPrerender }] = await Promise.all([import("./prerender-paths.js"), import("./run-prerender.js")]);
167
+ prerenderResult = await runPrerender({
168
+ root: context.root,
169
+ concurrency: context.prerenderConcurrency,
170
+ nextConfig: context.nextConfig,
171
+ routeRootConfig: context.routeRootConfig
172
+ });
173
+ await emitPrerenderPathManifest({
174
+ root: context.root,
175
+ nextConfig: context.nextConfig,
176
+ buildIdentity: hasBuildIdentityResponseHeader(context.cacheConfig) ? "response-header" : void 0,
177
+ responseVary: hasVerbatimResponseVary(context.cacheConfig) ? "verbatim" : void 0,
178
+ requestRouting: hasUncachedRequestRouting(context.cacheConfig) ? "uncached-stage" : void 0,
179
+ isResponsePolicyHeader: (name) => isConfiguredCdnResponsePolicyHeader(context.cacheConfig, name),
180
+ routeRootConfig: context.routeRootConfig
181
+ });
182
+ }
183
+ const { printBuildReport } = await import("./report.js");
184
+ await printBuildReport({
185
+ root: context.root,
186
+ pageExtensions: context.nextConfig.pageExtensions,
187
+ prerenderResult: prerenderResult ?? void 0
188
+ });
189
+ console.log("\n Build complete.\n");
190
+ }
191
+ function createBuildLifecyclePlugins(options) {
192
+ let outputPrepared = false;
193
+ const createContext = () => ({
194
+ ...options.createContext(),
195
+ deferPostBuild: options.shouldDeferPostBuild?.()
196
+ });
197
+ const finalizePlugin = {
198
+ name: "vinext:build-lifecycle-finalize",
199
+ apply: "build",
200
+ enforce: "post",
201
+ configResolved: {
202
+ order: "post",
203
+ handler(config) {
204
+ const plugins = config.plugins;
205
+ const index = plugins.indexOf(finalizePlugin);
206
+ if (index !== -1 && index !== plugins.length - 1) plugins.push(...plugins.splice(index, 1));
207
+ }
208
+ },
209
+ buildApp: {
210
+ order: "post",
211
+ async handler(builder) {
212
+ if (!options.isEnabled(builder)) return;
213
+ await finalizeBuild(builder, createContext());
214
+ options.onComplete?.();
215
+ }
216
+ }
217
+ };
218
+ return [{
219
+ name: "vinext:build-lifecycle-prepare",
220
+ apply: "build",
221
+ configResolved: {
222
+ order: "pre",
223
+ handler(config) {
224
+ if (outputPrepared || !options.shouldPrepare(config)) return;
225
+ const context = createContext();
226
+ if (config.build.emptyOutDir === false) context.emptyOutDir = false;
227
+ checkStandaloneBuildPrerequisite(context);
228
+ options.onPrepare?.();
229
+ prepareBuildOutput(context);
230
+ outputPrepared = true;
231
+ }
232
+ },
233
+ buildApp: {
234
+ order: "pre",
235
+ async handler(builder) {
236
+ if (!options.isEnabled(builder) || !options.shouldBuildPlainPages()) return;
237
+ for (const name of ["client", "ssr"]) {
238
+ const environment = builder.environments[name];
239
+ if (environment && !environment.isBuilt) await builder.build(environment);
240
+ }
241
+ }
242
+ }
243
+ }, finalizePlugin];
244
+ }
245
+ //#endregion
246
+ export { VINEXT_BUILD_LIFECYCLE_CONFIG, createBuildLifecyclePlugins, prepareBuildOutput };
@@ -1,6 +1,6 @@
1
+ import { appRouter } from "../routing/app-router.js";
1
2
  import { apiRouter, pagesRouter } from "../routing/pages-router.js";
2
3
  import { buildReportRows } from "./report.js";
3
- import { appRouter } from "../routing/app-router.js";
4
4
  //#region src/build/nitro-route-rules.ts
5
5
  /**
6
6
  * Scans the filesystem for route files and generates Nitro `routeRules` for ISR routes.
@@ -3,7 +3,4 @@ import { PagesClientAssets } from "../server/pages-client-assets.js";
3
3
  export declare const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
4
4
  export declare function buildPagesClientAssetsModule(assets: PagesClientAssets): string;
5
5
  export declare function writePagesClientAssetsModuleIfMissing(outputDir: string, moduleSource: string): void;
6
- export declare function setPagesClientAssetsBuildMetadata(buildSession: string, moduleSource: string): void;
7
- export declare function takePagesClientAssetsBuildMetadata(buildSession: string): string | null;
8
- export declare function clearPagesClientAssetsBuildMetadata(buildSession: string): void;
9
6
  //#endregion
@@ -2,7 +2,6 @@ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import fs from "node:fs";
3
3
  //#region src/build/pages-client-assets-module.ts
4
4
  const PAGES_CLIENT_ASSETS_MODULE = "vinext-client-assets.js";
5
- const pagesClientAssetsByBuildSession = /* @__PURE__ */ new Map();
6
5
  function buildPagesClientAssetsModule(assets) {
7
6
  return `export default ${JSON.stringify(assets)};\n`;
8
7
  }
@@ -12,16 +11,5 @@ function writePagesClientAssetsModuleIfMissing(outputDir, moduleSource) {
12
11
  fs.mkdirSync(outputDir, { recursive: true });
13
12
  fs.writeFileSync(outputPath, moduleSource);
14
13
  }
15
- function setPagesClientAssetsBuildMetadata(buildSession, moduleSource) {
16
- pagesClientAssetsByBuildSession.set(buildSession, moduleSource);
17
- }
18
- function takePagesClientAssetsBuildMetadata(buildSession) {
19
- const moduleSource = pagesClientAssetsByBuildSession.get(buildSession) ?? null;
20
- pagesClientAssetsByBuildSession.delete(buildSession);
21
- return moduleSource;
22
- }
23
- function clearPagesClientAssetsBuildMetadata(buildSession) {
24
- pagesClientAssetsByBuildSession.delete(buildSession);
25
- }
26
14
  //#endregion
27
- export { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, clearPagesClientAssetsBuildMetadata, setPagesClientAssetsBuildMetadata, takePagesClientAssetsBuildMetadata, writePagesClientAssetsModuleIfMissing };
15
+ export { PAGES_CLIENT_ASSETS_MODULE, buildPagesClientAssetsModule, writePagesClientAssetsModuleIfMissing };
@@ -1,9 +1,9 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { ASSET_PREFIX_URL_DIR } from "../utils/asset-prefix.js";
3
3
  import { isPrecompressedVariantBeneficial } from "../utils/precompressed-variant.js";
4
- import fsp from "node:fs/promises";
5
4
  import { randomUUID } from "node:crypto";
6
5
  import { promisify } from "node:util";
6
+ import fsp from "node:fs/promises";
7
7
  import os from "node:os";
8
8
  import zlib from "node:zlib";
9
9
  //#region src/build/precompress.ts
@@ -1,6 +1,6 @@
1
- import { ResolvedNextConfig } from "../config/next-config.js";
2
1
  import { CdnCacheAdapterCapabilities } from "../cache/cache-adapters-virtual.js";
3
2
  import { VinextRouteRootConfig } from "../config/prerender.js";
3
+ import { ResolvedNextConfig } from "../config/next-config.js";
4
4
  import { MatcherConfig } from "../server/middleware-matcher.js";
5
5
  //#region src/build/prerender-paths.d.ts
6
6
  export type PrerenderRoutePattern = {
@@ -1,26 +1,26 @@
1
1
  import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { findDir } from "../utils/project.js";
3
- import { apiRouter, matchRoute, pagesRouter } from "../routing/pages-router.js";
3
+ import { BLOCKED_PAGES, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
4
4
  import { VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
5
- import "../server/headers.js";
6
5
  import { isExternalUrl } from "../utils/external-url.js";
7
6
  import { matchHeaders, matchesRewriteSource } from "../config/config-matchers.js";
7
+ import { loadNextConfig, resolveNextConfig } from "../config/next-config.js";
8
+ import { appRouteHasMainTreeLoadingBoundary, appRouter, matchAppRoute } from "../routing/app-router.js";
9
+ import { apiRouter, matchRoute, pagesRouter } from "../routing/pages-router.js";
10
+ import "../server/headers.js";
8
11
  import { matchesMiddlewarePathname } from "../server/middleware-matcher.js";
9
12
  import { extractLocaleFromUrl, normalizeDefaultLocalePathname } from "../server/pages-i18n.js";
10
13
  import { classifyAppRoute, classifyAppRouteHandler, classifyPagesRoute, extractExportConstString, extractMiddlewareMatcherConfig, getAppRouteRenderEntryPath } from "./report.js";
11
- import { appRouteHasMainTreeLoadingBoundary, appRouter, matchAppRoute } from "../routing/app-router.js";
12
14
  import { normalizeStaticPathname, normalizeStaticPathsEntry } from "../routing/route-pattern.js";
13
15
  import { buildPagesDataHref } from "../shims/internal/pages-data-url.js";
14
16
  import { normalizePathTrailingSlash } from "../shims/url-utils.js";
15
- import { BLOCKED_PAGES, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
16
- import { loadNextConfig, resolveNextConfig } from "../config/next-config.js";
17
17
  import { pagesRouteHasPriorityOverAppRoute } from "../server/hybrid-route-priority.js";
18
18
  import { readPrerenderSecret } from "./server-manifest.js";
19
19
  import { startProdServer } from "../server/prod-server.js";
20
20
  import { enterPrerenderPhase } from "./prerender-phase.js";
21
21
  import { buildUrlFromParams, resolveParentParams } from "./prerender.js";
22
- import { resolveBuiltRscEntryPath } from "./server-entry.js";
23
22
  import { resolveAppPageDynamicConfig } from "../server/app-segment-config.js";
23
+ import { resolveBuiltRscEntryPath } from "./server-entry.js";
24
24
  import fs from "node:fs";
25
25
  //#region src/build/prerender-paths.ts
26
26
  const PRERENDER_PATH_DISCOVERY_ENV = "__VINEXT_PRERENDER_PATH_DISCOVERY";
@@ -2,8 +2,8 @@ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
3
3
  import fs from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
- import os from "node:os";
6
5
  import { fork } from "node:child_process";
6
+ import os from "node:os";
7
7
  //#region src/build/prerender-server-pool.ts
8
8
  /**
9
9
  * Parallel prerender server pool.
@@ -218,7 +218,7 @@ export declare function prerenderPages({ routes, apiRoutes, pagesDir, outDir, co
218
218
  * `vinext-prerender.json` to `outDir`.
219
219
  *
220
220
  * If the bundle does not exist, an error is thrown directing the user to run
221
- * `vinext build` first.
221
+ * `vite build` first.
222
222
  *
223
223
  * Speculative static rendering: routes classified as 'unknown' (no explicit
224
224
  * config, non-dynamic URL) are attempted with an empty headers/cookies context.
@@ -1,4 +1,5 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
+ import { BLOCKED_PAGES } from "../shims/constants.js";
2
3
  import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
3
4
  import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
4
5
  import { NEXT_CACHE_TAGS_HEADER, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER } from "../server/headers.js";
@@ -8,7 +9,6 @@ import { NoOpCacheHandler, getCacheHandler, setCacheHandler } from "../shims/cac
8
9
  import { headersContextFromRequest, runWithHeadersContext } from "../shims/headers.js";
9
10
  import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
10
11
  import { normalizeStaticPathsEntry } from "../routing/route-pattern.js";
11
- import { BLOCKED_PAGES } from "../shims/constants.js";
12
12
  import { readPrerenderSecret } from "./server-manifest.js";
13
13
  import { buildPregeneratedConcretePathTable } from "../server/prerender-manifest.js";
14
14
  import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
@@ -25,7 +25,7 @@ import fs from "node:fs";
25
25
  import os from "node:os";
26
26
  //#region src/build/prerender.ts
27
27
  /**
28
- * Prerendering phase for vinext build.
28
+ * Prerendering phase for vite build.
29
29
  *
30
30
  * Classifies every route, renders static and ISR routes to HTML/JSON/RSC files,
31
31
  * and writes a `vinext-prerender.json` build index.
@@ -290,7 +290,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
290
290
  try {
291
291
  let prerenderSecret = options._prerenderSecret;
292
292
  if (!prerenderSecret && pagesBundlePath) prerenderSecret = readPrerenderSecret(path.dirname(pagesBundlePath));
293
- if (!prerenderSecret) console.warn("[vinext] Warning: prerender secret not found. /__vinext/prerender/* endpoints will return 403 and dynamic routes will produce no paths. Run `vinext build` to regenerate the secret.");
293
+ if (!prerenderSecret) console.warn("[vinext] Warning: prerender secret not found. /__vinext/prerender/* endpoints will return 403 and dynamic routes will produce no paths. Run `vite build` to regenerate the secret.");
294
294
  const prodServer = options._prodServer ? options._prodServer : await (async () => {
295
295
  const srv = await startProdServer({
296
296
  port: 0,
@@ -534,7 +534,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
534
534
  * `vinext-prerender.json` to `outDir`.
535
535
  *
536
536
  * If the bundle does not exist, an error is thrown directing the user to run
537
- * `vinext build` first.
537
+ * `vite build` first.
538
538
  *
539
539
  * Speculative static rendering: routes classified as 'unknown' (no explicit
540
540
  * config, non-dynamic URL) are attempted with an empty headers/cookies context.
@@ -559,7 +559,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
559
559
  let renderRoundRobin = 0;
560
560
  try {
561
561
  const prerenderSecret = readPrerenderSecret(serverDir);
562
- if (!prerenderSecret) console.warn("[vinext] Warning: prerender secret not found. /__vinext/prerender/* endpoints will return 403 and generateStaticParams will not be called. Run `vinext build` to regenerate the secret.");
562
+ if (!prerenderSecret) console.warn("[vinext] Warning: prerender secret not found. /__vinext/prerender/* endpoints will return 403 and generateStaticParams will not be called. Run `vite build` to regenerate the secret.");
563
563
  const prodServer = options._prodServer ? options._prodServer : await (async () => {
564
564
  const srv = await startProdServer({
565
565
  port: 0,
@@ -6,5 +6,5 @@ export type PreviewBuildCredentials = {
6
6
  };
7
7
  export declare function createPreviewBuildCredentials(): PreviewBuildCredentials;
8
8
  export declare function getPreviewBuildCredentials(): PreviewBuildCredentials | undefined;
9
- export declare function runWithPreviewBuildCredentials<T>(callback: () => T): T;
9
+ export declare function runWithPreviewBuildCredentials<T>(callback: () => T, credentials?: PreviewBuildCredentials): T;
10
10
  //#endregion
@@ -12,8 +12,8 @@ function createPreviewBuildCredentials() {
12
12
  function getPreviewBuildCredentials() {
13
13
  return previewBuildCredentialsStorage.getStore();
14
14
  }
15
- function runWithPreviewBuildCredentials(callback) {
16
- return previewBuildCredentialsStorage.run(createPreviewBuildCredentials(), callback);
15
+ function runWithPreviewBuildCredentials(callback, credentials = createPreviewBuildCredentials()) {
16
+ return previewBuildCredentialsStorage.run(credentials, callback);
17
17
  }
18
18
  //#endregion
19
19
  export { createPreviewBuildCredentials, getPreviewBuildCredentials, runWithPreviewBuildCredentials };