vinext 0.1.4 → 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.
Files changed (126) hide show
  1. package/dist/build/css-url-assets.d.ts +1 -1
  2. package/dist/build/css-url-assets.js +9 -7
  3. package/dist/build/prerender.js +2 -1
  4. package/dist/cache/cache-adapters-virtual.js +1 -1
  5. package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
  6. package/dist/entries/app-rsc-entry.js +24 -20
  7. package/dist/entries/pages-server-entry.js +2 -1
  8. package/dist/index.js +187 -146
  9. package/dist/plugins/css-data-url.js +30 -26
  10. package/dist/plugins/extensionless-dynamic-import.js +27 -24
  11. package/dist/plugins/import-meta-url.js +21 -15
  12. package/dist/plugins/instrumentation-client.js +1 -1
  13. package/dist/plugins/middleware-server-only.js +7 -6
  14. package/dist/plugins/og-assets.js +48 -46
  15. package/dist/plugins/optimize-imports.js +9 -3
  16. package/dist/plugins/remove-console.d.ts +7 -1
  17. package/dist/plugins/remove-console.js +4 -1
  18. package/dist/plugins/require-context.js +21 -20
  19. package/dist/plugins/strip-server-exports.d.ts +7 -1
  20. package/dist/plugins/strip-server-exports.js +4 -1
  21. package/dist/server/app-bfcache-identity.d.ts +26 -0
  22. package/dist/server/app-bfcache-identity.js +127 -0
  23. package/dist/server/app-browser-entry.js +14 -11
  24. package/dist/server/app-browser-navigation-controller.js +1 -1
  25. package/dist/server/app-browser-state.d.ts +2 -21
  26. package/dist/server/app-browser-state.js +4 -128
  27. package/dist/server/app-browser-stream.js +1 -1
  28. package/dist/server/app-browser-visible-commit.js +3 -2
  29. package/dist/server/app-fallback-renderer.d.ts +1 -1
  30. package/dist/server/app-layout-param-observation.d.ts +1 -1
  31. package/dist/server/app-layout-param-observation.js +1 -1
  32. package/dist/server/app-middleware.js +2 -1
  33. package/dist/server/app-page-boundary-render.d.ts +1 -1
  34. package/dist/server/app-page-boundary.js +1 -1
  35. package/dist/server/app-page-cache-finalizer.d.ts +62 -0
  36. package/dist/server/app-page-cache-finalizer.js +122 -0
  37. package/dist/server/app-page-cache-render.d.ts +2 -2
  38. package/dist/server/app-page-cache-render.js +1 -1
  39. package/dist/server/app-page-cache.d.ts +2 -53
  40. package/dist/server/app-page-cache.js +5 -131
  41. package/dist/server/app-page-dispatch.d.ts +2 -2
  42. package/dist/server/app-page-dispatch.js +10 -8
  43. package/dist/server/app-page-probe.js +3 -2
  44. package/dist/server/app-page-render-observation.js +2 -2
  45. package/dist/server/app-page-render.d.ts +3 -3
  46. package/dist/server/app-page-render.js +3 -2
  47. package/dist/server/app-page-stream.d.ts +2 -9
  48. package/dist/server/app-page-stream.js +1 -35
  49. package/dist/server/app-request-context.d.ts +1 -2
  50. package/dist/server/app-request-context.js +2 -1
  51. package/dist/server/app-route-handler-dispatch.js +3 -2
  52. package/dist/server/app-route-handler-execution.d.ts +1 -1
  53. package/dist/server/app-route-handler-execution.js +1 -1
  54. package/dist/server/app-route-handler-response.d.ts +1 -1
  55. package/dist/server/app-router-entry.js +2 -1
  56. package/dist/server/app-rsc-handler.js +22 -16
  57. package/dist/server/app-rsc-response-finalizer.js +1 -1
  58. package/dist/server/app-server-action-execution.d.ts +1 -1
  59. package/dist/server/app-server-action-execution.js +5 -4
  60. package/dist/server/app-ssr-entry.d.ts +1 -1
  61. package/dist/server/app-ssr-entry.js +11 -9
  62. package/dist/server/app-ssr-router-instance.d.ts +6 -0
  63. package/dist/server/app-ssr-router-instance.js +24 -0
  64. package/dist/server/app-ssr-stream.js +1 -1
  65. package/dist/server/artifact-compatibility.js +1 -1
  66. package/dist/server/client-reuse-manifest.js +1 -1
  67. package/dist/server/defer-until-stream-consumed.d.ts +7 -0
  68. package/dist/server/defer-until-stream-consumed.js +34 -0
  69. package/dist/server/dev-server.js +1 -1
  70. package/dist/server/instrumentation.js +1 -1
  71. package/dist/server/isr-cache.d.ts +1 -1
  72. package/dist/server/isr-cache.js +1 -1
  73. package/dist/server/isr-decision.d.ts +1 -1
  74. package/dist/server/middleware-matcher.js +8 -6
  75. package/dist/server/middleware-runtime.js +2 -2
  76. package/dist/server/open-redirect.d.ts +12 -0
  77. package/dist/server/open-redirect.js +21 -0
  78. package/dist/server/pages-page-data.d.ts +1 -1
  79. package/dist/server/pages-page-response.d.ts +1 -1
  80. package/dist/server/pages-page-response.js +2 -2
  81. package/dist/server/prod-server.js +2 -1
  82. package/dist/server/request-pipeline.d.ts +1 -24
  83. package/dist/server/request-pipeline.js +1 -33
  84. package/dist/server/seed-cache.d.ts +1 -1
  85. package/dist/shims/cache-handler.d.ts +106 -0
  86. package/dist/shims/cache-handler.js +176 -0
  87. package/dist/shims/cache-request-state.d.ts +47 -0
  88. package/dist/shims/cache-request-state.js +126 -0
  89. package/dist/shims/cache-runtime.d.ts +2 -2
  90. package/dist/shims/cache-runtime.js +3 -14
  91. package/dist/shims/cache.d.ts +3 -231
  92. package/dist/shims/cache.js +17 -383
  93. package/dist/shims/cdn-cache.d.ts +1 -1
  94. package/dist/shims/cdn-cache.js +1 -1
  95. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  96. package/dist/shims/error-boundary-navigation.js +44 -0
  97. package/dist/shims/error-boundary.js +10 -8
  98. package/dist/shims/error.js +2 -1
  99. package/dist/shims/fetch-cache.js +1 -1
  100. package/dist/shims/form.js +1 -1
  101. package/dist/shims/image.js +67 -9
  102. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
  103. package/dist/shims/internal/app-page-props-cache-key.js +16 -0
  104. package/dist/shims/internal/navigation-untracked.js +2 -1
  105. package/dist/shims/layout-segment-context.d.ts +1 -1
  106. package/dist/shims/layout-segment-context.js +2 -1
  107. package/dist/shims/link.js +2 -2
  108. package/dist/shims/navigation-context-state.d.ts +40 -0
  109. package/dist/shims/navigation-context-state.js +116 -0
  110. package/dist/shims/navigation-errors.d.ts +55 -0
  111. package/dist/shims/navigation-errors.js +110 -0
  112. package/dist/shims/navigation-server.d.ts +3 -0
  113. package/dist/shims/navigation-server.js +3 -0
  114. package/dist/shims/navigation-state.d.ts +1 -2
  115. package/dist/shims/navigation-state.js +2 -1
  116. package/dist/shims/navigation.d.ts +3 -291
  117. package/dist/shims/navigation.js +14 -445
  118. package/dist/shims/navigation.react-server.d.ts +2 -2
  119. package/dist/shims/navigation.react-server.js +3 -1
  120. package/dist/shims/request-state-types.d.ts +3 -3
  121. package/dist/shims/script.js +1 -1
  122. package/dist/shims/slot.js +3 -1
  123. package/dist/shims/unified-request-context.d.ts +2 -2
  124. package/dist/utils/virtual-module.d.ts +5 -0
  125. package/dist/utils/virtual-module.js +0 -0
  126. 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
9
  import { matchesRewriteSource, proxyExternalRequest } from "./config/config-matchers.js";
9
- import { filterInternalHeaders, isOpenRedirectShaped, normalizeTrailingSlash } from "./server/request-pipeline.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";
@@ -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 { hasExportAllCandidate, hasServerExportCandidate, stripServerExports, validatePageExports } 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";
@@ -84,6 +87,10 @@ 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);
@@ -300,10 +307,13 @@ const RESOLVED_ROOT_PARAMS = "\0virtual:vinext-root-params";
300
307
  const RESOLVED_CACHE_ADAPTERS = "\0" + VIRTUAL_CACHE_ADAPTERS;
301
308
  /** Virtual module for composed instrumentation-client bootstrap. */
302
309
  const VIRTUAL_INSTRUMENTATION_CLIENT = "private-next-instrumentation-client";
303
- const RESOLVED_INSTRUMENTATION_CLIENT = `\0${VIRTUAL_INSTRUMENTATION_CLIENT}.mjs`;
310
+ const RESOLVED_INSTRUMENTATION_CLIENT = `${VIRTUAL_INSTRUMENTATION_CLIENT}.mjs`;
304
311
  /** Image file extensions handled by the vinext:image-imports plugin.
305
312
  * Shared between the Rolldown hook filter and the transform handler regex. */
306
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})$`);
307
317
  function createStaticImageAsset(imagePath) {
308
318
  const source = fs.readFileSync(imagePath);
309
319
  const extension = path.extname(imagePath);
@@ -321,6 +331,8 @@ function createStaticImageAsset(imagePath) {
321
331
  */
322
332
  const _shimsDir = normalizePathSeparators(path.resolve(__dirname, "shims")) + "/";
323
333
  const _fontGoogleShimPath = resolveShimModulePath(_shimsDir, "font-google");
334
+ const _appRscHandlerPath = resolveShimModulePath(path.resolve(__dirname, "server"), "app-rsc-handler");
335
+ const _canExternalizeAppRscHandler = _appRscHandlerPath.endsWith(".js");
324
336
  function isValidExportIdentifier(name) {
325
337
  return /^[$A-Z_a-z][$\w]*$/.test(name);
326
338
  }
@@ -435,9 +447,10 @@ function vinext(options = {}) {
435
447
  let rscCompatibilityId;
436
448
  const draftModeSecret = randomUUID();
437
449
  const sassComposesLoader = createSassAwareFileSystemLoader();
450
+ const typeofWindowIdFilter = { exclude: /(?!)/ };
438
451
  let rscClassificationManifest = null;
439
452
  const shimsDir = path.resolve(__dirname, "shims");
440
- const canonicalize = (p) => tryRealpathSync(p) ?? p;
453
+ const canonicalize = (p) => normalizePathSeparators(tryRealpathSync(p) ?? p);
441
454
  const pageTransformCanonicalPaths = /* @__PURE__ */ new Map();
442
455
  const canonicalizePageTransformPath = (modulePath) => {
443
456
  const cached = pageTransformCanonicalPaths.get(modulePath);
@@ -561,22 +574,25 @@ function vinext(options = {}) {
561
574
  ...viteMajorVersion >= 8 ? [{
562
575
  name: "vinext:jsx-in-js",
563
576
  enforce: "pre",
564
- async transform(code, id) {
565
- const cleanId = id.split("?")[0];
566
- if (!/\.(m?js)$/.test(cleanId)) return;
567
- if (cleanId.includes("/node_modules/")) {
568
- if (!code.includes("use client") && !code.includes("use server")) return;
569
- if (!hasReactDirective(code)) return;
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
+ };
570
595
  }
571
- const result = await transformWithOxc(code, id, {
572
- lang: "jsx",
573
- jsx: { runtime: "automatic" },
574
- sourcemap: true
575
- });
576
- return {
577
- code: result.code,
578
- map: result.map
579
- };
580
596
  }
581
597
  }] : [],
582
598
  createMiddlewareServerOnlyPlugin({
@@ -905,6 +921,7 @@ function vinext(options = {}) {
905
921
  "satori",
906
922
  "@resvg/resvg-js",
907
923
  "yoga-wasm-web",
924
+ ...env?.command === "serve" && _canExternalizeAppRscHandler ? ["vinext/server/app-rsc-handler"] : [],
908
925
  ...userSsrExternal
909
926
  ],
910
927
  ...userSsrExternal === true ? {} : { noExternal: true }
@@ -1031,6 +1048,8 @@ function vinext(options = {}) {
1031
1048
  return null;
1032
1049
  },
1033
1050
  async configResolved(config) {
1051
+ const cacheDirPrefix = getCacheDirPrefix(config.cacheDir);
1052
+ typeofWindowIdFilter.exclude = new RegExp(`^${escapeRegExp(cacheDirPrefix)}`);
1034
1053
  sassComposesLoader.setResolvedConfig(config);
1035
1054
  if (config.command === "build" && hasAppDir && hasPagesDir) {
1036
1055
  const [appRoutes, pageRoutes, apiRoutes] = await Promise.all([
@@ -1067,9 +1086,16 @@ function vinext(options = {}) {
1067
1086
  }));
1068
1087
  },
1069
1088
  resolveId: {
1070
- 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)?$)/ },
1071
1090
  handler(id, importer) {
1072
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
+ }
1073
1099
  if (isVercelOgImport(cleanId) && !isVinextOgShimImporter(importer)) return resolveShimModulePath(_shimsDir, "og");
1074
1100
  if (cleanId.startsWith("vinext/shims/")) return resolveShimModulePath(_shimsDir, stripJsExtension(stripViteModuleQuery(cleanId.slice(13))));
1075
1101
  if (cleanId === VIRTUAL_SERVER_ENTRY) return RESOLVED_SERVER_ENTRY;
@@ -1188,14 +1214,19 @@ function vinext(options = {}) {
1188
1214
  name: "vinext:css-url-assets-mark",
1189
1215
  enforce: "pre",
1190
1216
  apply: "build",
1191
- transform(code, id) {
1192
- if (this.environment?.name !== "client") return null;
1193
- const marked = markCssUrlAssetReferences(code, id);
1194
- if (marked === null) return null;
1195
- return {
1196
- code: marked,
1197
- map: null
1198
- };
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
+ }
1199
1230
  }
1200
1231
  },
1201
1232
  {
@@ -1220,7 +1251,6 @@ function vinext(options = {}) {
1220
1251
  enforce: "post",
1221
1252
  apply: "build",
1222
1253
  generateBundle(_options, bundle) {
1223
- if (this.environment?.name !== "client") return;
1224
1254
  restoreDedupedCssAssetReferences(bundle, (asset) => {
1225
1255
  this.emitFile({
1226
1256
  type: "asset",
@@ -1298,18 +1328,20 @@ function vinext(options = {}) {
1298
1328
  `export const addTransitionType = _React.addTransitionType || function addTransitionType() {};`
1299
1329
  ].join("\n");
1300
1330
  },
1301
- transform(code, id) {
1302
- if (id.includes("node_modules")) return null;
1303
- if (id.startsWith("\0")) return null;
1304
- if (!/\.(tsx?|jsx?|mjs)$/.test(id)) return null;
1305
- if (!(code.includes("ViewTransition") || code.includes("addTransitionType")) || !/from\s+['"]react['"]/.test(code)) return null;
1306
- if (!/import\s*\{[^}]*(ViewTransition|addTransitionType)[^}]*\}\s*from\s*['"]react['"]/.test(code)) return null;
1307
- const result = code.replace(/from\s*['"]react['"]/g, "from \"virtual:vinext-react-canary\"");
1308
- if (result !== code) return {
1309
- code: result,
1310
- map: null
1311
- };
1312
- return null;
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
+ }
1313
1345
  }
1314
1346
  },
1315
1347
  {
@@ -1828,50 +1860,59 @@ function vinext(options = {}) {
1828
1860
  },
1829
1861
  {
1830
1862
  name: "vinext:validate-page-exports",
1831
- transform: { handler(code, id) {
1832
- if (this.environment?.name !== "client") return null;
1833
- if (!hasPagesDir || id.startsWith("\0") || !hasExportAllCandidate(code)) return null;
1834
- const modulePath = stripViteModuleQuery(id);
1835
- if (!isWithinPagesDirectory(modulePath)) return null;
1836
- const canonicalId = canonicalizePageTransformPath(modulePath);
1837
- if (!isWithinPagesDirectory(canonicalId)) return null;
1838
- if (!fileMatcher.isPageFile(canonicalId)) return null;
1839
- if (isApiPage(canonicalId)) return null;
1840
- validatePageExports(code);
1841
- return null;
1842
- } }
1863
+ transform: {
1864
+ filter: {
1865
+ id: { exclude: VIRTUAL_MODULE_ID_RE },
1866
+ code: /\bexport\b[\s\S]*\*/
1867
+ },
1868
+ handler(code, id) {
1869
+ if (this.environment?.name !== "client") return null;
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;
1879
+ }
1880
+ }
1843
1881
  },
1844
1882
  {
1845
1883
  name: "vinext:strip-server-exports",
1846
- transform: { handler(code, id) {
1847
- if (this.environment?.name !== "client") return null;
1848
- if (!hasPagesDir || id.startsWith("\0") || !hasServerExportCandidate(code)) return null;
1849
- const modulePath = stripViteModuleQuery(id);
1850
- if (!isWithinPagesDirectory(modulePath)) return null;
1851
- const canonicalId = canonicalizePageTransformPath(modulePath);
1852
- if (!isWithinPagesDirectory(canonicalId)) return null;
1853
- if (!fileMatcher.isPageFile(canonicalId)) return null;
1854
- const relativePath = canonicalId.slice(canonicalPagesDir.length);
1855
- if (isApiPage(canonicalId)) return null;
1856
- if (/^\/(?:_app|_document|_error)(?:\.[^/]*)?$/.test(relativePath)) return null;
1857
- const result = stripServerExports(code);
1858
- if (!result) return null;
1859
- return {
1860
- code: result,
1861
- map: null
1862
- };
1863
- } }
1884
+ transform: {
1885
+ filter: {
1886
+ id: { exclude: VIRTUAL_MODULE_ID_RE },
1887
+ code: /getServerSideProps|getStaticProps|getStaticPaths|unstable_getServerProps|unstable_getServerSideProps|unstable_getStaticProps|unstable_getStaticPaths/
1888
+ },
1889
+ handler(code, id) {
1890
+ if (this.environment?.name !== "client") return null;
1891
+ if (!hasPagesDir) return null;
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
+ }
1864
1903
  },
1865
1904
  {
1866
1905
  name: "vinext:validate-server-only-client-imports",
1867
1906
  transform: {
1868
1907
  filter: {
1869
- id: /\.(tsx?|jsx?|mjs)$/,
1908
+ id: {
1909
+ include: /\.(tsx?|jsx?|mjs)$/,
1910
+ exclude: VIRTUAL_MODULE_ID_RE
1911
+ },
1870
1912
  code: "server-only"
1871
1913
  },
1872
- handler(code, id) {
1914
+ handler(code) {
1873
1915
  if (this.environment?.name !== "client") return null;
1874
- if (id.startsWith("\0")) return null;
1875
1916
  if (getLeadingReactDirective(code) === "use server") return null;
1876
1917
  if (!hasServerOnlyMarkerImport(code)) return null;
1877
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.`);
@@ -1882,17 +1923,17 @@ function vinext(options = {}) {
1882
1923
  name: "vinext:remove-console",
1883
1924
  apply: "build",
1884
1925
  transform: {
1885
- filter: { id: /\.(tsx?|jsx?|mjs)$/ },
1886
- handler(code, id) {
1926
+ filter: {
1927
+ id: {
1928
+ include: /\.(tsx?|jsx?|mjs)$/,
1929
+ exclude: /\/node_modules\//
1930
+ },
1931
+ code: /\bconsole\b/
1932
+ },
1933
+ handler(code) {
1887
1934
  if (this.environment?.name !== "client") return null;
1888
1935
  if (!nextConfig.removeConsole) return null;
1889
- if (id.includes("/node_modules/")) return null;
1890
- const result = removeConsoleCalls(code, nextConfig.removeConsole);
1891
- if (!result) return null;
1892
- return {
1893
- code: result,
1894
- map: null
1895
- };
1936
+ return removeConsoleCalls(code, nextConfig.removeConsole);
1896
1937
  }
1897
1938
  }
1898
1939
  },
@@ -1900,8 +1941,13 @@ function vinext(options = {}) {
1900
1941
  name: "vinext:typeof-window",
1901
1942
  enforce: "post",
1902
1943
  transform: {
1903
- filter: { code: /typeof\s+window/ },
1904
- handler(code) {
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;
1905
1951
  return replaceTypeofWindow(code, getTypeofWindowReplacement(this.environment));
1906
1952
  }
1907
1953
  }
@@ -1926,9 +1972,10 @@ function vinext(options = {}) {
1926
1972
  staticImageAssets.clear();
1927
1973
  },
1928
1974
  watchChange(id) {
1929
- imageImportDimCache.delete(id);
1930
- staticImageAssets.delete(id);
1931
- staticImageImportsByModule.delete(id);
1975
+ const key = normalizePathSeparators(id);
1976
+ imageImportDimCache.delete(key);
1977
+ staticImageAssets.delete(key);
1978
+ staticImageImportsByModule.delete(key);
1932
1979
  },
1933
1980
  resolveId: {
1934
1981
  filter: { id: /\?vinext-(?:image-url|meta)$/ },
@@ -1973,15 +2020,11 @@ function vinext(options = {}) {
1973
2020
  filter: {
1974
2021
  id: {
1975
2022
  include: /\.(tsx?|jsx?|mjs)$/,
1976
- exclude: /node_modules/
2023
+ exclude: [/node_modules/, VIRTUAL_MODULE_ID_RE]
1977
2024
  },
1978
2025
  code: new RegExp(`import\\s+\\w+\\s+from\\s+['"][^'"]+\\.(${IMAGE_EXTS})['"]`)
1979
2026
  },
1980
2027
  async handler(code, id) {
1981
- if (id.includes("node_modules")) return null;
1982
- if (id.startsWith("\0")) return null;
1983
- if (!id.match(/\.(tsx?|jsx?|mjs)$/)) return null;
1984
- const imageExtRe = new RegExp(`\\.(${IMAGE_EXTS})$`);
1985
2028
  const lang = id.endsWith(".ts") ? "ts" : "tsx";
1986
2029
  let ast;
1987
2030
  try {
@@ -1997,7 +2040,7 @@ function vinext(options = {}) {
1997
2040
  const importNode = node;
1998
2041
  const importPath = importNode.source?.value;
1999
2042
  if (typeof importPath !== "string") continue;
2000
- if (!imageExtRe.test(importPath)) continue;
2043
+ if (!IMAGE_EXT_RE.test(importPath)) continue;
2001
2044
  const specifiers = importNode.specifiers ?? [];
2002
2045
  if (specifiers.length !== 1) continue;
2003
2046
  const specifier = specifiers[0];
@@ -2058,15 +2101,11 @@ function vinext(options = {}) {
2058
2101
  filter: {
2059
2102
  id: {
2060
2103
  include: /\.(tsx?|jsx?|mjs)$/,
2061
- exclude: /node_modules/
2104
+ exclude: [/node_modules/, VIRTUAL_MODULE_ID_RE]
2062
2105
  },
2063
2106
  code: "use cache"
2064
2107
  },
2065
2108
  async handler(code, id) {
2066
- if (id.includes("node_modules")) return null;
2067
- if (id.startsWith("\0")) return null;
2068
- if (!id.match(/\.(tsx?|jsx?|mjs)$/)) return null;
2069
- if (!code.includes("use cache")) return null;
2070
2109
  const ast = parseAst(code);
2071
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"));
2072
2111
  function nodeHasInlineCacheDirective(node) {
@@ -2463,54 +2502,56 @@ function vinext(options = {}) {
2463
2502
  {
2464
2503
  name: "vinext:og-font-patch",
2465
2504
  enforce: "pre",
2466
- transform(code, id) {
2467
- if (!id.includes("@vercel/og") || !id.includes("index.edge.js")) return null;
2468
- let result = code;
2469
- const yogaMatch = /H = "data:application\/octet-stream;base64,([A-Za-z0-9+/]+=*)";/.exec(result);
2470
- if (yogaMatch) {
2471
- const yogaBase64 = yogaMatch[1];
2472
- const distDir = path.dirname(id);
2473
- const yogaWasmPath = path.join(distDir, "yoga.wasm");
2474
- if (!fs.existsSync(yogaWasmPath)) fs.writeFileSync(yogaWasmPath, Buffer.from(yogaBase64, "base64"));
2475
- result = result.replace(yogaMatch[0], `H = "";`);
2476
- const YOGA_CALL = `yoga_wasm_base64_esm_default()`;
2477
- const YOGA_CALL_PATCHED = [
2478
- `yoga_wasm_base64_esm_default({ instantiateWasm: function(imports, callback) {`,
2479
- ` __vi_yoga_mod.then(function(mod) {`,
2480
- ` if (mod) {`,
2481
- ` WebAssembly.instantiate(mod, imports).then(function(inst) { callback(inst); });`,
2482
- ` } else {`,
2483
- ` Promise.all([import("node:fs"), import("node:url")]).then(function(mods) {`,
2484
- ` var p = mods[1].fileURLToPath(new URL("./yoga.wasm", import.meta.url));`,
2485
- ` return mods[0].promises.readFile(p).then(function(bytes) {`,
2486
- ` return WebAssembly.instantiate(bytes, imports).then(function(r) { callback(r.instance); });`,
2487
- ` });`,
2488
- ` });`,
2489
- ` }`,
2490
- ` });`,
2491
- ` return {};`,
2492
- `} })`
2493
- ].join("\n");
2494
- result = result.replace(YOGA_CALL, YOGA_CALL_PATCHED);
2495
- result = [`var __vi_yoga_mod = import("./yoga.wasm?module").then(function(m) { return m.default; }).catch(function() { return null; });`].join("\n") + "\n" + result;
2496
- }
2497
- const resvgMatch = /import\s+resvg_wasm\s+from\s+["']\.\/resvg\.wasm\?module["']\s*;?/.exec(result);
2498
- if (resvgMatch) {
2499
- const resvgLoader = [
2500
- `var resvg_wasm = import("./resvg.wasm?module").then(function(m) { return m.default; }).catch(function() {`,
2501
- ` return Promise.all([import("node:fs"), import("node:url")]).then(function(mods) {`,
2502
- ` var p = mods[1].fileURLToPath(new URL("./resvg.wasm", import.meta.url));`,
2503
- ` return mods[0].promises.readFile(p).then(function(buf) { return WebAssembly.compile(buf); });`,
2504
- ` });`,
2505
- `});`
2506
- ].join("\n");
2507
- result = result.replace(resvgMatch[0], resvgLoader);
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
+ };
2508
2554
  }
2509
- if (result === code) return null;
2510
- return {
2511
- code: result,
2512
- map: null
2513
- };
2514
2555
  }
2515
2556
  }
2516
2557
  ];
@@ -36,33 +36,37 @@ function dataUrlCssPlugin() {
36
36
  return {
37
37
  name: "vinext:css-data-url",
38
38
  enforce: "pre",
39
- transform(code, id) {
40
- if (!code.includes(DATA_URL_HINT)) return null;
41
- if (id.startsWith(VIRTUAL_PREFIX)) return null;
42
- let mutated = false;
43
- const rewritten = code.replace(DATA_URL_IMPORT_RE, (_match, quote, moduleFlag, base64Flag, payload) => {
44
- const isModule = moduleFlag === "+module";
45
- const isBase64 = base64Flag === ";base64";
46
- let css;
47
- try {
48
- css = decode(payload, isBase64);
49
- } catch (err) {
50
- throw new Error(`[vinext] Failed to decode CSS data URL import in ${id}: ${err.message}`);
51
- }
52
- const ext = isModule ? ".module.css" : ".css";
53
- const syntheticId = `${VIRTUAL_PREFIX}${hash(css + ext)}${ext}`;
54
- entries.set(syntheticId, {
55
- css,
56
- isModule
39
+ transform: {
40
+ filter: {
41
+ id: { exclude: new RegExp(`^${VIRTUAL_PREFIX}`) },
42
+ code: DATA_URL_HINT
43
+ },
44
+ handler(code, id) {
45
+ let mutated = false;
46
+ const rewritten = code.replace(DATA_URL_IMPORT_RE, (_match, quote, moduleFlag, base64Flag, payload) => {
47
+ const isModule = moduleFlag === "+module";
48
+ const isBase64 = base64Flag === ";base64";
49
+ let css;
50
+ try {
51
+ css = decode(payload, isBase64);
52
+ } catch (err) {
53
+ throw new Error(`[vinext] Failed to decode CSS data URL import in ${id}: ${err.message}`);
54
+ }
55
+ const ext = isModule ? ".module.css" : ".css";
56
+ const syntheticId = `${VIRTUAL_PREFIX}${hash(css + ext)}${ext}`;
57
+ entries.set(syntheticId, {
58
+ css,
59
+ isModule
60
+ });
61
+ mutated = true;
62
+ return `${quote}${syntheticId}${quote}`;
57
63
  });
58
- mutated = true;
59
- return `${quote}${syntheticId}${quote}`;
60
- });
61
- if (!mutated) return null;
62
- return {
63
- code: rewritten,
64
- map: null
65
- };
64
+ if (!mutated) return null;
65
+ return {
66
+ code: rewritten,
67
+ map: null
68
+ };
69
+ }
66
70
  },
67
71
  resolveId(id) {
68
72
  if (id.startsWith(VIRTUAL_PREFIX)) return id;
@@ -29,28 +29,34 @@ function createExtensionlessDynamicImportPlugin() {
29
29
  configResolved(config) {
30
30
  moduleExtensions = getModuleExtensions(config);
31
31
  },
32
- transform(code, id) {
33
- if (!/\bimport\s*\(/.test(code)) return null;
34
- if (isDependencyId(id)) return null;
35
- const lang = langForId(id);
36
- if (!lang) return null;
37
- let ast;
38
- try {
39
- ast = parseAst(code, { lang });
40
- } catch {
41
- return null;
32
+ transform: {
33
+ filter: {
34
+ id: {
35
+ include: /\.(?:[cm]?[jt]s|[jt]sx)(?:\?.*)?$/i,
36
+ exclude: /[\\/]node_modules[\\/]/
37
+ },
38
+ code: /\bimport\s*\(/
39
+ },
40
+ handler(code, id) {
41
+ const lang = langForId(id);
42
+ let ast;
43
+ try {
44
+ ast = parseAst(code, { lang });
45
+ } catch {
46
+ return null;
47
+ }
48
+ const imports = collectExtensionlessImports(ast, code, moduleExtensions);
49
+ if (imports.length === 0) return null;
50
+ const output = new MagicString(code);
51
+ for (const dynamicImport of imports) {
52
+ const source = code.slice(dynamicImport.sourceStart, dynamicImport.sourceEnd);
53
+ output.overwrite(dynamicImport.start, dynamicImport.end, buildReplacement(source, dynamicImport.globPattern, dynamicImport.moduleExtensions));
54
+ }
55
+ return {
56
+ code: output.toString(),
57
+ map: output.generateMap({ hires: "boundary" })
58
+ };
42
59
  }
43
- const imports = collectExtensionlessImports(ast, code, moduleExtensions);
44
- if (imports.length === 0) return null;
45
- const output = new MagicString(code);
46
- for (const dynamicImport of imports) {
47
- const source = code.slice(dynamicImport.sourceStart, dynamicImport.sourceEnd);
48
- output.overwrite(dynamicImport.start, dynamicImport.end, buildReplacement(source, dynamicImport.globPattern, dynamicImport.moduleExtensions));
49
- }
50
- return {
51
- code: output.toString(),
52
- map: output.generateMap({ hires: "boundary" })
53
- };
54
60
  }
55
61
  };
56
62
  }
@@ -64,9 +70,6 @@ function langForId(id) {
64
70
  if (ext === ".tsx") return "tsx";
65
71
  return "jsx";
66
72
  }
67
- function isDependencyId(id) {
68
- return id.split("?", 1)[0].replaceAll("\\", "/").includes("/node_modules/");
69
- }
70
73
  function collectExtensionlessImports(ast, code, moduleExtensions) {
71
74
  const imports = [];
72
75
  function visit(value) {