@nuxt/nitro-server-nightly 5.0.0-29776938.e673c552 → 5.0.0-29778218.1397500a

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
@@ -22,7 +22,7 @@ import { nitro } from "nitro/vite";
22
22
  import MagicString from "magic-string";
23
23
  import remapping from "@ampproject/remapping";
24
24
  //#region package.json
25
- var version = "5.0.0-29776938.e673c552";
25
+ var version = "5.0.0-29778218.1397500a";
26
26
  //#endregion
27
27
  //#region src/utils.ts
28
28
  function toArray(value) {
@@ -221,8 +221,11 @@ const NITRO_VIRTUAL_PREFIX = "\0nuxt-nitro-virtual:";
221
221
  * minifier nor Nitro's subsequent inline-and-minify pass can rename or
222
222
  * tree-shake it before the substitution runs. Because the sentinel sits in
223
223
  * expression position, deferred providers must produce a module body of
224
- * exactly the form `export default <expression>` (no other statements); the
225
- * substitution inlines the expression, parenthesised, in its place.
224
+ * exactly the form `export default <expression>`; the
225
+ * substitution inlines the expression, parenthesised, in its place. A provider
226
+ * may append `export const <name> = <expression>` statements for the named
227
+ * exports declared in `DEFERRED_NAMED_EXPORTS`; each gets its own sentinel and
228
+ * resolves to `undefined` when the provider omits it.
226
229
  *
227
230
  * `entryChunkName` is excluded: `StableEntryPlugin` finalises it in the client
228
231
  * env's `writeBundle`, which completes before the ssr env loads it.
@@ -238,13 +241,34 @@ const DEFERRED_KEYS = /* @__PURE__ */ new Set([
238
241
  "entryIds",
239
242
  "ssrStyles"
240
243
  ]);
241
- function sentinel(specifier) {
242
- return `__NUXT_BUILD_OUTPUT__${specifier.replace(/\W/g, "_")}__`;
244
+ /**
245
+ * Named exports a deferred build output provides in addition to its default
246
+ * export. Each one gets its own sentinel, and the provider must append an
247
+ * `export const <name> = <expression>` statement for it.
248
+ */
249
+ const DEFERRED_NAMED_EXPORTS = { ssrStyles: ["inlinedCSS"] };
250
+ function sentinel(specifier, name) {
251
+ return `__NUXT_BUILD_OUTPUT__${specifier.replace(/\W/g, "_")}${name ? `__${name}` : ""}__`;
243
252
  }
244
- async function getDeferredExpression(nuxt, key) {
253
+ const NAMED_EXPORT_RE = /\nexport const (\w+) = /;
254
+ /**
255
+ * Split a deferred provider's module body into the expression for its default
256
+ * export and one for each of its named exports.
257
+ */
258
+ async function getDeferredExpressions(nuxt, key) {
245
259
  const body = String(await nuxt.buildOutputs[key]() ?? "export default {}").trim().replace(/;$/, "");
246
260
  if (!body.startsWith("export default ")) throw new Error(`[nuxt] Deferred build output \`${key}\` must be a module body of the form \`export default <expression>\`.`);
247
- return body.slice(15);
261
+ const expressions = /* @__PURE__ */ new Map();
262
+ let name;
263
+ let rest = body.slice(15);
264
+ let match;
265
+ while (match = rest.match(NAMED_EXPORT_RE)) {
266
+ expressions.set(name, rest.slice(0, match.index).trim().replace(/;$/, ""));
267
+ name = match[1];
268
+ rest = rest.slice(match.index + match[0].length);
269
+ }
270
+ expressions.set(name, rest.trim().replace(/;$/, ""));
271
+ return expressions;
248
272
  }
249
273
  /**
250
274
  * Resolves the `nuxt/*` build-output specifiers for the ssr environment.
@@ -270,10 +294,14 @@ function NuxtBuildOutputsPlugin(nuxt) {
270
294
  const specifier = id.slice(19);
271
295
  const key = NUXT_BUILD_OUTPUT_MAP[specifier];
272
296
  if (!key) return;
273
- if (!nuxt.options.dev && DEFERRED_KEYS.has(key)) return {
274
- code: `export default ${JSON.stringify(sentinel(specifier))}`,
275
- map: null
276
- };
297
+ if (!nuxt.options.dev && DEFERRED_KEYS.has(key)) {
298
+ const statements = [`export default ${JSON.stringify(sentinel(specifier))}`];
299
+ for (const name of DEFERRED_NAMED_EXPORTS[key] ?? []) statements.push(`export const ${name} = ${JSON.stringify(sentinel(specifier, name))}`);
300
+ return {
301
+ code: statements.join("\n"),
302
+ map: null
303
+ };
304
+ }
277
305
  return {
278
306
  code: await nuxt.buildOutputs[key]() ?? "",
279
307
  map: null
@@ -287,7 +315,9 @@ function NuxtBuildOutputsPlugin(nuxt) {
287
315
  const replacements = /* @__PURE__ */ new Map();
288
316
  for (const [specifier, key] of Object.entries(NUXT_BUILD_OUTPUT_MAP)) {
289
317
  if (!DEFERRED_KEYS.has(key)) continue;
290
- replacements.set(sentinel(specifier), `(${await getDeferredExpression(nuxt, key)})`);
318
+ const expressions = await getDeferredExpressions(nuxt, key);
319
+ replacements.set(sentinel(specifier), `(${expressions.get(void 0)})`);
320
+ for (const name of DEFERRED_NAMED_EXPORTS[key] ?? []) replacements.set(sentinel(specifier, name), `(${expressions.get(name) ?? "undefined"})`);
291
321
  }
292
322
  const sourcemap = !!this.environment.config.build.sourcemap;
293
323
  for (const file of Object.values(bundle)) {
@@ -10,6 +10,7 @@ import { renderInlineStyles } from "../utils/renderer/inline-styles.mjs";
10
10
  import { renderStreamedIslandTeleports, replaceIslandTeleports } from "../utils/renderer/islands.mjs";
11
11
  import { patchDevClientCss } from "../utils/renderer/dev-css.mjs";
12
12
  import { renderPayloadJsonScript, renderPayloadResponse, splitPayload } from "../utils/renderer/payload.mjs";
13
+ import { createInlinedCSSFilter } from "../utils/renderer/inlined-css.mjs";
13
14
  import { warnNoScriptsClientReliance } from "../utils/renderer/no-scripts.mjs";
14
15
  import { getQuery, joinURL } from "ufo";
15
16
  import { FastResponse } from "srvx";
@@ -213,8 +214,14 @@ async function renderRoute(event, ssrError) {
213
214
  }] });
214
215
  if (inlinedStyles.length) ssrContext.head.push({ style: inlinedStyles });
215
216
  const link = [];
217
+ const inlinedHrefs = [];
218
+ const isCSSInlined = NUXT_INLINE_STYLES ? await createInlinedCSSFilter(ssrContext.modules) : void 0;
216
219
  for (const resource of Object.values(styles)) {
217
220
  if (import.meta.dev && "inline" in getQuery(resource.file)) continue;
221
+ if (isCSSInlined?.(resource.file)) {
222
+ inlinedHrefs.push(renderer.rendererContext.buildAssetsURL(resource.file));
223
+ continue;
224
+ }
218
225
  link.push({
219
226
  rel: "stylesheet",
220
227
  href: renderer.rendererContext.buildAssetsURL(resource.file),
@@ -225,6 +232,7 @@ async function renderRoute(event, ssrError) {
225
232
  if (!NO_SCRIPTS) {
226
233
  const dependencyOptions = ssrContext["~lazyHydratedModules"]?.size ? { exclude: ssrContext["~lazyHydratedModules"] } : void 0;
227
234
  const excludeHrefs = new Set(link.map((l) => l.href));
235
+ for (const href of inlinedHrefs) excludeHrefs.add(href);
228
236
  for (const id of ssrContext["~neverHydratedModules"] ?? []) {
229
237
  const file = renderer.rendererContext.manifest?.[id]?.file;
230
238
  if (file) excludeHrefs.add(renderer.rendererContext.buildAssetsURL(file));
@@ -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,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": "5.0.0-29776938.e673c552",
3
+ "version": "5.0.0-29778218.1397500a",
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
  "@ampproject/remapping": "^2.3.0",
35
- "@nuxt/kit": "npm:@nuxt/kit-nightly@5.0.0-29776938.e673c552",
35
+ "@nuxt/kit": "npm:@nuxt/kit-nightly@5.0.0-29778218.1397500a",
36
36
  "@unhead/vue": "^3.3.1",
37
37
  "@vue/shared": "^3.5.40",
38
38
  "consola": "^3.4.2",
@@ -65,7 +65,7 @@
65
65
  "@babel/plugin-proposal-decorators": "^7.25.0 || ^8.0.0",
66
66
  "@babel/plugin-syntax-typescript": "^7.25.0 || ^8.0.0",
67
67
  "@rollup/plugin-babel": "^6.0.0 || ^7.0.0",
68
- "nuxt": "npm:nuxt-nightly@5.0.0-29776938.e673c552"
68
+ "nuxt": "npm:nuxt-nightly@5.0.0-29778218.1397500a"
69
69
  },
70
70
  "peerDependenciesMeta": {
71
71
  "@babel/plugin-proposal-decorators": {
@@ -81,10 +81,10 @@
81
81
  "devDependencies": {
82
82
  "@babel/plugin-proposal-decorators": "8.0.2",
83
83
  "@babel/plugin-syntax-typescript": "8.0.3",
84
- "@nuxt/schema": "npm:@nuxt/schema-nightly@5.0.0-29776938.e673c552",
84
+ "@nuxt/schema": "npm:@nuxt/schema-nightly@5.0.0-29778218.1397500a",
85
85
  "@rollup/plugin-babel": "7.1.0",
86
86
  "hookable": "^6.1.1",
87
- "nuxt": "npm:nuxt-nightly@5.0.0-29776938.e673c552",
87
+ "nuxt": "npm:nuxt-nightly@5.0.0-29778218.1397500a",
88
88
  "tsdown": "0.22.14",
89
89
  "vitest": "4.1.10"
90
90
  },