@nuxt/nitro-server-nightly 4.6.0-29776167.796cdae2 → 4.6.0-29778602.bfddf2f0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -21,7 +21,7 @@ import { ImpoundPlugin } from "impound";
21
21
  import { resolveModulePath } from "exsolve";
22
22
  import { runtimeDependencies } from "nitropack/runtime/meta";
23
23
  //#region package.json
24
- var version = "4.6.0-29776167.796cdae2";
24
+ var version = "4.6.0-29778602.bfddf2f0";
25
25
  //#endregion
26
26
  //#region src/utils.ts
27
27
  function toArray(value) {
@@ -327,6 +327,8 @@ const NUXT_BUILD_OUTPUT_MAP = {
327
327
  "nuxt/entry-ids": "entryIds"
328
328
  };
329
329
  async function bundle(nuxt) {
330
+ const errorPageOption = nuxt.options.experimental.prerenderErrorPages;
331
+ const errorPages = errorPageOption === true ? [404] : errorPageOption || [];
330
332
  const layerDirs = getLayerDirectories(nuxt);
331
333
  const excludePattern = [getLayerNodeModulesExcludePattern(layerDirs.map((dirs) => dirs.root))];
332
334
  const layerPublicAssetsDirs = [];
@@ -454,8 +456,15 @@ async function bundle(nuxt) {
454
456
  const hasCachedRoutes = Object.values(nitro.options.routeRules).some((r) => r.isr || r.cache);
455
457
  const noScriptsPatterns = [...new Set(Object.entries(nitro.options.routeRules).filter(([_route, rules]) => rules.noScripts).map(([route]) => rou3PatternToURLPattern(route).pattern))];
456
458
  const pagePatterns = nitro.options._noScriptsPagePatterns ?? [];
459
+ const noSSRRoutes = [
460
+ "/index.html",
461
+ "/200.html",
462
+ "/404.html"
463
+ ].filter((route) => !errorPages.includes(Number(route.slice(1, -5))));
457
464
  return [
458
465
  `export const NUXT_NO_SSR = ${nuxt.options.ssr === false}`,
466
+ `export const NUXT_PRERENDER_ERROR_PAGES = ${JSON.stringify(errorPages)}`,
467
+ `export const NUXT_PRERENDER_NO_SSR_ROUTES = ${JSON.stringify(noSSRRoutes)}`,
459
468
  `export const NUXT_EARLY_HINTS = ${nuxt.options.experimental.writeEarlyHints !== false}`,
460
469
  `export const NUXT_NO_SCRIPTS = ${nuxt.options.features.noScripts === "all" || !!nuxt.options.features.noScripts && !nuxt.options.dev}`,
461
470
  `export const NUXT_NO_SCRIPTS_PROD = ${nuxt.options.features.noScripts === "production"}`,
@@ -849,11 +858,14 @@ async function bundle(nuxt) {
849
858
  "h3",
850
859
  "h3/package.json"
851
860
  ];
852
- const basePath = nitroConfig.typescript.tsConfig.compilerOptions?.baseUrl ? resolve(nuxt.options.buildDir, nitroConfig.typescript.tsConfig.compilerOptions?.baseUrl) : nuxt.options.buildDir;
861
+ const isV5OrHigher = nuxt.options.future.compatibilityVersion >= 5;
862
+ const baseUrl = isV5OrHigher ? void 0 : nitroConfig.typescript.tsConfig.compilerOptions?.baseUrl;
863
+ const basePath = baseUrl ? resolve(nuxt.options.buildDir, baseUrl) : nuxt.options.buildDir;
853
864
  const aliases = nitroConfig.alias;
854
865
  const importPaths = nuxt.options.modulesDir.map((d) => pathToFileURL(withTrailingSlash(d)));
855
866
  const tsConfig = nitroConfig.typescript.tsConfig;
856
867
  tsConfig.compilerOptions ||= {};
868
+ if (isV5OrHigher) Reflect.deleteProperty(tsConfig.compilerOptions, "baseUrl");
857
869
  tsConfig.compilerOptions.paths ||= {};
858
870
  for (const _alias in aliases) {
859
871
  const alias = _alias;
@@ -1050,6 +1062,7 @@ async function bundle(nuxt) {
1050
1062
  });
1051
1063
  if (nitro.options.static) nitro.hooks.hook("prerender:routes", (routes) => {
1052
1064
  for (const route of ["/200.html", "/404.html"]) routes.add(route);
1065
+ for (const status of errorPages) routes.add(`/${status}.html`);
1053
1066
  if (!nuxt.options.ssr) routes.add("/index.html");
1054
1067
  });
1055
1068
  if (!nuxt.options.dev) nitro.hooks.hook("rollup:before", async (nitro) => {
@@ -8,6 +8,7 @@ import { createSSRContext } from "../utils/renderer/app.mjs";
8
8
  import { getSSRRenderer } from "../utils/renderer/build-files.mjs";
9
9
  import { renderInlineStyles } from "../utils/renderer/inline-styles.mjs";
10
10
  import { getClientIslandResponse, getServerComponentHTML, getSlotIslandResponse } from "../utils/renderer/islands.mjs";
11
+ import { isStyleOfModule } from "../utils/renderer/dev-css.mjs";
11
12
  import { getQuery } from "ufo";
12
13
  import { createError, defineEventHandler, getQuery as getQuery$1, getRequestHeader, getRequestWebStream, setResponseHeader, setResponseHeaders, setResponseStatus } from "h3";
13
14
  import { useNitroApp } from "nitropack/runtime";
@@ -108,9 +109,10 @@ async function renderIsland(event) {
108
109
  if (import.meta.dev) {
109
110
  const { styles } = getRequestDependencies(ssrContext, renderer.rendererContext);
110
111
  const link = [];
112
+ const modules = ssrContext.modules ?? [];
111
113
  for (const resource of Object.values(styles)) {
112
114
  if ("inline" in getQuery(resource.file)) continue;
113
- if (resource.file.includes("scoped") && !resource.file.includes("pages/")) link.push({
115
+ if (isStyleOfModule(resource.file, modules)) link.push({
114
116
  rel: "stylesheet",
115
117
  href: renderer.rendererContext.buildAssetsURL(resource.file),
116
118
  crossorigin: ""
@@ -7,6 +7,7 @@ import { APP_ROOT_CLOSE_TAG, APP_ROOT_OPEN_TAG, getRenderer, getServerApp } from
7
7
  import { renderInlineStyles } from "../utils/renderer/inline-styles.mjs";
8
8
  import { renderStreamedIslandTeleports, replaceIslandTeleports } from "../utils/renderer/islands.mjs";
9
9
  import { renderPayloadJsonScript, renderPayloadResponse, renderPayloadScript, splitPayload } from "../utils/renderer/payload.mjs";
10
+ import { createInlinedCSSFilter } from "../utils/renderer/inlined-css.mjs";
10
11
  import { warnNoScriptsClientReliance } from "../utils/renderer/no-scripts.mjs";
11
12
  import { getQuery, joinURL } from "ufo";
12
13
  import { appendResponseHeader, createError, getQuery as getQuery$1, getRequestHeader, getResponseStatus, getResponseStatusText, removeResponseHeader, setResponseHeader, writeEarlyHints } from "h3";
@@ -15,7 +16,7 @@ import destr from "destr";
15
16
  import { getPrefetchLinks, getPreloadLinks, getRequestDependencies, renderResourceHeaders } from "vue-bundle-renderer/runtime";
16
17
  import { appHead, appTeleportAttrs, appTeleportTag, componentIslands, componentIslandsActive, tracingChannelNuxt } from "#internal/nuxt.config.mjs";
17
18
  import { AsyncLocalStorage } from "node:async_hooks";
18
- import { NUXT_ASYNC_CONTEXT, NUXT_EARLY_HINTS, NUXT_INLINE_STYLES, NUXT_JSON_PAYLOADS, NUXT_NO_SCRIPTS, NUXT_NO_SCRIPTS_PATTERNS, NUXT_NO_SCRIPTS_PROD, NUXT_PAGE_PATTERNS, NUXT_PAYLOAD_EXTRACTION, NUXT_PAYLOAD_INLINE, NUXT_RUNTIME_PAYLOAD_EXTRACTION, NUXT_SSR_STREAMING, NUXT_SSR_STREAMING_BOT_RE, NUXT_VIEW_TRANSITIONS, PARSE_ERROR_DATA } from "#internal/nuxt/nitro-config.mjs";
19
+ import { NUXT_ASYNC_CONTEXT, NUXT_EARLY_HINTS, NUXT_INLINE_STYLES, NUXT_JSON_PAYLOADS, NUXT_NO_SCRIPTS, NUXT_NO_SCRIPTS_PATTERNS, NUXT_NO_SCRIPTS_PROD, NUXT_PAGE_PATTERNS, NUXT_PAYLOAD_EXTRACTION, NUXT_PAYLOAD_INLINE, NUXT_PRERENDER_ERROR_PAGES, NUXT_RUNTIME_PAYLOAD_EXTRACTION, NUXT_SSR_STREAMING, NUXT_SSR_STREAMING_BOT_RE, NUXT_VIEW_TRANSITIONS, PARSE_ERROR_DATA } from "#internal/nuxt/nitro-config.mjs";
19
20
  import { propsToString, renderSSRHead } from "@unhead/vue/server";
20
21
  import { renderToWebStream } from "vue/server-renderer";
21
22
  import { createBootstrapScript, renderSSRHeadSuspenseChunk, renderShell } from "@unhead/vue/stream/server";
@@ -38,7 +39,7 @@ const PAYLOAD_BUILD_ID_PARAM = "_b";
38
39
  let entryPath;
39
40
  const SSR_BOT_RE = NUXT_SSR_STREAMING_BOT_RE;
40
41
  const handler = defineRenderHandler((event) => {
41
- const ssrError = event.path.startsWith("/__nuxt_error") ? getQuery$1(event) : null;
42
+ const ssrError = event.path.startsWith("/__nuxt_error") ? getQuery$1(event) : import.meta.prerender ? getPrerenderedErrorPage(event) : null;
42
43
  if (ssrError && !("__unenv__" in event.node.req)) throw createError({
43
44
  status: 404,
44
45
  statusText: "Page Not Found: /__nuxt_error",
@@ -58,6 +59,38 @@ const handler = defineRenderHandler((event) => {
58
59
  }
59
60
  return renderRoute(event, ssrError);
60
61
  });
62
+ const ERROR_PAGE_RE = /^\/(\d{3})\.html$/;
63
+ const STATUS_TEXT = {
64
+ 400: "Bad Request",
65
+ 401: "Unauthorized",
66
+ 403: "Forbidden",
67
+ 404: "Page Not Found",
68
+ 410: "Gone",
69
+ 500: "Internal Server Error",
70
+ 503: "Service Unavailable"
71
+ };
72
+ function isPrerenderedErrorPage(pathname) {
73
+ const status = Number(ERROR_PAGE_RE.exec(pathname)?.[1]);
74
+ return status && NUXT_PRERENDER_ERROR_PAGES.includes(status) ? status : void 0;
75
+ }
76
+ /**
77
+ * Synthesise the error a static error page (`404.html` and friends) renders
78
+ * with, so the page is server-rendered at build time rather than written out as
79
+ * an empty SPA shell.
80
+ */
81
+ function getPrerenderedErrorPage(event) {
82
+ const pathname = event.path.replace(/[?#].*$/, "");
83
+ const status = isPrerenderedErrorPage(pathname);
84
+ if (!status) return null;
85
+ const statusText = STATUS_TEXT[status] || "Error";
86
+ return {
87
+ status,
88
+ statusText,
89
+ message: statusText,
90
+ fatal: false,
91
+ url: pathname
92
+ };
93
+ }
61
94
  async function renderRoute(event, ssrError) {
62
95
  const nitroApp = useNitroApp();
63
96
  const ssrContext = createSSRContext(event);
@@ -73,7 +106,7 @@ async function renderRoute(event, ssrError) {
73
106
  }
74
107
  const routeOptions = getRouteRules(event);
75
108
  if (routeOptions.ssr === false) ssrContext.noSSR = true;
76
- const _PAYLOAD_EXTRACTION = !ssrContext.noSSR && (import.meta.prerender && NUXT_PAYLOAD_EXTRACTION || NUXT_RUNTIME_PAYLOAD_EXTRACTION && (routeOptions.isr || routeOptions.cache));
109
+ const _PAYLOAD_EXTRACTION = !ssrContext.noSSR && !ssrError && (import.meta.prerender && NUXT_PAYLOAD_EXTRACTION || NUXT_RUNTIME_PAYLOAD_EXTRACTION && (routeOptions.isr || routeOptions.cache));
77
110
  const _PAYLOAD_INLINE = !_PAYLOAD_EXTRACTION || NUXT_PAYLOAD_INLINE;
78
111
  const isRenderingPayload = (_PAYLOAD_EXTRACTION || import.meta.dev && routeOptions.prerender) && PAYLOAD_URL_RE.test(ssrContext.url);
79
112
  if (isRenderingPayload) {
@@ -126,6 +159,10 @@ async function renderRoute(event, ssrError) {
126
159
  throw _err;
127
160
  });
128
161
  const inlinedStyles = NUXT_INLINE_STYLES && !ssrContext["~renderResponse"] && !ssrContext._renderResponse && !isRenderingPayload ? await renderInlineStyles(ssrContext.modules ?? []) : [];
162
+ if (import.meta.prerender && ssrError && isPrerenderedErrorPage(event.path.replace(/[?#].*$/, ""))) {
163
+ delete ssrContext.payload.path;
164
+ if (ssrContext.payload.error) ssrContext.payload.error.url = void 0;
165
+ }
129
166
  await ssrContext.nuxt?.hooks.callHook("app:rendered", {
130
167
  ssrContext,
131
168
  renderResult: _rendered
@@ -172,8 +209,14 @@ async function renderRoute(event, ssrError) {
172
209
  }] });
173
210
  if (inlinedStyles.length) ssrContext.head.push({ style: inlinedStyles });
174
211
  const link = [];
212
+ const inlinedHrefs = [];
213
+ const isCSSInlined = NUXT_INLINE_STYLES ? await createInlinedCSSFilter(ssrContext.modules) : void 0;
175
214
  for (const resource of Object.values(styles)) {
176
215
  if (import.meta.dev && "inline" in getQuery(resource.file)) continue;
216
+ if (isCSSInlined?.(resource.file)) {
217
+ inlinedHrefs.push(renderer.rendererContext.buildAssetsURL(resource.file));
218
+ continue;
219
+ }
177
220
  link.push({
178
221
  rel: "stylesheet",
179
222
  href: renderer.rendererContext.buildAssetsURL(resource.file),
@@ -184,6 +227,7 @@ async function renderRoute(event, ssrError) {
184
227
  if (!NO_SCRIPTS) {
185
228
  const dependencyOptions = ssrContext["~lazyHydratedModules"]?.size ? { exclude: ssrContext["~lazyHydratedModules"] } : void 0;
186
229
  const excludeHrefs = new Set(link.map((l) => l.href));
230
+ for (const href of inlinedHrefs) excludeHrefs.add(href);
187
231
  for (const id of ssrContext["~neverHydratedModules"] ?? []) {
188
232
  const file = renderer.rendererContext.manifest?.[id]?.file;
189
233
  if (file) excludeHrefs.add(renderer.rendererContext.buildAssetsURL(file));
@@ -1,19 +1,23 @@
1
1
  import { sharedPrerenderCache } from "../cache.mjs";
2
- import { encodePath } from "ufo";
3
2
  import { useRuntimeConfig } from "nitropack/runtime";
4
- import { NUXT_NO_SSR, NUXT_SHARED_DATA } from "#internal/nuxt/nitro-config.mjs";
3
+ import { NUXT_NO_SSR, NUXT_PRERENDER_NO_SSR_ROUTES, NUXT_SHARED_DATA } from "#internal/nuxt/nitro-config.mjs";
5
4
  import { createHead } from "@unhead/vue/server";
6
5
  import unheadOptions from "#internal/unhead-options.mjs";
7
6
  //#region src/runtime/utils/renderer/app.ts
8
- const PRERENDER_NO_SSR_ROUTES = /* @__PURE__ */ new Set([
9
- "/index.html",
10
- "/200.html",
11
- "/404.html"
12
- ]);
7
+ const PRERENDER_NO_SSR_ROUTES = new Set(NUXT_PRERENDER_NO_SSR_ROUTES);
8
+ const ENC_PIPE_RE = /%7C/g;
9
+ const ENC_BRACKET_OPEN_RE = /%5B/g;
10
+ const ENC_BRACKET_CLOSE_RE = /%5D/g;
11
+ const ENC_ENC_SLASH_RE = /%252F/gi;
12
+ const HASH_RE = /#/g;
13
+ const QUESTION_MARK_RE = /\?/g;
13
14
  function encodeEventPath(path) {
14
15
  const queryIndex = path.indexOf("?");
15
- if (queryIndex === -1) return encodePath(path);
16
- return encodePath(path.slice(0, queryIndex)) + path.slice(queryIndex);
16
+ if (queryIndex === -1) return encodeVueRouterPath(path);
17
+ return encodeVueRouterPath(path.slice(0, queryIndex)) + path.slice(queryIndex);
18
+ }
19
+ function encodeVueRouterPath(path) {
20
+ return encodeURI(path).replace(ENC_PIPE_RE, "|").replace(ENC_BRACKET_OPEN_RE, "[").replace(ENC_BRACKET_CLOSE_RE, "]").replace(HASH_RE, "%23").replace(QUESTION_MARK_RE, "%3F").replace(ENC_ENC_SLASH_RE, "%2F");
17
21
  }
18
22
  function createSSRContext(event) {
19
23
  const url = encodeEventPath(event.path);
@@ -68,5 +68,6 @@ function getRenderer(ssrContext) {
68
68
  }
69
69
  const getServerApp = lazyCachedFunction(getServerEntry);
70
70
  const getSSRStyles = lazyCachedFunction(() => import("nuxt/styles").then((r) => r.default || r));
71
+ const getInlinedCSS = lazyCachedFunction(() => import("nuxt/styles").then((r) => r.inlinedCSS || {}));
71
72
  //#endregion
72
- export { APP_ROOT_CLOSE_TAG, APP_ROOT_OPEN_TAG, getRenderer, getSSRRenderer, getSSRStyles, getServerApp };
73
+ export { APP_ROOT_CLOSE_TAG, APP_ROOT_OPEN_TAG, getInlinedCSS, getRenderer, getSSRRenderer, getSSRStyles, getServerApp };
@@ -0,0 +1,20 @@
1
+ //#region src/runtime/utils/renderer/dev-css.ts
2
+ const QUERY_RE = /\?.*$/;
3
+ const LEADING_RELATIVE_RE = /^(?:\.\.?\/)+/;
4
+ /**
5
+ * Whether a dev stylesheet belongs to one of the modules a render actually used.
6
+ *
7
+ * The dev CSS set is the builder's whole module graph, not a per-request subset, so
8
+ * consumers that must not leak unrelated styles (islands) narrow it with the modules
9
+ * Vue registered during their own render.
10
+ */
11
+ function isStyleOfModule(file, modules) {
12
+ const path = file.replace(QUERY_RE, "");
13
+ for (const mod of modules) {
14
+ const normalized = mod.replace(LEADING_RELATIVE_RE, "");
15
+ if (normalized && (path === normalized || path.endsWith("/" + normalized))) return true;
16
+ }
17
+ return false;
18
+ }
19
+ //#endregion
20
+ export { isStyleOfModule };
@@ -0,0 +1,33 @@
1
+ import { getInlinedCSS } from "./build-files.mjs";
2
+ //#region src/runtime/utils/renderer/inlined-css.ts
3
+ /**
4
+ * Build a predicate telling whether the contents of an emitted CSS file were
5
+ * inlined as `<style>` tags for this request, meaning its `<link>` can be
6
+ * dropped.
7
+ *
8
+ * The builder can only remove a link at build time when every CSS source in
9
+ * the file is inlined for a module that is always rendered. For the rest it
10
+ * records the modules that inline each source, and the answer depends on what
11
+ * the request actually rendered: a component inside `<ClientOnly>` never
12
+ * reaches `ssrContext.modules`, so its styles are only ever delivered by the
13
+ * link. (#36058)
14
+ */
15
+ async function createInlinedCSSFilter(modules) {
16
+ const inlinedCSS = await getInlinedCSS();
17
+ return (file) => {
18
+ const conditions = inlinedCSS[file.slice(file.lastIndexOf("/") + 1)];
19
+ if (!conditions) return false;
20
+ if (!modules?.size) return false;
21
+ for (const inliners of conditions) {
22
+ let inlined = false;
23
+ for (const id of inliners) if (modules.has(id)) {
24
+ inlined = true;
25
+ break;
26
+ }
27
+ if (!inlined) return false;
28
+ }
29
+ return true;
30
+ };
31
+ }
32
+ //#endregion
33
+ export { createInlinedCSSFilter };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuxt/nitro-server-nightly",
3
- "version": "4.6.0-29776167.796cdae2",
3
+ "version": "4.6.0-29778602.bfddf2f0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/nuxt/nuxt.git",
@@ -32,7 +32,7 @@
32
32
  ],
33
33
  "dependencies": {
34
34
  "@nuxt/devalue": "^2.0.2",
35
- "@nuxt/kit": "npm:@nuxt/kit-nightly@4.6.0-29776167.796cdae2",
35
+ "@nuxt/kit": "npm:@nuxt/kit-nightly@4.6.0-29778602.bfddf2f0",
36
36
  "@unhead/vue": "^3.3.1",
37
37
  "@vue/shared": "^3.5.40",
38
38
  "consola": "^3.4.2",
@@ -54,7 +54,7 @@
54
54
  "std-env": "^4.2.0",
55
55
  "ufo": "^1.6.4",
56
56
  "unctx": "^3.0.0",
57
- "unrouting": "^0.2.2",
57
+ "unrouting": "^0.2.3",
58
58
  "unstorage": "^1.17.5",
59
59
  "vue": "^3.5.40",
60
60
  "vue-bundle-renderer": "^2.3.1",
@@ -64,7 +64,7 @@
64
64
  "@babel/plugin-proposal-decorators": "^7.25.0 || ^8.0.0",
65
65
  "@babel/plugin-syntax-typescript": "^7.25.0 || ^8.0.0",
66
66
  "@rollup/plugin-babel": "^6.0.0 || ^7.0.0",
67
- "nuxt": "npm:nuxt-nightly@4.6.0-29776167.796cdae2"
67
+ "nuxt": "npm:nuxt-nightly@4.6.0-29778602.bfddf2f0"
68
68
  },
69
69
  "peerDependenciesMeta": {
70
70
  "@babel/plugin-proposal-decorators": {
@@ -80,9 +80,9 @@
80
80
  "devDependencies": {
81
81
  "@babel/plugin-proposal-decorators": "8.0.2",
82
82
  "@babel/plugin-syntax-typescript": "8.0.3",
83
- "@nuxt/schema": "npm:@nuxt/schema-nightly@4.6.0-29776167.796cdae2",
83
+ "@nuxt/schema": "npm:@nuxt/schema-nightly@4.6.0-29778602.bfddf2f0",
84
84
  "@rollup/plugin-babel": "7.1.0",
85
- "nuxt": "npm:nuxt-nightly@4.6.0-29776167.796cdae2",
85
+ "nuxt": "npm:nuxt-nightly@4.6.0-29778602.bfddf2f0",
86
86
  "tsdown": "0.22.14",
87
87
  "vitest": "4.1.10"
88
88
  },