astro 6.0.0-alpha.4 → 6.0.0-beta.0

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 (122) hide show
  1. package/dist/assets/build/generate.js +1 -1
  2. package/dist/assets/build/remote.js +1 -1
  3. package/dist/assets/endpoint/dev.js +44 -16
  4. package/dist/assets/fonts/config.d.ts +13 -0
  5. package/dist/assets/fonts/config.js +4 -2
  6. package/dist/assets/fonts/constants.js +2 -1
  7. package/dist/assets/fonts/core/resolve-families.js +1 -0
  8. package/dist/assets/fonts/definitions.d.ts +10 -2
  9. package/dist/assets/fonts/infra/remote-font-provider-resolver.d.ts +2 -2
  10. package/dist/assets/fonts/infra/unifont-font-resolver.d.ts +24 -0
  11. package/dist/assets/fonts/infra/unifont-font-resolver.js +59 -0
  12. package/dist/assets/fonts/orchestrate.d.ts +6 -4
  13. package/dist/assets/fonts/orchestrate.js +16 -32
  14. package/dist/assets/fonts/providers/entrypoints/bunny.d.ts +1 -1
  15. package/dist/assets/fonts/providers/entrypoints/fontshare.d.ts +1 -1
  16. package/dist/assets/fonts/providers/entrypoints/fontsource.d.ts +1 -1
  17. package/dist/assets/fonts/providers/index.d.ts +6 -8
  18. package/dist/assets/fonts/providers/index.js +10 -14
  19. package/dist/assets/fonts/types.d.ts +17 -4
  20. package/dist/assets/fonts/vite-plugin-fonts.js +6 -1
  21. package/dist/assets/utils/vendor/image-size/detector.d.ts +1 -1
  22. package/dist/assets/utils/vendor/image-size/detector.js +2 -1
  23. package/dist/assets/utils/vendor/image-size/types/bmp.js +1 -1
  24. package/dist/assets/utils/vendor/image-size/types/gif.js +1 -1
  25. package/dist/assets/utils/vendor/image-size/types/heif.js +51 -29
  26. package/dist/assets/utils/vendor/image-size/types/icns.js +13 -14
  27. package/dist/assets/utils/vendor/image-size/types/ico.js +5 -5
  28. package/dist/assets/utils/vendor/image-size/types/index.d.ts +3 -3
  29. package/dist/assets/utils/vendor/image-size/types/index.js +4 -0
  30. package/dist/assets/utils/vendor/image-size/types/interface.d.ts +6 -6
  31. package/dist/assets/utils/vendor/image-size/types/j2c.js +2 -2
  32. package/dist/assets/utils/vendor/image-size/types/jp2.js +5 -3
  33. package/dist/assets/utils/vendor/image-size/types/jpg.js +4 -4
  34. package/dist/assets/utils/vendor/image-size/types/jxl-stream.d.ts +2 -0
  35. package/dist/assets/utils/vendor/image-size/types/jxl-stream.js +36 -0
  36. package/dist/assets/utils/vendor/image-size/types/jxl.d.ts +2 -0
  37. package/dist/assets/utils/vendor/image-size/types/jxl.js +57 -0
  38. package/dist/assets/utils/vendor/image-size/types/ktx.js +1 -1
  39. package/dist/assets/utils/vendor/image-size/types/png.js +1 -1
  40. package/dist/assets/utils/vendor/image-size/types/pnm.js +5 -7
  41. package/dist/assets/utils/vendor/image-size/types/psd.js +1 -1
  42. package/dist/assets/utils/vendor/image-size/types/tiff.js +93 -40
  43. package/dist/assets/utils/vendor/image-size/types/utils.d.ts +3 -2
  44. package/dist/assets/utils/vendor/image-size/types/utils.js +24 -22
  45. package/dist/assets/utils/vendor/image-size/types/webp.js +5 -6
  46. package/dist/assets/utils/vendor/image-size/utils/bit-reader.d.ts +10 -0
  47. package/dist/assets/utils/vendor/image-size/utils/bit-reader.js +41 -0
  48. package/dist/assets/vite-plugin-assets.js +7 -0
  49. package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
  50. package/dist/config/entrypoint.d.ts +1 -2
  51. package/dist/config/entrypoint.js +1 -2
  52. package/dist/config/index.js +1 -1
  53. package/dist/content/config.d.ts +25 -9
  54. package/dist/content/config.js +13 -17
  55. package/dist/content/content-layer.js +38 -21
  56. package/dist/content/loaders/glob.d.ts +4 -1
  57. package/dist/content/loaders/glob.js +36 -8
  58. package/dist/content/types-generator.js +10 -6
  59. package/dist/content/utils.d.ts +17 -1
  60. package/dist/content/utils.js +129 -8
  61. package/dist/content/vite-plugin-content-assets.d.ts +4 -5
  62. package/dist/content/vite-plugin-content-assets.js +3 -10
  63. package/dist/content/vite-plugin-content-imports.js +5 -1
  64. package/dist/content/vite-plugin-content-virtual-mod.js +10 -2
  65. package/dist/core/app/app.d.ts +1 -0
  66. package/dist/core/app/app.js +3 -0
  67. package/dist/core/app/base.d.ts +12 -0
  68. package/dist/core/app/base.js +18 -1
  69. package/dist/core/app/dev/app.d.ts +4 -1
  70. package/dist/core/app/dev/app.js +24 -3
  71. package/dist/core/build/app.d.ts +1 -0
  72. package/dist/core/build/app.js +3 -0
  73. package/dist/core/build/index.js +1 -1
  74. package/dist/core/build/plugins/plugin-manifest.d.ts +4 -6
  75. package/dist/core/build/plugins/plugin-manifest.js +14 -45
  76. package/dist/core/build/static-build.d.ts +10 -0
  77. package/dist/core/build/static-build.js +42 -34
  78. package/dist/core/config/schemas/base.d.ts +19 -2
  79. package/dist/core/config/schemas/base.js +6 -2
  80. package/dist/core/config/schemas/relative.d.ts +24 -3
  81. package/dist/core/config/settings.js +5 -1
  82. package/dist/core/constants.js +1 -1
  83. package/dist/core/dev/container.js +1 -1
  84. package/dist/core/dev/dev.js +1 -1
  85. package/dist/core/messages.js +2 -2
  86. package/dist/core/preview/index.js +1 -1
  87. package/dist/core/routing/dev.d.ts +14 -0
  88. package/dist/core/routing/dev.js +67 -0
  89. package/dist/core/routing/index.d.ts +0 -1
  90. package/dist/core/routing/index.js +0 -2
  91. package/dist/core/routing/manifest/create.js +9 -6
  92. package/dist/core/sync/index.js +11 -3
  93. package/dist/prerender/routing.d.ts +1 -1
  94. package/dist/prerender/routing.js +4 -4
  95. package/dist/runtime/client/dev-toolbar/apps/audit/rules/perf.js +1 -0
  96. package/dist/runtime/server/jsx.js +18 -4
  97. package/dist/runtime/server/render/astro/render.js +26 -3
  98. package/dist/runtime/server/render/common.d.ts +1 -0
  99. package/dist/runtime/server/render/common.js +16 -0
  100. package/dist/runtime/server/render/component.js +28 -4
  101. package/dist/runtime/server/render/instruction.d.ts +6 -1
  102. package/dist/runtime/server/render/script.d.ts +5 -1
  103. package/dist/runtime/server/render/script.js +7 -10
  104. package/dist/runtime/server/render/slot.d.ts +5 -0
  105. package/dist/runtime/server/render/slot.js +9 -4
  106. package/dist/transitions/router.js +2 -0
  107. package/dist/types/public/config.d.ts +21 -3
  108. package/dist/types/public/context.d.ts +307 -291
  109. package/dist/vite-plugin-app/app.d.ts +3 -0
  110. package/dist/vite-plugin-app/app.js +30 -80
  111. package/dist/vite-plugin-app/pipeline.d.ts +0 -1
  112. package/dist/vite-plugin-app/pipeline.js +3 -12
  113. package/dist/vite-plugin-astro-server/base.js +3 -2
  114. package/dist/vite-plugin-astro-server/response.js +4 -6
  115. package/dist/vite-plugin-config-alias/index.js +3 -2
  116. package/dist/vite-plugin-pages/pages.js +17 -1
  117. package/dist/vite-plugin-routes/index.js +1 -1
  118. package/package.json +13 -13
  119. package/dist/assets/fonts/core/dedupe-font-faces.d.ts +0 -2
  120. package/dist/assets/fonts/core/dedupe-font-faces.js +0 -30
  121. package/dist/assets/fonts/core/extract-unifont-providers.d.ts +0 -10
  122. package/dist/assets/fonts/core/extract-unifont-providers.js +0 -28
@@ -8,6 +8,7 @@ import xxhash from "xxhash-wasm";
8
8
  import * as z from "zod/v4";
9
9
  import { AstroError, AstroErrorData, errorMap, MarkdownError } from "../core/errors/index.js";
10
10
  import { isYAMLException } from "../core/errors/utils.js";
11
+ import { appendForwardSlash } from "../core/path.js";
11
12
  import { normalizePath } from "../core/viteUtils.js";
12
13
  import {
13
14
  CONTENT_LAYER_TYPE,
@@ -17,6 +18,7 @@ import {
17
18
  LIVE_CONTENT_TYPE,
18
19
  PROPAGATED_ASSET_FLAG
19
20
  } from "./consts.js";
21
+ import { glob, secretLegacyFlag } from "./loaders/glob.js";
20
22
  import { createImage } from "./runtime-assets.js";
21
23
  const entryTypeSchema = z.object({
22
24
  id: z.string({
@@ -36,6 +38,16 @@ const loaderReturnSchema = z.union([
36
38
  )
37
39
  ]);
38
40
  const collectionConfigParser = z.union([
41
+ z.object({
42
+ type: z.literal("content").optional(),
43
+ schema: z.any().optional(),
44
+ loader: z.never().optional()
45
+ }),
46
+ z.object({
47
+ type: z.literal("data").optional(),
48
+ schema: z.any().optional(),
49
+ loader: z.never().optional()
50
+ }),
39
51
  z.object({
40
52
  type: z.literal(CONTENT_LAYER_TYPE),
41
53
  schema: z.any().optional(),
@@ -349,7 +361,11 @@ async function loadContentConfig({
349
361
  settings,
350
362
  environment
351
363
  }) {
352
- const contentPaths = getContentPaths(settings.config, fs);
364
+ const contentPaths = getContentPaths(
365
+ settings.config,
366
+ fs,
367
+ settings.config.legacy?.collectionsBackwardsCompat
368
+ );
353
369
  if (!contentPaths.config.exists) {
354
370
  return void 0;
355
371
  }
@@ -383,6 +399,74 @@ ${message}
383
399
  return void 0;
384
400
  }
385
401
  }
402
+ async function autogenerateCollections({
403
+ config,
404
+ settings,
405
+ fs
406
+ }) {
407
+ if (!config) {
408
+ return config;
409
+ }
410
+ if (!settings.config.legacy?.collectionsBackwardsCompat) {
411
+ return config;
412
+ }
413
+ const contentDir = new URL("./content/", settings.config.srcDir);
414
+ const collections = config.collections ?? {};
415
+ const contentExts = getContentEntryExts(settings);
416
+ const dataExts = getDataEntryExts(settings);
417
+ const contentPattern = globWithUnderscoresIgnored("", contentExts);
418
+ const dataPattern = globWithUnderscoresIgnored("", dataExts);
419
+ let usesContentLayer = false;
420
+ for (const collectionName of Object.keys(collections)) {
421
+ const collection = collections[collectionName];
422
+ if (collection?.type === CONTENT_LAYER_TYPE || collection?.type === LIVE_CONTENT_TYPE) {
423
+ usesContentLayer = true;
424
+ continue;
425
+ }
426
+ const isDataCollection = collection?.type === "data";
427
+ const base = new URL(`${collectionName}/`, contentDir);
428
+ collections[collectionName] = {
429
+ ...collection,
430
+ type: CONTENT_LAYER_TYPE,
431
+ loader: glob({
432
+ base,
433
+ pattern: isDataCollection ? dataPattern : contentPattern,
434
+ [secretLegacyFlag]: true
435
+ })
436
+ };
437
+ }
438
+ if (!usesContentLayer && fs.existsSync(contentDir)) {
439
+ const orphanedCollections = [];
440
+ for (const entry of await fs.promises.readdir(contentDir, { withFileTypes: true })) {
441
+ const collectionName = entry.name;
442
+ if (["_", "."].includes(collectionName.at(0) ?? "")) {
443
+ continue;
444
+ }
445
+ if (entry.isDirectory() && !(collectionName in collections)) {
446
+ orphanedCollections.push(collectionName);
447
+ const base = new URL(`${collectionName}/`, contentDir);
448
+ collections[collectionName] = {
449
+ type: CONTENT_LAYER_TYPE,
450
+ loader: glob({
451
+ base,
452
+ pattern: contentPattern,
453
+ [secretLegacyFlag]: true
454
+ })
455
+ };
456
+ }
457
+ }
458
+ if (orphanedCollections.length > 0) {
459
+ console.warn(
460
+ `
461
+ Auto-generating collections for folders in "src/content/" that are not defined as collections.
462
+ This is deprecated, so you should define these collections yourself in "src/content.config.ts".
463
+ The following collections have been auto-generated: ${orphanedCollections.map((name) => colors.green(name)).join(", ")}
464
+ `
465
+ );
466
+ }
467
+ }
468
+ return { ...config, collections };
469
+ }
386
470
  async function reloadContentConfigObserver({
387
471
  observer = globalContentConfigObserver,
388
472
  ...loadContentConfigOpts
@@ -390,6 +474,10 @@ async function reloadContentConfigObserver({
390
474
  observer.set({ status: "loading" });
391
475
  try {
392
476
  let config = await loadContentConfig(loadContentConfigOpts);
477
+ config = await autogenerateCollections({
478
+ config,
479
+ ...loadContentConfigOpts
480
+ });
393
481
  if (config) {
394
482
  observer.set({ status: "loaded", config });
395
483
  } else {
@@ -424,20 +512,38 @@ function contentObservable(initialCtx) {
424
512
  subscribe
425
513
  };
426
514
  }
427
- function getContentPaths({ srcDir, root }, fs = fsMod) {
515
+ function getContentPaths({ srcDir, root }, fs = fsMod, legacyCollectionsBackwardsCompat = false) {
516
+ const pkgBase = new URL("../../", import.meta.url);
428
517
  const configStats = searchConfig(fs, srcDir);
429
518
  if (!configStats.exists) {
430
519
  const legacyConfigStats = searchLegacyConfig(fs, srcDir);
431
520
  if (legacyConfigStats.exists) {
432
- const relativePath = path.relative(fileURLToPath(root), fileURLToPath(legacyConfigStats.url));
433
- throw new AstroError({
434
- ...AstroErrorData.LegacyContentConfigError,
435
- message: AstroErrorData.LegacyContentConfigError.message(relativePath)
436
- });
521
+ if (!legacyCollectionsBackwardsCompat) {
522
+ const relativePath = path.relative(
523
+ fileURLToPath(root),
524
+ fileURLToPath(legacyConfigStats.url)
525
+ );
526
+ throw new AstroError({
527
+ ...AstroErrorData.LegacyContentConfigError,
528
+ message: AstroErrorData.LegacyContentConfigError.message(relativePath)
529
+ });
530
+ }
531
+ return getContentPathsWithConfig(root, srcDir, pkgBase, legacyConfigStats, fs);
437
532
  }
438
533
  }
439
534
  const liveConfigStats = searchLiveConfig(fs, srcDir);
440
- const pkgBase = new URL("../../", import.meta.url);
535
+ return {
536
+ root: new URL("./", root),
537
+ contentDir: new URL("./content/", srcDir),
538
+ assetsDir: new URL("./assets/", srcDir),
539
+ typesTemplate: new URL("templates/content/types.d.ts", pkgBase),
540
+ virtualModTemplate: new URL("templates/content/module.mjs", pkgBase),
541
+ config: configStats,
542
+ liveConfig: liveConfigStats
543
+ };
544
+ }
545
+ function getContentPathsWithConfig(root, srcDir, pkgBase, configStats, fs) {
546
+ const liveConfigStats = searchLiveConfig(fs, srcDir);
441
547
  return {
442
548
  root: new URL("./", root),
443
549
  contentDir: new URL("./content/", srcDir),
@@ -499,6 +605,21 @@ async function getEntrySlug({
499
605
  });
500
606
  return parseEntrySlug({ generatedSlug, frontmatterSlug, id, collection });
501
607
  }
608
+ function getExtGlob(exts) {
609
+ return exts.length === 1 ? (
610
+ // Wrapping {...} breaks when there is only one extension
611
+ exts[0]
612
+ ) : `{${exts.join(",")}}`;
613
+ }
614
+ function globWithUnderscoresIgnored(relContentDir, exts) {
615
+ const extGlob = getExtGlob(exts);
616
+ const contentDir = relContentDir.length > 0 ? appendForwardSlash(relContentDir) : relContentDir;
617
+ return [
618
+ `${contentDir}**/*${extGlob}`,
619
+ `!${contentDir}**/_*/**/*${extGlob}`,
620
+ `!${contentDir}**/_*${extGlob}`
621
+ ];
622
+ }
502
623
  function hasAssetPropagationFlag(id) {
503
624
  try {
504
625
  return new URL(id, "file://").searchParams.has(PROPAGATED_ASSET_FLAG);
@@ -1,6 +1,6 @@
1
- import type * as vite from 'vite';
2
1
  import { type Plugin } from 'vite';
3
2
  import type { BuildInternals } from '../core/build/internal.js';
3
+ import type { ExtractedChunk } from '../core/build/static-build.js';
4
4
  import type { AstroSettings } from '../types/astro.js';
5
5
  export declare function astroContentAssetPropagationPlugin({ settings, }: {
6
6
  settings: AstroSettings;
@@ -10,8 +10,7 @@ export declare function astroContentAssetPropagationPlugin({ settings, }: {
10
10
  * Finds chunks with LINKS_PLACEHOLDER and STYLES_PLACEHOLDER, and replaces them
11
11
  * with actual styles from propagatedStylesMap.
12
12
  */
13
- export declare function contentAssetsBuildPostHook(base: string, internals: BuildInternals, { ssrOutputs, prerenderOutputs, mutate, }: {
14
- ssrOutputs: vite.Rollup.RollupOutput[];
15
- prerenderOutputs: vite.Rollup.RollupOutput[];
16
- mutate: (chunk: vite.Rollup.OutputChunk, envs: ['server'], code: string) => void;
13
+ export declare function contentAssetsBuildPostHook(base: string, internals: BuildInternals, { chunks, mutate, }: {
14
+ chunks: ExtractedChunk[];
15
+ mutate: (fileName: string, code: string, prerender: boolean) => void;
17
16
  }): Promise<void>;
@@ -148,17 +148,10 @@ async function getStylesForURL(filePath, environment) {
148
148
  };
149
149
  }
150
150
  async function contentAssetsBuildPostHook(base, internals, {
151
- ssrOutputs,
152
- prerenderOutputs,
151
+ chunks,
153
152
  mutate
154
153
  }) {
155
- const outputs = ssrOutputs.flatMap((o) => o.output).concat(
156
- ...(Array.isArray(prerenderOutputs) ? prerenderOutputs : [prerenderOutputs]).flatMap(
157
- (o) => o.output
158
- )
159
- );
160
- for (const chunk of outputs) {
161
- if (chunk.type !== "chunk") continue;
154
+ for (const chunk of chunks) {
162
155
  if (!chunk.code.includes(LINKS_PLACEHOLDER)) continue;
163
156
  const entryStyles = /* @__PURE__ */ new Set();
164
157
  const entryLinks = /* @__PURE__ */ new Set();
@@ -189,7 +182,7 @@ async function contentAssetsBuildPostHook(base, internals, {
189
182
  } else {
190
183
  newCode = newCode.replace(JSON.stringify(LINKS_PLACEHOLDER), "[]");
191
184
  }
192
- mutate(chunk, ["server"], newCode);
185
+ mutate(chunk.fileName, newCode, chunk.prerender);
193
186
  }
194
187
  }
195
188
  export {
@@ -40,7 +40,11 @@ function astroContentImportPlugin({
40
40
  settings,
41
41
  logger
42
42
  }) {
43
- const contentPaths = getContentPaths(settings.config, fs);
43
+ const contentPaths = getContentPaths(
44
+ settings.config,
45
+ fs,
46
+ settings.config.legacy?.collectionsBackwardsCompat
47
+ );
44
48
  const contentEntryExts = getContentEntryExts(settings);
45
49
  const dataEntryExts = getDataEntryExts(settings);
46
50
  const contentEntryConfigByExt = getEntryConfigByExtMap(settings.contentEntryTypes);
@@ -46,7 +46,11 @@ function astroContentVirtualModPlugin({
46
46
  enforce: "pre",
47
47
  config(_, env) {
48
48
  dataStoreFile = getDataStoreFile(settings, env.command === "serve");
49
- const contentPaths = getContentPaths(settings.config);
49
+ const contentPaths = getContentPaths(
50
+ settings.config,
51
+ void 0,
52
+ settings.config.legacy?.collectionsBackwardsCompat
53
+ );
50
54
  if (contentPaths.liveConfig.exists) {
51
55
  liveConfig = normalizePath(fileURLToPath(contentPaths.liveConfig.url));
52
56
  }
@@ -178,7 +182,11 @@ async function generateContentEntryFile({
178
182
  settings,
179
183
  isClient
180
184
  }) {
181
- const contentPaths = getContentPaths(settings.config);
185
+ const contentPaths = getContentPaths(
186
+ settings.config,
187
+ void 0,
188
+ settings.config.legacy?.collectionsBackwardsCompat
189
+ );
182
190
  const relContentDir = rootRelativePath(settings.config.root, contentPaths.contentDir);
183
191
  let virtualModContents;
184
192
  if (isClient) {
@@ -2,4 +2,5 @@ import { BaseApp } from './base.js';
2
2
  import { AppPipeline } from './pipeline.js';
3
3
  export declare class App extends BaseApp {
4
4
  createPipeline(streaming: boolean): AppPipeline;
5
+ isDev(): boolean;
5
6
  }
@@ -7,6 +7,9 @@ class App extends BaseApp {
7
7
  streaming
8
8
  });
9
9
  }
10
+ isDev() {
11
+ return false;
12
+ }
10
13
  }
11
14
  export {
12
15
  App
@@ -6,6 +6,10 @@ import { AstroIntegrationLogger, Logger } from '../logger/core.js';
6
6
  import { type CreateRenderContext, RenderContext } from '../render-context.js';
7
7
  import type { AppPipeline } from './pipeline.js';
8
8
  import type { SSRManifest } from './types.js';
9
+ export interface DevMatch {
10
+ routeData: RouteData;
11
+ resolvedPathname: string;
12
+ }
9
13
  export interface RenderOptions {
10
14
  /**
11
15
  * Whether to automatically add all cookies written by `Astro.cookie.set()` to the response headers.
@@ -72,6 +76,7 @@ export declare abstract class BaseApp<P extends Pipeline = AppPipeline> {
72
76
  baseWithoutTrailingSlash: string;
73
77
  logger: Logger;
74
78
  constructor(manifest: SSRManifest, streaming?: boolean, ...args: any[]);
79
+ abstract isDev(): boolean;
75
80
  createRenderContext(payload: CreateRenderContext): Promise<RenderContext>;
76
81
  getAdapterLogger(): AstroIntegrationLogger;
77
82
  getAllowedDomains(): Partial<RemotePattern>[] | undefined;
@@ -104,6 +109,13 @@ export declare abstract class BaseApp<P extends Pipeline = AppPipeline> {
104
109
  * @param allowPrerenderedRoutes
105
110
  */
106
111
  match(request: Request, allowPrerenderedRoutes?: boolean): RouteData | undefined;
112
+ /**
113
+ * A matching route function to use in the development server.
114
+ * Contrary to the `.match` function, this function resolves props and params, returning the correct
115
+ * route based on the priority, segments. It also returns the correct, resolved pathname.
116
+ * @param pathname
117
+ */
118
+ devMatch(pathname?: string): Promise<DevMatch | undefined> | undefined;
107
119
  private computePathnameFromDomain;
108
120
  private redirectTrailingSlash;
109
121
  render(request: Request, renderOptions?: RenderOptions): Promise<Response>;
@@ -118,6 +118,16 @@ class BaseApp {
118
118
  }
119
119
  return routeData;
120
120
  }
121
+ /**
122
+ * A matching route function to use in the development server.
123
+ * Contrary to the `.match` function, this function resolves props and params, returning the correct
124
+ * route based on the priority, segments. It also returns the correct, resolved pathname.
125
+ * @param pathname
126
+ */
127
+ devMatch(pathname) {
128
+ pathname;
129
+ return void 0;
130
+ }
121
131
  computePathnameFromDomain(request) {
122
132
  let pathname = void 0;
123
133
  const url = new URL(request.url);
@@ -235,7 +245,14 @@ class BaseApp {
235
245
  }
236
246
  }
237
247
  if (!routeData) {
238
- routeData = this.match(request);
248
+ if (this.isDev()) {
249
+ const result = await this.devMatch(this.getPathnameFromRequest(request));
250
+ if (result) {
251
+ routeData = result.routeData;
252
+ }
253
+ } else {
254
+ routeData = this.match(request);
255
+ }
239
256
  this.logger.debug("router", "Astro matched the following route for " + request.url);
240
257
  this.logger.debug("router", "RouteData:\n" + routeData);
241
258
  }
@@ -1,7 +1,7 @@
1
1
  import type { RouteData } from '../../../types/public/index.js';
2
2
  import type { Logger } from '../../logger/core.js';
3
3
  import type { CreateRenderContext, RenderContext } from '../../render-context.js';
4
- import { BaseApp, type RenderErrorOptions } from '../base.js';
4
+ import { BaseApp, type DevMatch, type RenderErrorOptions } from '../base.js';
5
5
  import type { SSRManifest } from '../types.js';
6
6
  import { NonRunnablePipeline } from './pipeline.js';
7
7
  /**
@@ -10,9 +10,12 @@ import { NonRunnablePipeline } from './pipeline.js';
10
10
  export declare class DevApp extends BaseApp<NonRunnablePipeline> {
11
11
  logger: Logger;
12
12
  currentRenderContext: RenderContext | undefined;
13
+ resolvedPathname: string | undefined;
13
14
  constructor(manifest: SSRManifest, streaming: boolean | undefined, logger: Logger);
14
15
  createPipeline(streaming: boolean, manifest: SSRManifest, logger: Logger): NonRunnablePipeline;
16
+ isDev(): boolean;
15
17
  match(request: Request): RouteData | undefined;
18
+ devMatch(pathname: string): Promise<DevMatch | undefined>;
16
19
  createRenderContext(payload: CreateRenderContext): Promise<RenderContext>;
17
20
  renderError(request: Request, { locals, skipMiddleware, error, clientAddress, status }: RenderErrorOptions): Promise<Response>;
18
21
  }
@@ -3,9 +3,11 @@ import { isAstroError } from "../../errors/index.js";
3
3
  import { BaseApp } from "../base.js";
4
4
  import { NonRunnablePipeline } from "./pipeline.js";
5
5
  import { getCustom404Route, getCustom500Route } from "../../routing/helpers.js";
6
+ import { matchRoute } from "../../routing/dev.js";
6
7
  class DevApp extends BaseApp {
7
8
  logger;
8
9
  currentRenderContext = void 0;
10
+ resolvedPathname = void 0;
9
11
  constructor(manifest, streaming = true, logger) {
10
12
  super(manifest, streaming, logger);
11
13
  this.logger = logger;
@@ -17,12 +19,31 @@ class DevApp extends BaseApp {
17
19
  streaming
18
20
  });
19
21
  }
22
+ isDev() {
23
+ return true;
24
+ }
20
25
  match(request) {
21
26
  return super.match(request, true);
22
27
  }
28
+ async devMatch(pathname) {
29
+ const matchedRoute = await matchRoute(
30
+ pathname,
31
+ this.manifestData,
32
+ this.pipeline,
33
+ this.manifest
34
+ );
35
+ if (!matchedRoute) return void 0;
36
+ this.resolvedPathname = matchedRoute.resolvedPathname;
37
+ return {
38
+ routeData: matchedRoute.route,
39
+ resolvedPathname: matchedRoute.resolvedPathname
40
+ };
41
+ }
23
42
  async createRenderContext(payload) {
24
- this.currentRenderContext = await super.createRenderContext(payload);
25
- return this.currentRenderContext;
43
+ return super.createRenderContext({
44
+ ...payload,
45
+ pathname: this.resolvedPathname ?? payload.pathname
46
+ });
26
47
  }
27
48
  async renderError(request, { locals, skipMiddleware = false, error, clientAddress, status }) {
28
49
  if (isAstroError(error) && [MiddlewareNoDataOrNextCalled.name, MiddlewareNotAResponse.name].includes(error.name)) {
@@ -34,7 +55,7 @@ class DevApp extends BaseApp {
34
55
  const renderContext = await this.createRenderContext({
35
56
  locals,
36
57
  pipeline: this.pipeline,
37
- pathname: this.getPathnameFromRequest(request),
58
+ pathname: await this.getPathnameFromRequest(request),
38
59
  skipMiddleware,
39
60
  request,
40
61
  routeData,
@@ -5,6 +5,7 @@ import { BuildPipeline } from './pipeline.js';
5
5
  import type { StaticBuildOptions } from './types.js';
6
6
  export declare class BuildApp extends BaseApp<BuildPipeline> {
7
7
  createPipeline(_streaming: boolean, manifest: SSRManifest, ..._args: any[]): BuildPipeline;
8
+ isDev(): boolean;
8
9
  setInternals(internals: BuildInternals): void;
9
10
  setOptions(options: StaticBuildOptions): void;
10
11
  getOptions(): StaticBuildOptions;
@@ -6,6 +6,9 @@ class BuildApp extends BaseApp {
6
6
  manifest
7
7
  });
8
8
  }
9
+ isDev() {
10
+ return true;
11
+ }
9
12
  setInternals(internals) {
10
13
  this.pipeline.setInternals(internals);
11
14
  }
@@ -17,7 +17,7 @@ import { createVite } from "../create-vite.js";
17
17
  import { createKey, getEnvironmentKey, hasEnvironmentKey } from "../encryption.js";
18
18
  import { AstroError, AstroErrorData } from "../errors/index.js";
19
19
  import { levels, timerMessage } from "../logger/core.js";
20
- import { createRoutesList } from "../routing/index.js";
20
+ import { createRoutesList } from "../routing/manifest/create.js";
21
21
  import { clearContentLayerCache } from "../sync/index.js";
22
22
  import { ensureProcessNodeEnv } from "../util.js";
23
23
  import { collectPagesData } from "./page-data.js";
@@ -1,5 +1,4 @@
1
- import type { OutputChunk } from 'rollup';
2
- import type * as vite from 'vite';
1
+ import type { ExtractedChunk } from '../static-build.js';
3
2
  import type { BuildInternals } from '../internal.js';
4
3
  import type { StaticBuildOptions } from '../types.js';
5
4
  /**
@@ -27,8 +26,7 @@ export declare const MANIFEST_REPLACE = "@@ASTRO_MANIFEST_REPLACE@@";
27
26
  * Post-build hook that injects the computed manifest into bundled chunks.
28
27
  * Finds the serialized manifest chunk and replaces the placeholder token with real data.
29
28
  */
30
- export declare function manifestBuildPostHook(options: StaticBuildOptions, internals: BuildInternals, { ssrOutputs, prerenderOutputs, mutate, }: {
31
- ssrOutputs: vite.Rollup.RollupOutput[];
32
- prerenderOutputs: vite.Rollup.RollupOutput[];
33
- mutate: (chunk: OutputChunk, envs: ['server'], code: string) => void;
29
+ export declare function manifestBuildPostHook(options: StaticBuildOptions, internals: BuildInternals, { chunks, mutate, }: {
30
+ chunks: ExtractedChunk[];
31
+ mutate: (fileName: string, code: string, prerender: boolean) => void;
34
32
  }): Promise<void>;
@@ -29,30 +29,14 @@ import { sessionConfigToManifest } from "../../session/utils.js";
29
29
  const MANIFEST_REPLACE = "@@ASTRO_MANIFEST_REPLACE@@";
30
30
  const replaceExp = new RegExp(`['"]${MANIFEST_REPLACE}['"]`, "g");
31
31
  async function manifestBuildPostHook(options, internals, {
32
- ssrOutputs,
33
- prerenderOutputs,
32
+ chunks,
34
33
  mutate
35
34
  }) {
36
35
  const manifest = await createManifest(options, internals);
37
- if (ssrOutputs.length > 0) {
38
- let manifestEntryChunk;
39
- for (const output of ssrOutputs) {
40
- for (const chunk of output.output) {
41
- if (chunk.type === "asset") {
42
- continue;
43
- }
44
- if (chunk.code && chunk.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)) {
45
- manifestEntryChunk = chunk;
46
- break;
47
- }
48
- }
49
- if (manifestEntryChunk) {
50
- break;
51
- }
52
- }
53
- if (!manifestEntryChunk) {
54
- throw new Error(`Did not find serialized manifest chunk for SSR`);
55
- }
36
+ const ssrManifestChunk = chunks.find(
37
+ (c) => !c.prerender && c.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)
38
+ );
39
+ if (ssrManifestChunk) {
56
40
  const shouldPassMiddlewareEntryPoint = options.settings.adapter?.adapterFeatures?.edgeMiddleware;
57
41
  await runHookBuildSsr({
58
42
  config: options.settings.config,
@@ -60,29 +44,15 @@ async function manifestBuildPostHook(options, internals, {
60
44
  logger: options.logger,
61
45
  middlewareEntryPoint: shouldPassMiddlewareEntryPoint ? internals.middlewareEntryPoint : void 0
62
46
  });
63
- const code = injectManifest(manifest, manifestEntryChunk);
64
- mutate(manifestEntryChunk, ["server"], code);
47
+ const code = injectManifest(manifest, ssrManifestChunk.code);
48
+ mutate(ssrManifestChunk.fileName, code, false);
65
49
  }
66
- if (prerenderOutputs?.length > 0) {
67
- let prerenderManifestChunk;
68
- for (const output of prerenderOutputs) {
69
- for (const chunk of output.output) {
70
- if (chunk.type === "asset") {
71
- continue;
72
- }
73
- if (chunk.code && chunk.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)) {
74
- prerenderManifestChunk = chunk;
75
- break;
76
- }
77
- }
78
- if (prerenderManifestChunk) {
79
- break;
80
- }
81
- }
82
- if (prerenderManifestChunk) {
83
- const prerenderCode = injectManifest(manifest, prerenderManifestChunk);
84
- mutate(prerenderManifestChunk, ["server"], prerenderCode);
85
- }
50
+ const prerenderManifestChunk = chunks.find(
51
+ (c) => c.prerender && c.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID)
52
+ );
53
+ if (prerenderManifestChunk) {
54
+ const code = injectManifest(manifest, prerenderManifestChunk.code);
55
+ mutate(prerenderManifestChunk.fileName, code, true);
86
56
  }
87
57
  }
88
58
  async function createManifest(buildOpts, internals) {
@@ -99,8 +69,7 @@ async function createManifest(buildOpts, internals) {
99
69
  const manifest = await buildManifest(buildOpts, internals, Array.from(staticFiles), encodedKey);
100
70
  return manifest;
101
71
  }
102
- function injectManifest(manifest, chunk) {
103
- const code = chunk.code;
72
+ function injectManifest(manifest, code) {
104
73
  return code.replace(replaceExp, () => {
105
74
  return JSON.stringify(manifest);
106
75
  });
@@ -1,6 +1,16 @@
1
1
  import { type BuildInternals } from '../../core/build/internal.js';
2
2
  import type { RouteData } from '../../types/public/internal.js';
3
3
  import type { StaticBuildOptions } from './types.js';
4
+ /**
5
+ * Minimal chunk data extracted from RollupOutput for deferred manifest/content injection.
6
+ * Allows releasing full RollupOutput objects early to reduce memory usage.
7
+ */
8
+ export interface ExtractedChunk {
9
+ fileName: string;
10
+ code: string;
11
+ moduleIds: string[];
12
+ prerender: boolean;
13
+ }
4
14
  export declare function viteBuild(opts: StaticBuildOptions): Promise<{
5
15
  internals: BuildInternals;
6
16
  prerenderOutputDir: URL;