vinext 0.1.3 → 0.1.5
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/build/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/css-url-assets.d.ts +1 -1
- package/dist/build/css-url-assets.js +9 -7
- package/dist/build/prerender.js +3 -1
- package/dist/cache/cache-adapters-virtual.js +1 -1
- package/dist/client/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.js +2 -0
- package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +14 -2
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.js +20 -13
- package/dist/entries/app-rsc-entry.js +27 -22
- package/dist/entries/pages-client-entry.js +14 -13
- package/dist/entries/pages-server-entry.js +8 -27
- package/dist/index.js +365 -147
- package/dist/plugins/css-data-url.js +30 -26
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.js +27 -24
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/import-meta-url.js +21 -15
- package/dist/plugins/instrumentation-client.js +1 -1
- package/dist/plugins/middleware-server-only.js +7 -6
- package/dist/plugins/og-assets.js +48 -46
- package/dist/plugins/optimize-imports.js +9 -3
- package/dist/plugins/remove-console.d.ts +7 -1
- package/dist/plugins/remove-console.js +4 -1
- package/dist/plugins/require-context.js +21 -20
- package/dist/plugins/strip-server-exports.d.ts +16 -8
- package/dist/plugins/strip-server-exports.js +496 -46
- package/dist/routing/app-route-graph.js +2 -2
- package/dist/server/app-bfcache-identity.d.ts +26 -0
- package/dist/server/app-bfcache-identity.js +127 -0
- package/dist/server/app-browser-action-result.js +1 -1
- package/dist/server/app-browser-entry.js +22 -12
- package/dist/server/app-browser-navigation-controller.d.ts +1 -1
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-state.d.ts +3 -22
- package/dist/server/app-browser-state.js +23 -139
- package/dist/server/app-browser-stream.js +1 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +3 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -1
- package/dist/server/app-layout-param-observation.d.ts +1 -1
- package/dist/server/app-layout-param-observation.js +1 -1
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-page-boundary-render.d.ts +1 -1
- package/dist/server/app-page-boundary.js +1 -1
- package/dist/server/app-page-cache-finalizer.d.ts +62 -0
- package/dist/server/app-page-cache-finalizer.js +122 -0
- package/dist/server/app-page-cache-render.d.ts +2 -2
- package/dist/server/app-page-cache-render.js +1 -1
- package/dist/server/app-page-cache.d.ts +2 -53
- package/dist/server/app-page-cache.js +5 -131
- package/dist/server/app-page-dispatch.d.ts +2 -2
- package/dist/server/app-page-dispatch.js +10 -8
- package/dist/server/app-page-probe.js +3 -2
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +3 -3
- package/dist/server/app-page-render.js +3 -2
- package/dist/server/app-page-stream.d.ts +2 -9
- package/dist/server/app-page-stream.js +1 -35
- package/dist/server/app-pages-bridge.d.ts +5 -1
- package/dist/server/app-pages-bridge.js +5 -13
- package/dist/server/app-request-context.d.ts +1 -2
- package/dist/server/app-request-context.js +2 -1
- package/dist/server/app-route-handler-dispatch.js +3 -2
- package/dist/server/app-route-handler-execution.d.ts +1 -1
- package/dist/server/app-route-handler-execution.js +1 -1
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-router-entry.js +2 -1
- package/dist/server/app-rsc-handler.d.ts +3 -0
- package/dist/server/app-rsc-handler.js +73 -31
- package/dist/server/app-rsc-response-finalizer.js +1 -1
- package/dist/server/app-rsc-route-matching.js +6 -2
- package/dist/server/app-server-action-execution.d.ts +1 -1
- package/dist/server/app-server-action-execution.js +10 -6
- package/dist/server/app-ssr-entry.d.ts +1 -1
- package/dist/server/app-ssr-entry.js +12 -38
- package/dist/server/app-ssr-router-instance.d.ts +6 -0
- package/dist/server/app-ssr-router-instance.js +24 -0
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/artifact-compatibility.js +1 -1
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/client-reuse-manifest.js +1 -1
- package/dist/server/csp.js +1 -4
- package/dist/server/defer-until-stream-consumed.d.ts +7 -0
- package/dist/server/defer-until-stream-consumed.js +34 -0
- package/dist/server/dev-server.js +82 -37
- package/dist/server/instrumentation.js +1 -1
- package/dist/server/isr-cache.d.ts +1 -1
- package/dist/server/isr-cache.js +1 -1
- package/dist/server/isr-decision.d.ts +1 -1
- package/dist/server/middleware-matcher.js +20 -9
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +4 -2
- package/dist/server/navigation-planner.d.ts +3 -12
- package/dist/server/navigation-planner.js +24 -0
- package/dist/server/navigation-trace.d.ts +2 -1
- package/dist/server/navigation-trace.js +1 -0
- package/dist/server/open-redirect.d.ts +12 -0
- package/dist/server/open-redirect.js +21 -0
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-data-route.d.ts +1 -1
- package/dist/server/pages-data-route.js +7 -4
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- package/dist/server/pages-i18n.js +2 -2
- package/dist/server/pages-page-data.d.ts +1 -1
- package/dist/server/pages-page-data.js +3 -1
- package/dist/server/pages-page-handler.js +3 -1
- package/dist/server/pages-page-response.d.ts +3 -1
- package/dist/server/pages-page-response.js +6 -6
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +7 -7
- package/dist/server/pages-request-pipeline.js +63 -21
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +43 -11
- package/dist/server/request-pipeline.d.ts +1 -24
- package/dist/server/request-pipeline.js +1 -33
- package/dist/server/seed-cache.d.ts +1 -1
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/cache-handler.d.ts +106 -0
- package/dist/shims/cache-handler.js +176 -0
- package/dist/shims/cache-request-state.d.ts +47 -0
- package/dist/shims/cache-request-state.js +126 -0
- package/dist/shims/cache-runtime.d.ts +2 -2
- package/dist/shims/cache-runtime.js +3 -14
- package/dist/shims/cache.d.ts +3 -231
- package/dist/shims/cache.js +17 -383
- package/dist/shims/cdn-cache.d.ts +1 -1
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +44 -0
- package/dist/shims/error-boundary.js +10 -8
- package/dist/shims/error.js +2 -1
- package/dist/shims/fetch-cache.js +1 -1
- package/dist/shims/form.js +1 -1
- package/dist/shims/image.js +74 -9
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
- package/dist/shims/internal/app-page-props-cache-key.js +16 -0
- package/dist/shims/internal/navigation-untracked.js +2 -1
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- package/dist/shims/internal/pages-data-target.js +1 -1
- package/dist/shims/layout-segment-context.d.ts +1 -1
- package/dist/shims/layout-segment-context.js +2 -1
- package/dist/shims/link.js +38 -17
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation-context-state.d.ts +40 -0
- package/dist/shims/navigation-context-state.js +116 -0
- package/dist/shims/navigation-errors.d.ts +55 -0
- package/dist/shims/navigation-errors.js +110 -0
- package/dist/shims/navigation-server.d.ts +3 -0
- package/dist/shims/navigation-server.js +3 -0
- package/dist/shims/navigation-state.d.ts +1 -2
- package/dist/shims/navigation-state.js +2 -1
- package/dist/shims/navigation.d.ts +3 -291
- package/dist/shims/navigation.js +16 -445
- package/dist/shims/navigation.react-server.d.ts +2 -2
- package/dist/shims/navigation.react-server.js +3 -1
- package/dist/shims/request-state-types.d.ts +3 -3
- package/dist/shims/router.d.ts +6 -2
- package/dist/shims/router.js +99 -20
- package/dist/shims/script.js +9 -5
- package/dist/shims/slot.js +3 -1
- package/dist/shims/unified-request-context.d.ts +2 -2
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- package/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/virtual-module.d.ts +5 -0
- package/dist/utils/virtual-module.js +0 -0
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.js +9 -1
- package/package.json +5 -1
package/dist/index.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { detectPackageManager } from "./utils/project.js";
|
|
2
2
|
import { normalizePathSeparators, stripJsExtension, stripViteModuleQuery } from "./utils/path.js";
|
|
3
3
|
import { normalizePathnameForRouteMatchStrict } from "./routing/utils.js";
|
|
4
|
+
import { escapeRegExp } from "./utils/regex.js";
|
|
4
5
|
import { buildViteResolveExtensions, createValidFileMatcher, findFileWithExts, normalizeViteResolveExtensions } from "./routing/file-matcher.js";
|
|
5
6
|
import { apiRouter, invalidateRouteCache, matchRoute, pagesRouter } from "./routing/pages-router.js";
|
|
6
7
|
import { INTERNAL_HEADERS, NEXTJS_DEPLOYMENT_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MW_CTX_HEADER, VINEXT_TIMING_HEADER } from "./server/headers.js";
|
|
7
8
|
import { normalizePath as normalizePath$1 } from "./server/normalize-path.js";
|
|
8
|
-
import { proxyExternalRequest } from "./config/config-matchers.js";
|
|
9
|
-
import {
|
|
9
|
+
import { matchesRewriteSource, proxyExternalRequest } from "./config/config-matchers.js";
|
|
10
|
+
import { isOpenRedirectShaped } from "./server/open-redirect.js";
|
|
11
|
+
import { filterInternalHeaders, normalizeTrailingSlash } from "./server/request-pipeline.js";
|
|
10
12
|
import { findMiddlewareFile, runMiddleware } from "./server/middleware.js";
|
|
11
13
|
import { generateServerEntry } from "./entries/pages-server-entry.js";
|
|
12
14
|
import { generateClientEntry } from "./entries/pages-client-entry.js";
|
|
@@ -31,7 +33,7 @@ import { planRouteClassificationInjection } from "./build/route-classification-i
|
|
|
31
33
|
import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "./shims/constants.js";
|
|
32
34
|
import { resolveAssetsDir } from "./utils/asset-prefix.js";
|
|
33
35
|
import { RESOLVED_VIRTUAL_GOOGLE_FONTS, VIRTUAL_GOOGLE_FONTS, createGoogleFontsPlugin, createLocalFontsPlugin, generateGoogleFontsVirtualModule, parseStaticObjectLiteral } from "./plugins/fonts.js";
|
|
34
|
-
import { getViteMajorVersion } from "./utils/vite-version.js";
|
|
36
|
+
import { getDepOptimizeNodeEnvOptions, getViteMajorVersion, serializeViteDefine } from "./utils/vite-version.js";
|
|
35
37
|
import { createRscCompatibilityId, findNextConfigPath, loadNextConfig, resolveNextConfig, resolveNextConfigInput } from "./config/next-config.js";
|
|
36
38
|
import { isNextDataPathname, parseNextDataPathname } from "./server/pages-data-route.js";
|
|
37
39
|
import { precompressAssets } from "./build/precompress.js";
|
|
@@ -41,6 +43,7 @@ import { collectInlineCssManifest, injectInlineCssManifestGlobal } from "./build
|
|
|
41
43
|
import { installDevStackSourcemapMiddleware } from "./server/dev-stack-sourcemap.js";
|
|
42
44
|
import { runPagesRequest } from "./server/pages-request-pipeline.js";
|
|
43
45
|
import { pagesRouteHasPriorityOverAppRoute, validateHybridRouteConflicts } from "./server/hybrid-route-priority.js";
|
|
46
|
+
import { VIRTUAL_MODULE_ID_RE } from "./utils/virtual-module.js";
|
|
44
47
|
import { renderVinextBuiltUrl } from "./utils/built-asset-url.js";
|
|
45
48
|
import { asyncHooksStubPlugin } from "./plugins/async-hooks-stub.js";
|
|
46
49
|
import { clientReferenceDedupPlugin } from "./plugins/client-reference-dedup.js";
|
|
@@ -63,7 +66,7 @@ import { resolvePostcssStringPlugins } from "./plugins/postcss.js";
|
|
|
63
66
|
import { buildSassPreprocessorOptions, createSassAwareFileSystemLoader, createSassTildeImporter } from "./plugins/sass.js";
|
|
64
67
|
import { createClientAssetFileNames, createClientCodeSplittingConfig, createClientFileNameConfig, createClientManualChunks, createClientOutputConfig, createRscFrameworkChunkOutputConfig, getBuildBundlerOptions, getClientTreeshakeConfigForVite, withBuildBundlerOptions } from "./build/client-build-config.js";
|
|
65
68
|
import { markCssUrlAssetReferences, restoreDedupedCssAssetReferences } from "./build/css-url-assets.js";
|
|
66
|
-
import { stripServerExports } from "./plugins/strip-server-exports.js";
|
|
69
|
+
import { hasExportAllCandidate, stripServerExports, validatePageExports } from "./plugins/strip-server-exports.js";
|
|
67
70
|
import { removeConsoleCalls } from "./plugins/remove-console.js";
|
|
68
71
|
import { createImportMetaUrlPlugin } from "./plugins/import-meta-url.js";
|
|
69
72
|
import { createRequireContextPlugin } from "./plugins/require-context.js";
|
|
@@ -78,12 +81,16 @@ import fs from "node:fs";
|
|
|
78
81
|
import path from "node:path";
|
|
79
82
|
import { loadEnv, parseAst, transformWithOxc } from "vite";
|
|
80
83
|
import { pathToFileURL } from "node:url";
|
|
81
|
-
import { randomBytes, randomUUID } from "node:crypto";
|
|
84
|
+
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
82
85
|
import commonjs from "vite-plugin-commonjs";
|
|
83
86
|
import MagicString from "magic-string";
|
|
84
87
|
import tsconfigPaths from "vite-tsconfig-paths";
|
|
85
88
|
//#region src/index.ts
|
|
86
89
|
installSocketErrorBackstop();
|
|
90
|
+
function getCacheDirPrefix(cacheDir) {
|
|
91
|
+
const normalizedCacheDir = normalizePathSeparators(cacheDir);
|
|
92
|
+
return normalizedCacheDir.endsWith("/") ? normalizedCacheDir : `${normalizedCacheDir}/`;
|
|
93
|
+
}
|
|
87
94
|
function isInsideDirectory(dir, filePath) {
|
|
88
95
|
const relativePath = path.relative(dir, filePath);
|
|
89
96
|
return relativePath !== "" && !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
|
|
@@ -162,6 +169,19 @@ function resolveTsconfigPathCandidate(candidate) {
|
|
|
162
169
|
for (const item of candidates) if (fs.existsSync(item) && fs.statSync(item).isFile()) return item;
|
|
163
170
|
return null;
|
|
164
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Normalize a tsconfig `extends` field into a list of specifier strings.
|
|
174
|
+
*
|
|
175
|
+
* TypeScript 5.0+ allows `extends` to be either a string or an array of
|
|
176
|
+
* strings. Matches Next.js's handling in
|
|
177
|
+
* packages/next/src/build/next-config-ts/transpile-config.ts, where parents
|
|
178
|
+
* are iterated in order and later entries override earlier ones.
|
|
179
|
+
*/
|
|
180
|
+
function normalizeTsconfigExtends(extendsField) {
|
|
181
|
+
if (typeof extendsField === "string") return [extendsField];
|
|
182
|
+
if (Array.isArray(extendsField)) return extendsField.filter((value) => typeof value === "string");
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
165
185
|
function resolveTsconfigExtends(configPath, specifier) {
|
|
166
186
|
const fromDir = path.dirname(configPath);
|
|
167
187
|
if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("\\")) return resolveTsconfigPathCandidate(path.resolve(fromDir, specifier));
|
|
@@ -221,9 +241,12 @@ function loadTsconfigPathAliases(configPath, projectRoot, seen = /* @__PURE__ */
|
|
|
221
241
|
}
|
|
222
242
|
if (!parsed) return {};
|
|
223
243
|
let aliases = {};
|
|
224
|
-
|
|
225
|
-
const extendedPath = resolveTsconfigExtends(normalizedPath,
|
|
226
|
-
if (extendedPath) aliases =
|
|
244
|
+
for (const extendsSpecifier of normalizeTsconfigExtends(parsed.extends)) {
|
|
245
|
+
const extendedPath = resolveTsconfigExtends(normalizedPath, extendsSpecifier);
|
|
246
|
+
if (extendedPath) aliases = {
|
|
247
|
+
...aliases,
|
|
248
|
+
...loadTsconfigPathAliases(extendedPath, projectRoot, seen)
|
|
249
|
+
};
|
|
227
250
|
}
|
|
228
251
|
const compilerOptions = isUnknownRecord(parsed.compilerOptions) ? parsed.compilerOptions : null;
|
|
229
252
|
const pathsConfig = compilerOptions && isUnknownRecord(compilerOptions.paths) ? compilerOptions.paths : null;
|
|
@@ -284,10 +307,21 @@ const RESOLVED_ROOT_PARAMS = "\0virtual:vinext-root-params";
|
|
|
284
307
|
const RESOLVED_CACHE_ADAPTERS = "\0" + VIRTUAL_CACHE_ADAPTERS;
|
|
285
308
|
/** Virtual module for composed instrumentation-client bootstrap. */
|
|
286
309
|
const VIRTUAL_INSTRUMENTATION_CLIENT = "private-next-instrumentation-client";
|
|
287
|
-
const RESOLVED_INSTRUMENTATION_CLIENT =
|
|
310
|
+
const RESOLVED_INSTRUMENTATION_CLIENT = `${VIRTUAL_INSTRUMENTATION_CLIENT}.mjs`;
|
|
288
311
|
/** Image file extensions handled by the vinext:image-imports plugin.
|
|
289
312
|
* Shared between the Rolldown hook filter and the transform handler regex. */
|
|
290
313
|
const IMAGE_EXTS = "png|jpe?g|gif|webp|avif|svg|ico|bmp|tiff?";
|
|
314
|
+
/** Matches a trailing image extension on an import path. Built once: `IMAGE_EXTS`
|
|
315
|
+
* is constant, so there is no need to recompile this per transform invocation. */
|
|
316
|
+
const IMAGE_EXT_RE = new RegExp(`\\.(${IMAGE_EXTS})$`);
|
|
317
|
+
function createStaticImageAsset(imagePath) {
|
|
318
|
+
const source = fs.readFileSync(imagePath);
|
|
319
|
+
const extension = path.extname(imagePath);
|
|
320
|
+
return {
|
|
321
|
+
fileName: `media/${path.basename(imagePath, extension)}.${createHash("sha256").update(source).digest("hex").slice(0, 8)}${extension}`,
|
|
322
|
+
source
|
|
323
|
+
};
|
|
324
|
+
}
|
|
291
325
|
/**
|
|
292
326
|
* Absolute path to vinext's shims directory, with a trailing slash. Normalized
|
|
293
327
|
* to forward slashes because it is prefix-matched against Vite module ids (which
|
|
@@ -297,6 +331,8 @@ const IMAGE_EXTS = "png|jpe?g|gif|webp|avif|svg|ico|bmp|tiff?";
|
|
|
297
331
|
*/
|
|
298
332
|
const _shimsDir = normalizePathSeparators(path.resolve(__dirname, "shims")) + "/";
|
|
299
333
|
const _fontGoogleShimPath = resolveShimModulePath(_shimsDir, "font-google");
|
|
334
|
+
const _appRscHandlerPath = resolveShimModulePath(path.resolve(__dirname, "server"), "app-rsc-handler");
|
|
335
|
+
const _canExternalizeAppRscHandler = _appRscHandlerPath.endsWith(".js");
|
|
300
336
|
function isValidExportIdentifier(name) {
|
|
301
337
|
return /^[$A-Z_a-z][$\w]*$/.test(name);
|
|
302
338
|
}
|
|
@@ -394,6 +430,7 @@ function vinext(options = {}) {
|
|
|
394
430
|
const viteMajorVersion = getViteMajorVersion();
|
|
395
431
|
let root;
|
|
396
432
|
let pagesDir;
|
|
433
|
+
let canonicalPagesDir;
|
|
397
434
|
let appDir;
|
|
398
435
|
let hasAppDir = false;
|
|
399
436
|
let hasPagesDir = false;
|
|
@@ -410,9 +447,23 @@ function vinext(options = {}) {
|
|
|
410
447
|
let rscCompatibilityId;
|
|
411
448
|
const draftModeSecret = randomUUID();
|
|
412
449
|
const sassComposesLoader = createSassAwareFileSystemLoader();
|
|
450
|
+
const typeofWindowIdFilter = { exclude: /(?!)/ };
|
|
413
451
|
let rscClassificationManifest = null;
|
|
414
452
|
const shimsDir = path.resolve(__dirname, "shims");
|
|
415
|
-
const canonicalize = (p) => tryRealpathSync(p) ?? p;
|
|
453
|
+
const canonicalize = (p) => normalizePathSeparators(tryRealpathSync(p) ?? p);
|
|
454
|
+
const pageTransformCanonicalPaths = /* @__PURE__ */ new Map();
|
|
455
|
+
const canonicalizePageTransformPath = (modulePath) => {
|
|
456
|
+
const cached = pageTransformCanonicalPaths.get(modulePath);
|
|
457
|
+
if (cached) return cached;
|
|
458
|
+
const canonicalPath = canonicalize(modulePath);
|
|
459
|
+
pageTransformCanonicalPaths.set(modulePath, canonicalPath);
|
|
460
|
+
return canonicalPath;
|
|
461
|
+
};
|
|
462
|
+
const isWithinPagesDirectory = (modulePath) => modulePath === pagesDir || modulePath.startsWith(`${pagesDir}/`) || modulePath === canonicalPagesDir || modulePath.startsWith(`${canonicalPagesDir}/`);
|
|
463
|
+
const isApiPage = (canonicalId) => {
|
|
464
|
+
const relativePath = fileMatcher.stripExtension(canonicalId.slice(canonicalPagesDir.length));
|
|
465
|
+
return relativePath === "/api" || relativePath.startsWith("/api/");
|
|
466
|
+
};
|
|
416
467
|
const dynamicShimPaths = new Set([
|
|
417
468
|
resolveShimModulePath(shimsDir, "headers"),
|
|
418
469
|
resolveShimModulePath(shimsDir, "server"),
|
|
@@ -481,6 +532,9 @@ function vinext(options = {}) {
|
|
|
481
532
|
});
|
|
482
533
|
}
|
|
483
534
|
const imageImportDimCache = /* @__PURE__ */ new Map();
|
|
535
|
+
const staticImageAssets = /* @__PURE__ */ new Map();
|
|
536
|
+
const staticImageImportsByModule = /* @__PURE__ */ new Map();
|
|
537
|
+
const writtenStaticImageFiles = /* @__PURE__ */ new Set();
|
|
484
538
|
let mdxDelegate = null;
|
|
485
539
|
let mdxDelegatePromise = null;
|
|
486
540
|
let hasUserMdxPlugin = false;
|
|
@@ -520,22 +574,25 @@ function vinext(options = {}) {
|
|
|
520
574
|
...viteMajorVersion >= 8 ? [{
|
|
521
575
|
name: "vinext:jsx-in-js",
|
|
522
576
|
enforce: "pre",
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if (
|
|
528
|
-
if (
|
|
577
|
+
transform: {
|
|
578
|
+
filter: { id: /\.m?js(?:\?.*)?$/ },
|
|
579
|
+
async handler(code, id) {
|
|
580
|
+
const cleanId = id.split("?")[0];
|
|
581
|
+
if (isInsideDirectory(__dirname, cleanId)) return;
|
|
582
|
+
if (cleanId.includes("/node_modules/")) {
|
|
583
|
+
if (!code.includes("use client") && !code.includes("use server")) return;
|
|
584
|
+
if (!hasReactDirective(code)) return;
|
|
585
|
+
}
|
|
586
|
+
const result = await transformWithOxc(code, id, {
|
|
587
|
+
lang: "jsx",
|
|
588
|
+
jsx: { runtime: "automatic" },
|
|
589
|
+
sourcemap: true
|
|
590
|
+
});
|
|
591
|
+
return {
|
|
592
|
+
code: result.code,
|
|
593
|
+
map: result.map
|
|
594
|
+
};
|
|
529
595
|
}
|
|
530
|
-
const result = await transformWithOxc(code, id, {
|
|
531
|
-
lang: "jsx",
|
|
532
|
-
jsx: { runtime: "automatic" },
|
|
533
|
-
sourcemap: true
|
|
534
|
-
});
|
|
535
|
-
return {
|
|
536
|
-
code: result.code,
|
|
537
|
-
map: result.map
|
|
538
|
-
};
|
|
539
596
|
}
|
|
540
597
|
}] : [],
|
|
541
598
|
createMiddlewareServerOnlyPlugin({
|
|
@@ -572,6 +629,7 @@ function vinext(options = {}) {
|
|
|
572
629
|
else baseDir = root;
|
|
573
630
|
}
|
|
574
631
|
pagesDir = path.posix.join(baseDir, "pages");
|
|
632
|
+
canonicalPagesDir = canonicalize(pagesDir);
|
|
575
633
|
appDir = path.posix.join(baseDir, "app");
|
|
576
634
|
hasPagesDir = fs.existsSync(pagesDir);
|
|
577
635
|
hasAppDir = !options.disableAppRouter && fs.existsSync(appDir);
|
|
@@ -605,7 +663,10 @@ function vinext(options = {}) {
|
|
|
605
663
|
clientInjectModule = instrumentationClientInjects.length ? generateInstrumentationClientInjectModule(instrumentationClientInjects, instrumentationClientPath, INSTRUMENTATION_CLIENT_EMPTY_MODULE) : null;
|
|
606
664
|
if (env?.command === "build") await writeRouteTypes();
|
|
607
665
|
const defines = getNextPublicEnvDefines();
|
|
608
|
-
|
|
666
|
+
const userNodeEnvDefine = config.define?.["process.env.NODE_ENV"];
|
|
667
|
+
const hasUserNodeEnvDefine = Object.hasOwn(config.define ?? {}, "process.env.NODE_ENV");
|
|
668
|
+
const nodeEnvDefine = hasUserNodeEnvDefine ? serializeViteDefine(userNodeEnvDefine) : JSON.stringify(resolvedNodeEnv);
|
|
669
|
+
if (!hasUserNodeEnvDefine) defines["process.env.NODE_ENV"] = nodeEnvDefine;
|
|
609
670
|
for (const [key, value] of Object.entries(nextConfig.env)) {
|
|
610
671
|
if (key === "NODE_ENV") continue;
|
|
611
672
|
defines[`process.env.${key}`] = JSON.stringify(value);
|
|
@@ -836,10 +897,15 @@ function vinext(options = {}) {
|
|
|
836
897
|
if (shimBase !== void 0) return resolveShimModulePath(shimsDir, shimBase);
|
|
837
898
|
}
|
|
838
899
|
};
|
|
900
|
+
const depOptimizeNodeEnvOptions = getDepOptimizeNodeEnvOptions(viteMajorVersion, nodeEnvDefine);
|
|
839
901
|
viteConfig.optimizeDeps = {
|
|
840
902
|
exclude: mergeOptimizeDepsExclude(incomingExclude, VINEXT_OPTIMIZE_DEPS_EXCLUDE, ["@tailwindcss/oxide"]),
|
|
841
903
|
...incomingInclude.length > 0 ? { include: incomingInclude } : {},
|
|
842
|
-
|
|
904
|
+
...depOptimizeNodeEnvOptions,
|
|
905
|
+
rolldownOptions: {
|
|
906
|
+
...depOptimizeNodeEnvOptions.rolldownOptions,
|
|
907
|
+
plugins: [depOptimizeAliasPlugin]
|
|
908
|
+
}
|
|
843
909
|
};
|
|
844
910
|
const pagesOptimizeEntries = !hasAppDir ? [...hasPagesDir ? [toRelativeFileEntry(root, pagesDir) + "/**/*.{tsx,ts,jsx,js}"] : [], ...[instrumentationPath, instrumentationClientPath].flatMap((entry) => entry ? [toRelativeFileEntry(root, entry)] : [])] : [];
|
|
845
911
|
if (hasAppDir) {
|
|
@@ -855,13 +921,16 @@ function vinext(options = {}) {
|
|
|
855
921
|
"satori",
|
|
856
922
|
"@resvg/resvg-js",
|
|
857
923
|
"yoga-wasm-web",
|
|
924
|
+
...env?.command === "serve" && _canExternalizeAppRscHandler ? ["vinext/server/app-rsc-handler"] : [],
|
|
858
925
|
...userSsrExternal
|
|
859
926
|
],
|
|
860
927
|
...userSsrExternal === true ? {} : { noExternal: true }
|
|
861
928
|
} },
|
|
862
929
|
optimizeDeps: {
|
|
863
930
|
exclude: mergeOptimizeDepsExclude(incomingExclude, VINEXT_OPTIMIZE_DEPS_EXCLUDE),
|
|
864
|
-
entries: optimizeEntries
|
|
931
|
+
entries: optimizeEntries,
|
|
932
|
+
include: [...new Set([...incomingInclude, "react-server-dom-webpack/static.edge"])],
|
|
933
|
+
...depOptimizeNodeEnvOptions
|
|
865
934
|
},
|
|
866
935
|
build: {
|
|
867
936
|
outDir: options.rscOutDir ?? "dist/server",
|
|
@@ -878,7 +947,8 @@ function vinext(options = {}) {
|
|
|
878
947
|
} },
|
|
879
948
|
optimizeDeps: {
|
|
880
949
|
exclude: mergeOptimizeDepsExclude(incomingExclude, VINEXT_OPTIMIZE_DEPS_EXCLUDE, ["ipaddr.js"], userSsrExternal === true ? SSR_EXTERNAL_REACT_ENTRIES : []),
|
|
881
|
-
entries: optimizeEntries
|
|
950
|
+
entries: optimizeEntries,
|
|
951
|
+
...depOptimizeNodeEnvOptions
|
|
882
952
|
},
|
|
883
953
|
build: {
|
|
884
954
|
outDir: options.ssrOutDir ?? "dist/server/ssr",
|
|
@@ -951,7 +1021,10 @@ function vinext(options = {}) {
|
|
|
951
1021
|
],
|
|
952
1022
|
noExternal: true
|
|
953
1023
|
},
|
|
954
|
-
optimizeDeps: {
|
|
1024
|
+
optimizeDeps: {
|
|
1025
|
+
exclude: ["ipaddr.js"],
|
|
1026
|
+
...depOptimizeNodeEnvOptions
|
|
1027
|
+
},
|
|
955
1028
|
build: {
|
|
956
1029
|
outDir: "dist/server",
|
|
957
1030
|
...withBuildBundlerOptions(viteMajorVersion, {
|
|
@@ -975,6 +1048,8 @@ function vinext(options = {}) {
|
|
|
975
1048
|
return null;
|
|
976
1049
|
},
|
|
977
1050
|
async configResolved(config) {
|
|
1051
|
+
const cacheDirPrefix = getCacheDirPrefix(config.cacheDir);
|
|
1052
|
+
typeofWindowIdFilter.exclude = new RegExp(`^${escapeRegExp(cacheDirPrefix)}`);
|
|
978
1053
|
sassComposesLoader.setResolvedConfig(config);
|
|
979
1054
|
if (config.command === "build" && hasAppDir && hasPagesDir) {
|
|
980
1055
|
const [appRoutes, pageRoutes, apiRoutes] = await Promise.all([
|
|
@@ -1011,9 +1086,16 @@ function vinext(options = {}) {
|
|
|
1011
1086
|
}));
|
|
1012
1087
|
},
|
|
1013
1088
|
resolveId: {
|
|
1014
|
-
filter: { id: /(?:next\/|vinext\/shims\/|virtual:vinext-|@vercel\/og(?:\.js)?$)/ },
|
|
1089
|
+
filter: { id: /(?:next\/|vinext\/(?:shims\/|server\/app-rsc-handler)|virtual:vinext-|@vercel\/og(?:\.js)?$)/ },
|
|
1015
1090
|
handler(id, importer) {
|
|
1016
1091
|
const cleanId = id.startsWith("\0") ? id.slice(1) : id;
|
|
1092
|
+
if (cleanId === "vinext/server/app-rsc-handler") {
|
|
1093
|
+
if (_canExternalizeAppRscHandler && this.environment?.name === "rsc" && this.environment.config?.command === "serve") return {
|
|
1094
|
+
id: _appRscHandlerPath,
|
|
1095
|
+
external: true
|
|
1096
|
+
};
|
|
1097
|
+
return _appRscHandlerPath;
|
|
1098
|
+
}
|
|
1017
1099
|
if (isVercelOgImport(cleanId) && !isVinextOgShimImporter(importer)) return resolveShimModulePath(_shimsDir, "og");
|
|
1018
1100
|
if (cleanId.startsWith("vinext/shims/")) return resolveShimModulePath(_shimsDir, stripJsExtension(stripViteModuleQuery(cleanId.slice(13))));
|
|
1019
1101
|
if (cleanId === VIRTUAL_SERVER_ENTRY) return RESOLVED_SERVER_ENTRY;
|
|
@@ -1132,14 +1214,19 @@ function vinext(options = {}) {
|
|
|
1132
1214
|
name: "vinext:css-url-assets-mark",
|
|
1133
1215
|
enforce: "pre",
|
|
1134
1216
|
apply: "build",
|
|
1135
|
-
transform
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1217
|
+
transform: {
|
|
1218
|
+
filter: {
|
|
1219
|
+
id: /\.(?:css|scss|sass|less|styl|stylus)(?:\?|$)/i,
|
|
1220
|
+
code: "url("
|
|
1221
|
+
},
|
|
1222
|
+
handler(code, id) {
|
|
1223
|
+
const marked = markCssUrlAssetReferences(code, id);
|
|
1224
|
+
if (marked === null) return null;
|
|
1225
|
+
return {
|
|
1226
|
+
code: marked,
|
|
1227
|
+
map: null
|
|
1228
|
+
};
|
|
1229
|
+
}
|
|
1143
1230
|
}
|
|
1144
1231
|
},
|
|
1145
1232
|
{
|
|
@@ -1164,7 +1251,6 @@ function vinext(options = {}) {
|
|
|
1164
1251
|
enforce: "post",
|
|
1165
1252
|
apply: "build",
|
|
1166
1253
|
generateBundle(_options, bundle) {
|
|
1167
|
-
if (this.environment?.name !== "client") return;
|
|
1168
1254
|
restoreDedupedCssAssetReferences(bundle, (asset) => {
|
|
1169
1255
|
this.emitFile({
|
|
1170
1256
|
type: "asset",
|
|
@@ -1242,18 +1328,20 @@ function vinext(options = {}) {
|
|
|
1242
1328
|
`export const addTransitionType = _React.addTransitionType || function addTransitionType() {};`
|
|
1243
1329
|
].join("\n");
|
|
1244
1330
|
},
|
|
1245
|
-
transform
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1331
|
+
transform: {
|
|
1332
|
+
filter: {
|
|
1333
|
+
id: {
|
|
1334
|
+
include: /\.(tsx?|jsx?|mjs)$/,
|
|
1335
|
+
exclude: [/node_modules/, VIRTUAL_MODULE_ID_RE]
|
|
1336
|
+
},
|
|
1337
|
+
code: /import\s*\{[^}]*(ViewTransition|addTransitionType)[^}]*\}\s*from\s*['"]react['"]/
|
|
1338
|
+
},
|
|
1339
|
+
handler(code) {
|
|
1340
|
+
return {
|
|
1341
|
+
code: code.replace(/from\s*['"]react['"]/g, "from \"virtual:vinext-react-canary\""),
|
|
1342
|
+
map: null
|
|
1343
|
+
};
|
|
1344
|
+
}
|
|
1257
1345
|
}
|
|
1258
1346
|
},
|
|
1259
1347
|
{
|
|
@@ -1435,6 +1523,51 @@ function vinext(options = {}) {
|
|
|
1435
1523
|
});
|
|
1436
1524
|
installDevStackSourcemapMiddleware(server);
|
|
1437
1525
|
return () => {
|
|
1526
|
+
const viteFilesystemMiddlewares = server.middlewares.stack.filter(({ handle }) => {
|
|
1527
|
+
const name = typeof handle === "function" ? handle.name : "";
|
|
1528
|
+
return name === "viteServePublicMiddleware" || name === "viteServeStaticMiddleware";
|
|
1529
|
+
}).map(({ handle }) => handle).filter((handle) => typeof handle === "function");
|
|
1530
|
+
const serveRewrittenViteFilesystemRoute = async (req, res, requestPathname, stagedHeaders) => {
|
|
1531
|
+
const originalUrl = req.url;
|
|
1532
|
+
const originalStatusCode = res.statusCode;
|
|
1533
|
+
const originalStatusMessage = res.statusMessage;
|
|
1534
|
+
const originalHeaders = res.getHeaders();
|
|
1535
|
+
req.url = requestPathname;
|
|
1536
|
+
for (const [key, value] of Object.entries(stagedHeaders)) res.setHeader(key, value);
|
|
1537
|
+
const restore = () => {
|
|
1538
|
+
req.url = originalUrl;
|
|
1539
|
+
res.statusCode = originalStatusCode;
|
|
1540
|
+
res.statusMessage = originalStatusMessage;
|
|
1541
|
+
for (const key of Object.keys(res.getHeaders())) res.removeHeader(key);
|
|
1542
|
+
for (const [key, value] of Object.entries(originalHeaders)) if (value !== void 0) res.setHeader(key, value);
|
|
1543
|
+
};
|
|
1544
|
+
try {
|
|
1545
|
+
for (const middleware of viteFilesystemMiddlewares) if (await new Promise((resolve, reject) => {
|
|
1546
|
+
let settled = false;
|
|
1547
|
+
const settle = (value, error) => {
|
|
1548
|
+
if (settled) return;
|
|
1549
|
+
settled = true;
|
|
1550
|
+
res.off("finish", onServed);
|
|
1551
|
+
res.off("close", onServed);
|
|
1552
|
+
if (error) reject(error);
|
|
1553
|
+
else resolve(value);
|
|
1554
|
+
};
|
|
1555
|
+
const onServed = () => settle("served");
|
|
1556
|
+
res.once("finish", onServed);
|
|
1557
|
+
res.once("close", onServed);
|
|
1558
|
+
middleware(req, res, (error) => settle("next", error));
|
|
1559
|
+
if (res.writableEnded) settle("served");
|
|
1560
|
+
}) === "served") {
|
|
1561
|
+
req.url = originalUrl;
|
|
1562
|
+
return true;
|
|
1563
|
+
}
|
|
1564
|
+
} catch (error) {
|
|
1565
|
+
restore();
|
|
1566
|
+
throw error;
|
|
1567
|
+
}
|
|
1568
|
+
restore();
|
|
1569
|
+
return false;
|
|
1570
|
+
};
|
|
1438
1571
|
if (instrumentationPath && !hasAppDir) runInstrumentation(getPagesRunner(), instrumentationPath).catch((err) => {
|
|
1439
1572
|
console.error("[vinext] Instrumentation error:", err);
|
|
1440
1573
|
});
|
|
@@ -1556,6 +1689,7 @@ function vinext(options = {}) {
|
|
|
1556
1689
|
return;
|
|
1557
1690
|
}
|
|
1558
1691
|
}
|
|
1692
|
+
if (hasCloudflarePlugin) return next();
|
|
1559
1693
|
let isDataReq = false;
|
|
1560
1694
|
if (isNextDataPathname(pathname)) {
|
|
1561
1695
|
const devBuildId = nextConfig?.buildId ?? process.env.__VINEXT_BUILD_ID ?? "development";
|
|
@@ -1575,10 +1709,17 @@ function vinext(options = {}) {
|
|
|
1575
1709
|
return;
|
|
1576
1710
|
}
|
|
1577
1711
|
}
|
|
1578
|
-
|
|
1579
|
-
|
|
1712
|
+
const filePathMatchesRewrite = [
|
|
1713
|
+
...nextConfig?.rewrites.beforeFiles ?? [],
|
|
1714
|
+
...nextConfig?.rewrites.afterFiles ?? [],
|
|
1715
|
+
...nextConfig?.rewrites.fallback ?? []
|
|
1716
|
+
].some((rewrite) => matchesRewriteSource(pathname, rewrite, {
|
|
1717
|
+
basePath: bp,
|
|
1718
|
+
hadBasePath: true
|
|
1719
|
+
}));
|
|
1720
|
+
if (pathname.includes(".") && !pathname.endsWith(".html") && !filePathMatchesRewrite) return next();
|
|
1580
1721
|
const rawHeaders = new Headers(Object.fromEntries(Object.entries(req.headers).filter(([k, v]) => v !== void 0 && !k.startsWith(":")).map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v)])));
|
|
1581
|
-
const isDataRequest =
|
|
1722
|
+
const isDataRequest = isDataReq;
|
|
1582
1723
|
const nodeRequestHeaders = filterInternalHeaders(rawHeaders);
|
|
1583
1724
|
for (const header of INTERNAL_HEADERS) delete req.headers[header];
|
|
1584
1725
|
for (const header of VINEXT_INTERNAL_HEADERS) delete req.headers[header];
|
|
@@ -1649,6 +1790,10 @@ function vinext(options = {}) {
|
|
|
1649
1790
|
externalInit.duplex = "half";
|
|
1650
1791
|
}
|
|
1651
1792
|
return proxyExternalRequest(new Request(new URL(url, requestOrigin), externalInit), externalUrl);
|
|
1793
|
+
},
|
|
1794
|
+
serveFilesystemRoute: async (requestPathname, stagedHeaders, phase) => {
|
|
1795
|
+
if (phase === "direct" || req.method !== "GET" && req.method !== "HEAD" || requestPathname === "/" || requestPathname === "/api" || requestPathname.startsWith("/api/")) return false;
|
|
1796
|
+
return serveRewrittenViteFilesystemRoute(req, res, requestPathname, stagedHeaders);
|
|
1652
1797
|
}
|
|
1653
1798
|
});
|
|
1654
1799
|
if (pipelineResult.type === "response") {
|
|
@@ -1714,38 +1859,63 @@ function vinext(options = {}) {
|
|
|
1714
1859
|
}
|
|
1715
1860
|
},
|
|
1716
1861
|
{
|
|
1717
|
-
name: "vinext:validate-
|
|
1862
|
+
name: "vinext:validate-page-exports",
|
|
1718
1863
|
transform: {
|
|
1719
1864
|
filter: {
|
|
1720
|
-
id:
|
|
1721
|
-
code:
|
|
1865
|
+
id: { exclude: VIRTUAL_MODULE_ID_RE },
|
|
1866
|
+
code: /\bexport\b[\s\S]*\*/
|
|
1722
1867
|
},
|
|
1723
1868
|
handler(code, id) {
|
|
1724
1869
|
if (this.environment?.name !== "client") return null;
|
|
1725
|
-
if (
|
|
1726
|
-
|
|
1727
|
-
if (!
|
|
1728
|
-
|
|
1870
|
+
if (!hasPagesDir || !hasExportAllCandidate(code)) return null;
|
|
1871
|
+
const modulePath = stripViteModuleQuery(id);
|
|
1872
|
+
if (!isWithinPagesDirectory(modulePath)) return null;
|
|
1873
|
+
const canonicalId = canonicalizePageTransformPath(modulePath);
|
|
1874
|
+
if (!isWithinPagesDirectory(canonicalId)) return null;
|
|
1875
|
+
if (!fileMatcher.isPageFile(canonicalId)) return null;
|
|
1876
|
+
if (isApiPage(canonicalId)) return null;
|
|
1877
|
+
validatePageExports(code);
|
|
1878
|
+
return null;
|
|
1729
1879
|
}
|
|
1730
1880
|
}
|
|
1731
1881
|
},
|
|
1732
1882
|
{
|
|
1733
1883
|
name: "vinext:strip-server-exports",
|
|
1734
1884
|
transform: {
|
|
1735
|
-
filter: {
|
|
1885
|
+
filter: {
|
|
1886
|
+
id: { exclude: VIRTUAL_MODULE_ID_RE },
|
|
1887
|
+
code: /getServerSideProps|getStaticProps|getStaticPaths|unstable_getServerProps|unstable_getServerSideProps|unstable_getStaticProps|unstable_getStaticPaths/
|
|
1888
|
+
},
|
|
1736
1889
|
handler(code, id) {
|
|
1737
1890
|
if (this.environment?.name !== "client") return null;
|
|
1738
1891
|
if (!hasPagesDir) return null;
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
if (
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
return
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1892
|
+
const modulePath = stripViteModuleQuery(id);
|
|
1893
|
+
if (!isWithinPagesDirectory(modulePath)) return null;
|
|
1894
|
+
const canonicalId = canonicalizePageTransformPath(modulePath);
|
|
1895
|
+
if (!isWithinPagesDirectory(canonicalId)) return null;
|
|
1896
|
+
if (!fileMatcher.isPageFile(canonicalId)) return null;
|
|
1897
|
+
const relativePath = canonicalId.slice(canonicalPagesDir.length);
|
|
1898
|
+
if (isApiPage(canonicalId)) return null;
|
|
1899
|
+
if (/^\/(?:_app|_document|_error)(?:\.[^/]*)?$/.test(relativePath)) return null;
|
|
1900
|
+
return stripServerExports(code);
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
},
|
|
1904
|
+
{
|
|
1905
|
+
name: "vinext:validate-server-only-client-imports",
|
|
1906
|
+
transform: {
|
|
1907
|
+
filter: {
|
|
1908
|
+
id: {
|
|
1909
|
+
include: /\.(tsx?|jsx?|mjs)$/,
|
|
1910
|
+
exclude: VIRTUAL_MODULE_ID_RE
|
|
1911
|
+
},
|
|
1912
|
+
code: "server-only"
|
|
1913
|
+
},
|
|
1914
|
+
handler(code) {
|
|
1915
|
+
if (this.environment?.name !== "client") return null;
|
|
1916
|
+
if (getLeadingReactDirective(code) === "use server") return null;
|
|
1917
|
+
if (!hasServerOnlyMarkerImport(code)) return null;
|
|
1918
|
+
throw new Error(`You're importing a module that depends on "server-only". This API is only available in Server Components in the App Router, but this module is reachable from a client bundle.`);
|
|
1749
1919
|
}
|
|
1750
1920
|
}
|
|
1751
1921
|
},
|
|
@@ -1753,17 +1923,17 @@ function vinext(options = {}) {
|
|
|
1753
1923
|
name: "vinext:remove-console",
|
|
1754
1924
|
apply: "build",
|
|
1755
1925
|
transform: {
|
|
1756
|
-
filter: {
|
|
1757
|
-
|
|
1926
|
+
filter: {
|
|
1927
|
+
id: {
|
|
1928
|
+
include: /\.(tsx?|jsx?|mjs)$/,
|
|
1929
|
+
exclude: /\/node_modules\//
|
|
1930
|
+
},
|
|
1931
|
+
code: /\bconsole\b/
|
|
1932
|
+
},
|
|
1933
|
+
handler(code) {
|
|
1758
1934
|
if (this.environment?.name !== "client") return null;
|
|
1759
1935
|
if (!nextConfig.removeConsole) return null;
|
|
1760
|
-
|
|
1761
|
-
const result = removeConsoleCalls(code, nextConfig.removeConsole);
|
|
1762
|
-
if (!result) return null;
|
|
1763
|
-
return {
|
|
1764
|
-
code: result,
|
|
1765
|
-
map: null
|
|
1766
|
-
};
|
|
1936
|
+
return removeConsoleCalls(code, nextConfig.removeConsole);
|
|
1767
1937
|
}
|
|
1768
1938
|
}
|
|
1769
1939
|
},
|
|
@@ -1771,8 +1941,13 @@ function vinext(options = {}) {
|
|
|
1771
1941
|
name: "vinext:typeof-window",
|
|
1772
1942
|
enforce: "post",
|
|
1773
1943
|
transform: {
|
|
1774
|
-
filter: {
|
|
1775
|
-
|
|
1944
|
+
filter: {
|
|
1945
|
+
id: typeofWindowIdFilter,
|
|
1946
|
+
code: /typeof\s+window/
|
|
1947
|
+
},
|
|
1948
|
+
handler(code, id) {
|
|
1949
|
+
const cacheDirPrefix = getCacheDirPrefix(this.environment.config.cacheDir);
|
|
1950
|
+
if (normalizePathSeparators(id).startsWith(cacheDirPrefix)) return null;
|
|
1776
1951
|
return replaceTypeofWindow(code, getTypeofWindowReplacement(this.environment));
|
|
1777
1952
|
}
|
|
1778
1953
|
}
|
|
@@ -1792,16 +1967,37 @@ function vinext(options = {}) {
|
|
|
1792
1967
|
name: "vinext:image-imports",
|
|
1793
1968
|
enforce: "pre",
|
|
1794
1969
|
_dimCache: imageImportDimCache,
|
|
1970
|
+
buildStart() {
|
|
1971
|
+
imageImportDimCache.clear();
|
|
1972
|
+
staticImageAssets.clear();
|
|
1973
|
+
},
|
|
1974
|
+
watchChange(id) {
|
|
1975
|
+
const key = normalizePathSeparators(id);
|
|
1976
|
+
imageImportDimCache.delete(key);
|
|
1977
|
+
staticImageAssets.delete(key);
|
|
1978
|
+
staticImageImportsByModule.delete(key);
|
|
1979
|
+
},
|
|
1795
1980
|
resolveId: {
|
|
1796
|
-
filter: { id: /\?vinext-meta$/ },
|
|
1981
|
+
filter: { id: /\?vinext-(?:image-url|meta)$/ },
|
|
1797
1982
|
handler(source, _importer) {
|
|
1798
|
-
if (
|
|
1799
|
-
return `\0vinext-image-meta:${source.
|
|
1983
|
+
if (source.endsWith("?vinext-image-url")) return `\0vinext-image-url:${source.slice(0, -17)}`;
|
|
1984
|
+
if (source.endsWith("?vinext-meta")) return `\0vinext-image-meta:${source.slice(0, -12)}`;
|
|
1985
|
+
return null;
|
|
1800
1986
|
}
|
|
1801
1987
|
},
|
|
1802
1988
|
async load(id) {
|
|
1989
|
+
if (id.startsWith("\0vinext-image-url:")) {
|
|
1990
|
+
const imagePath = id.replace("\0vinext-image-url:", "");
|
|
1991
|
+
this.addWatchFile(imagePath);
|
|
1992
|
+
if (this.environment.config.command === "serve") return `import url from ${JSON.stringify(imagePath + "?url")}; export default url;`;
|
|
1993
|
+
const asset = createStaticImageAsset(imagePath);
|
|
1994
|
+
staticImageAssets.set(imagePath, asset);
|
|
1995
|
+
const builtFileName = `${resolveAssetsDir(nextConfig.assetPrefix)}/${asset.fileName}`;
|
|
1996
|
+
return `export default ${JSON.stringify(renderVinextBuiltUrl(builtFileName, nextConfig.assetPrefix, nextConfig.deploymentId))};`;
|
|
1997
|
+
}
|
|
1803
1998
|
if (!id.startsWith("\0vinext-image-meta:")) return null;
|
|
1804
1999
|
const imagePath = id.replace("\0vinext-image-meta:", "");
|
|
2000
|
+
this.addWatchFile(imagePath);
|
|
1805
2001
|
const cache = imageImportDimCache;
|
|
1806
2002
|
let dims = cache.get(imagePath);
|
|
1807
2003
|
if (!dims) try {
|
|
@@ -1824,15 +2020,11 @@ function vinext(options = {}) {
|
|
|
1824
2020
|
filter: {
|
|
1825
2021
|
id: {
|
|
1826
2022
|
include: /\.(tsx?|jsx?|mjs)$/,
|
|
1827
|
-
exclude: /node_modules
|
|
2023
|
+
exclude: [/node_modules/, VIRTUAL_MODULE_ID_RE]
|
|
1828
2024
|
},
|
|
1829
2025
|
code: new RegExp(`import\\s+\\w+\\s+from\\s+['"][^'"]+\\.(${IMAGE_EXTS})['"]`)
|
|
1830
2026
|
},
|
|
1831
2027
|
async handler(code, id) {
|
|
1832
|
-
if (id.includes("node_modules")) return null;
|
|
1833
|
-
if (id.startsWith("\0")) return null;
|
|
1834
|
-
if (!id.match(/\.(tsx?|jsx?|mjs)$/)) return null;
|
|
1835
|
-
const imageExtRe = new RegExp(`\\.(${IMAGE_EXTS})$`);
|
|
1836
2028
|
const lang = id.endsWith(".ts") ? "ts" : "tsx";
|
|
1837
2029
|
let ast;
|
|
1838
2030
|
try {
|
|
@@ -1842,12 +2034,13 @@ function vinext(options = {}) {
|
|
|
1842
2034
|
}
|
|
1843
2035
|
const s = new MagicString(code);
|
|
1844
2036
|
let hasChanges = false;
|
|
2037
|
+
const imageImports = /* @__PURE__ */ new Set();
|
|
1845
2038
|
for (const node of ast.body) {
|
|
1846
2039
|
if (node.type !== "ImportDeclaration") continue;
|
|
1847
2040
|
const importNode = node;
|
|
1848
2041
|
const importPath = importNode.source?.value;
|
|
1849
2042
|
if (typeof importPath !== "string") continue;
|
|
1850
|
-
if (!
|
|
2043
|
+
if (!IMAGE_EXT_RE.test(importPath)) continue;
|
|
1851
2044
|
const specifiers = importNode.specifiers ?? [];
|
|
1852
2045
|
if (specifiers.length !== 1) continue;
|
|
1853
2046
|
const specifier = specifiers[0];
|
|
@@ -1857,18 +2050,45 @@ function vinext(options = {}) {
|
|
|
1857
2050
|
const dir = path.dirname(id);
|
|
1858
2051
|
const absImagePath = normalizePathSeparators(path.resolve(dir, importPath));
|
|
1859
2052
|
if (!fs.existsSync(absImagePath)) continue;
|
|
2053
|
+
imageImports.add(absImagePath);
|
|
1860
2054
|
const urlVar = `__vinext_img_url_${varName}`;
|
|
1861
2055
|
const metaVar = `__vinext_img_meta_${varName}`;
|
|
1862
|
-
const replacement = `import ${urlVar} from ${JSON.stringify(
|
|
2056
|
+
const replacement = `import ${urlVar} from ${JSON.stringify(absImagePath + "?vinext-image-url")};\nimport ${metaVar} from ${JSON.stringify(absImagePath + "?vinext-meta")};\nconst ${varName} = { src: ${urlVar}, width: ${metaVar}.width, height: ${metaVar}.height };`;
|
|
1863
2057
|
s.overwrite(importNode.start, importNode.end, replacement);
|
|
1864
2058
|
hasChanges = true;
|
|
1865
2059
|
}
|
|
1866
|
-
if (!hasChanges)
|
|
2060
|
+
if (!hasChanges) {
|
|
2061
|
+
staticImageImportsByModule.delete(id);
|
|
2062
|
+
return null;
|
|
2063
|
+
}
|
|
2064
|
+
staticImageImportsByModule.set(id, imageImports);
|
|
1867
2065
|
return {
|
|
1868
2066
|
code: s.toString(),
|
|
1869
2067
|
map: s.generateMap({ hires: "boundary" })
|
|
1870
2068
|
};
|
|
1871
2069
|
}
|
|
2070
|
+
},
|
|
2071
|
+
writeBundle: {
|
|
2072
|
+
sequential: true,
|
|
2073
|
+
order: "post",
|
|
2074
|
+
handler(outputOptions) {
|
|
2075
|
+
if (this.environment?.name !== "client") return;
|
|
2076
|
+
const clientOutDir = outputOptions.dir ? path.resolve(root, outputOptions.dir) : path.resolve(root, options.clientOutDir ?? "dist/client");
|
|
2077
|
+
const assetsDir = resolveAssetsDir(nextConfig.assetPrefix);
|
|
2078
|
+
const activeImagePaths = new Set(Array.from(staticImageImportsByModule.values()).flatMap((imports) => [...imports]));
|
|
2079
|
+
const nextWrittenFiles = /* @__PURE__ */ new Set();
|
|
2080
|
+
for (const imagePath of activeImagePaths) {
|
|
2081
|
+
if (!fs.existsSync(imagePath)) continue;
|
|
2082
|
+
const asset = staticImageAssets.get(imagePath) ?? createStaticImageAsset(imagePath);
|
|
2083
|
+
const outputPath = path.join(clientOutDir, assetsDir, asset.fileName);
|
|
2084
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
2085
|
+
fs.writeFileSync(outputPath, asset.source);
|
|
2086
|
+
nextWrittenFiles.add(outputPath);
|
|
2087
|
+
}
|
|
2088
|
+
for (const outputPath of writtenStaticImageFiles) if (!nextWrittenFiles.has(outputPath)) fs.rmSync(outputPath, { force: true });
|
|
2089
|
+
writtenStaticImageFiles.clear();
|
|
2090
|
+
for (const outputPath of nextWrittenFiles) writtenStaticImageFiles.add(outputPath);
|
|
2091
|
+
}
|
|
1872
2092
|
}
|
|
1873
2093
|
},
|
|
1874
2094
|
createGoogleFontsPlugin(_fontGoogleShimPath, _shimsDir),
|
|
@@ -1881,15 +2101,11 @@ function vinext(options = {}) {
|
|
|
1881
2101
|
filter: {
|
|
1882
2102
|
id: {
|
|
1883
2103
|
include: /\.(tsx?|jsx?|mjs)$/,
|
|
1884
|
-
exclude: /node_modules
|
|
2104
|
+
exclude: [/node_modules/, VIRTUAL_MODULE_ID_RE]
|
|
1885
2105
|
},
|
|
1886
2106
|
code: "use cache"
|
|
1887
2107
|
},
|
|
1888
2108
|
async handler(code, id) {
|
|
1889
|
-
if (id.includes("node_modules")) return null;
|
|
1890
|
-
if (id.startsWith("\0")) return null;
|
|
1891
|
-
if (!id.match(/\.(tsx?|jsx?|mjs)$/)) return null;
|
|
1892
|
-
if (!code.includes("use cache")) return null;
|
|
1893
2109
|
const ast = parseAst(code);
|
|
1894
2110
|
const cacheDirective = ast.body.find((node) => node.type === "ExpressionStatement" && node.expression?.type === "Literal" && typeof node.expression.value === "string" && node.expression.value.startsWith("use cache"));
|
|
1895
2111
|
function nodeHasInlineCacheDirective(node) {
|
|
@@ -2286,54 +2502,56 @@ function vinext(options = {}) {
|
|
|
2286
2502
|
{
|
|
2287
2503
|
name: "vinext:og-font-patch",
|
|
2288
2504
|
enforce: "pre",
|
|
2289
|
-
transform
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2505
|
+
transform: {
|
|
2506
|
+
filter: { id: /@vercel\/og.*index\.edge\.js/ },
|
|
2507
|
+
handler(code, id) {
|
|
2508
|
+
let result = code;
|
|
2509
|
+
const yogaMatch = /H = "data:application\/octet-stream;base64,([A-Za-z0-9+/]+=*)";/.exec(result);
|
|
2510
|
+
if (yogaMatch) {
|
|
2511
|
+
const yogaBase64 = yogaMatch[1];
|
|
2512
|
+
const distDir = path.dirname(id);
|
|
2513
|
+
const yogaWasmPath = path.join(distDir, "yoga.wasm");
|
|
2514
|
+
if (!fs.existsSync(yogaWasmPath)) fs.writeFileSync(yogaWasmPath, Buffer.from(yogaBase64, "base64"));
|
|
2515
|
+
result = result.replace(yogaMatch[0], `H = "";`);
|
|
2516
|
+
const YOGA_CALL = `yoga_wasm_base64_esm_default()`;
|
|
2517
|
+
const YOGA_CALL_PATCHED = [
|
|
2518
|
+
`yoga_wasm_base64_esm_default({ instantiateWasm: function(imports, callback) {`,
|
|
2519
|
+
` __vi_yoga_mod.then(function(mod) {`,
|
|
2520
|
+
` if (mod) {`,
|
|
2521
|
+
` WebAssembly.instantiate(mod, imports).then(function(inst) { callback(inst); });`,
|
|
2522
|
+
` } else {`,
|
|
2523
|
+
` Promise.all([import("node:fs"), import("node:url")]).then(function(mods) {`,
|
|
2524
|
+
` var p = mods[1].fileURLToPath(new URL("./yoga.wasm", import.meta.url));`,
|
|
2525
|
+
` return mods[0].promises.readFile(p).then(function(bytes) {`,
|
|
2526
|
+
` return WebAssembly.instantiate(bytes, imports).then(function(r) { callback(r.instance); });`,
|
|
2527
|
+
` });`,
|
|
2528
|
+
` });`,
|
|
2529
|
+
` }`,
|
|
2530
|
+
` });`,
|
|
2531
|
+
` return {};`,
|
|
2532
|
+
`} })`
|
|
2533
|
+
].join("\n");
|
|
2534
|
+
result = result.replace(YOGA_CALL, YOGA_CALL_PATCHED);
|
|
2535
|
+
result = [`var __vi_yoga_mod = import("./yoga.wasm?module").then(function(m) { return m.default; }).catch(function() { return null; });`].join("\n") + "\n" + result;
|
|
2536
|
+
}
|
|
2537
|
+
const resvgMatch = /import\s+resvg_wasm\s+from\s+["']\.\/resvg\.wasm\?module["']\s*;?/.exec(result);
|
|
2538
|
+
if (resvgMatch) {
|
|
2539
|
+
const resvgLoader = [
|
|
2540
|
+
`var resvg_wasm = import("./resvg.wasm?module").then(function(m) { return m.default; }).catch(function() {`,
|
|
2541
|
+
` return Promise.all([import("node:fs"), import("node:url")]).then(function(mods) {`,
|
|
2542
|
+
` var p = mods[1].fileURLToPath(new URL("./resvg.wasm", import.meta.url));`,
|
|
2543
|
+
` return mods[0].promises.readFile(p).then(function(buf) { return WebAssembly.compile(buf); });`,
|
|
2544
|
+
` });`,
|
|
2545
|
+
`});`
|
|
2546
|
+
].join("\n");
|
|
2547
|
+
result = result.replace(resvgMatch[0], resvgLoader);
|
|
2548
|
+
}
|
|
2549
|
+
if (result === code) return null;
|
|
2550
|
+
return {
|
|
2551
|
+
code: result,
|
|
2552
|
+
map: null
|
|
2553
|
+
};
|
|
2331
2554
|
}
|
|
2332
|
-
if (result === code) return null;
|
|
2333
|
-
return {
|
|
2334
|
-
code: result,
|
|
2335
|
-
map: null
|
|
2336
|
-
};
|
|
2337
2555
|
}
|
|
2338
2556
|
}
|
|
2339
2557
|
];
|