astro 2.6.6 → 2.7.1

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 (79) hide show
  1. package/README.md +3 -6
  2. package/dist/@types/astro.d.ts +30 -15
  3. package/dist/assets/utils/emitAsset.js +1 -2
  4. package/dist/content/utils.d.ts +1 -2
  5. package/dist/content/utils.js +3 -4
  6. package/dist/content/vite-plugin-content-imports.js +0 -1
  7. package/dist/content/vite-plugin-content-virtual-mod.d.ts +1 -1
  8. package/dist/content/vite-plugin-content-virtual-mod.js +7 -1
  9. package/dist/core/add/babel.d.ts +8 -2
  10. package/dist/core/app/index.d.ts +3 -4
  11. package/dist/core/app/index.js +21 -14
  12. package/dist/core/app/node.d.ts +1 -1
  13. package/dist/core/app/node.js +9 -5
  14. package/dist/core/app/types.d.ts +5 -5
  15. package/dist/core/build/generate.js +9 -12
  16. package/dist/core/build/index.js +1 -8
  17. package/dist/core/build/internal.d.ts +3 -1
  18. package/dist/core/build/internal.js +5 -6
  19. package/dist/core/build/plugins/index.js +2 -1
  20. package/dist/core/build/plugins/plugin-middleware.js +15 -0
  21. package/dist/core/build/plugins/plugin-pages.d.ts +1 -2
  22. package/dist/core/build/plugins/plugin-pages.js +6 -9
  23. package/dist/core/build/plugins/plugin-ssr.d.ts +13 -2
  24. package/dist/core/build/plugins/plugin-ssr.js +220 -73
  25. package/dist/core/build/plugins/util.d.ts +15 -0
  26. package/dist/core/build/plugins/util.js +17 -1
  27. package/dist/core/build/static-build.d.ts +33 -0
  28. package/dist/core/build/static-build.js +57 -26
  29. package/dist/core/build/types.d.ts +5 -3
  30. package/dist/core/compile/compile.js +0 -5
  31. package/dist/core/compile/style.js +0 -1
  32. package/dist/core/config/schema.d.ts +12 -0
  33. package/dist/core/config/schema.js +6 -3
  34. package/dist/core/config/settings.js +1 -1
  35. package/dist/core/constants.js +1 -1
  36. package/dist/core/dev/dev.js +1 -1
  37. package/dist/core/endpoint/dev/index.js +1 -1
  38. package/dist/core/endpoint/index.d.ts +2 -2
  39. package/dist/core/endpoint/index.js +3 -3
  40. package/dist/core/errors/dev/vite.js +1 -9
  41. package/dist/core/errors/errors-data.d.ts +29 -70
  42. package/dist/core/errors/errors-data.js +20 -75
  43. package/dist/core/errors/errors.d.ts +1 -9
  44. package/dist/core/errors/errors.js +8 -9
  45. package/dist/core/errors/index.d.ts +1 -1
  46. package/dist/core/errors/utils.d.ts +2 -3
  47. package/dist/core/errors/utils.js +3 -3
  48. package/dist/core/messages.js +2 -2
  49. package/dist/core/module-loader/loader.d.ts +4 -0
  50. package/dist/core/redirects/component.js +1 -4
  51. package/dist/core/render/context.d.ts +1 -0
  52. package/dist/core/render/context.js +17 -1
  53. package/dist/core/render/core.d.ts +3 -3
  54. package/dist/core/render/core.js +3 -4
  55. package/dist/core/render/dev/index.js +18 -8
  56. package/dist/core/render/dev/vite.js +25 -19
  57. package/dist/core/render/ssr-element.js +3 -4
  58. package/dist/core/request.d.ts +2 -1
  59. package/dist/core/request.js +3 -2
  60. package/dist/core/routing/manifest/create.js +3 -4
  61. package/dist/core/util.d.ts +1 -0
  62. package/dist/core/util.js +5 -4
  63. package/dist/events/error.d.ts +0 -1
  64. package/dist/events/error.js +1 -5
  65. package/dist/integrations/index.d.ts +6 -7
  66. package/dist/integrations/index.js +8 -11
  67. package/dist/jsx/babel.js +3 -3
  68. package/dist/vite-plugin-astro/compile.js +2 -0
  69. package/dist/vite-plugin-astro-server/route.js +4 -1
  70. package/dist/vite-plugin-jsx/index.js +2 -0
  71. package/dist/vite-plugin-load-fallback/index.js +2 -2
  72. package/dist/vite-plugin-markdown/content-entry-type.d.ts +0 -5
  73. package/dist/vite-plugin-markdown/content-entry-type.js +1 -26
  74. package/dist/vite-plugin-markdown/index.js +0 -2
  75. package/package.json +39 -40
  76. package/dist/content/template/types.d.js +0 -0
  77. package/dist/content/template/virtual-mod.d.mts +0 -7
  78. /package/{src/content/template/virtual-mod.mjs → content-module.template.mjs} +0 -0
  79. /package/{src/content/template/types.d.ts → content-types.template.d.ts} +0 -0
package/README.md CHANGED
@@ -8,10 +8,8 @@
8
8
  <br/><br/>
9
9
  </p>
10
10
 
11
-
12
11
  ## Install
13
12
 
14
-
15
13
  ```bash
16
14
  # Recommended!
17
15
  npm create astro@latest
@@ -20,7 +18,7 @@ npm create astro@latest
20
18
  npm install --save-dev astro
21
19
  ```
22
20
 
23
- Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide.
21
+ Looking for help? Start with our [Getting Started](https://docs.astro.build/en/getting-started/) guide.
24
22
 
25
23
  Looking for quick examples? [Open a starter project](https://astro.new/) right in your browser.
26
24
 
@@ -31,9 +29,10 @@ Visit our [official documentation](https://docs.astro.build/).
31
29
  ## Support
32
30
 
33
31
  Having trouble? Get help in the official [Astro Discord](https://astro.build/chat).
32
+
34
33
  ## Contributing
35
34
 
36
- **New contributors welcome!** Check out our [Contributors Guide](/CONTRIBUTING.md) for help getting started.
35
+ **New contributors welcome!** Check out our [Contributors Guide](/CONTRIBUTING.md) for help getting started.
37
36
 
38
37
  Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll help you get your first contribution in no time!
39
38
 
@@ -42,5 +41,3 @@ Join us on [Discord](https://astro.build/chat) to meet other maintainers. We'll
42
41
  Astro is generously supported by [Netlify](https://www.netlify.com/), [Vercel](https://vercel.com/), and several other amazing organizations [listed here.](https://astro.build/)
43
42
 
44
43
  [❤️ Sponsor Astro! ❤️](https://github.com/withastro/.github/blob/main/FUNDING.md)
45
-
46
-
@@ -75,20 +75,6 @@ export interface CLIFlags {
75
75
  experimentalAssets?: boolean;
76
76
  experimentalRedirects?: boolean;
77
77
  }
78
- export interface BuildConfig {
79
- /**
80
- * @deprecated Use config.build.client instead.
81
- */
82
- client: URL;
83
- /**
84
- * @deprecated Use config.build.server instead.
85
- */
86
- server: URL;
87
- /**
88
- * @deprecated Use config.build.serverEntry instead.
89
- */
90
- serverEntry: string;
91
- }
92
78
  /**
93
79
  * Astro global available in all contexts in .astro files
94
80
  *
@@ -773,6 +759,29 @@ export interface AstroUserConfig {
773
759
  * ```
774
760
  */
775
761
  inlineStylesheets?: 'always' | 'auto' | 'never';
762
+ /**
763
+ * @docs
764
+ * @name build.split
765
+ * @type {boolean}
766
+ * @default {false}
767
+ * @version 2.7.0
768
+ * @description
769
+ * Defines how the SSR code should be bundled when built.
770
+ *
771
+ * When `split` is `true`, Astro will emit a file for each page.
772
+ * Each file emitted will render only one page. The pages will be emitted
773
+ * inside a `dist/pages/` directory, and the emitted files will keep the same file paths
774
+ * of the `src/pages` directory.
775
+ *
776
+ * ```js
777
+ * {
778
+ * build: {
779
+ * split: true
780
+ * }
781
+ * }
782
+ * ```
783
+ */
784
+ split?: boolean;
776
785
  };
777
786
  /**
778
787
  * @docs
@@ -793,7 +802,7 @@ export interface AstroUserConfig {
793
802
  * ```js
794
803
  * {
795
804
  * // Example: Use the function syntax to customize based on command
796
- * server: (command) => ({ port: command === 'dev' ? 3000 : 4000 })
805
+ * server: ({ command }) => ({ port: command === 'dev' ? 3000 : 4000 })
797
806
  * }
798
807
  * ```
799
808
  */
@@ -1173,6 +1182,7 @@ export type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' |
1173
1182
  export interface InjectedRoute {
1174
1183
  pattern: string;
1175
1184
  entryPoint: string;
1185
+ prerender?: boolean;
1176
1186
  }
1177
1187
  export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
1178
1188
  integrations: AstroIntegration[];
@@ -1649,6 +1659,11 @@ export interface AstroIntegration {
1649
1659
  'astro:server:done'?: () => void | Promise<void>;
1650
1660
  'astro:build:ssr'?: (options: {
1651
1661
  manifest: SerializedSSRManifest;
1662
+ /**
1663
+ * This maps a {@link RouteData} to an {@link URL}, this URL represents
1664
+ * the physical file you should import.
1665
+ */
1666
+ entryPoints: Map<RouteData, URL>;
1652
1667
  }) => void | Promise<void>;
1653
1668
  'astro:build:start'?: () => void | Promise<void>;
1654
1669
  'astro:build:setup'?: (options: {
@@ -1,8 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath, pathToFileURL } from "node:url";
4
- import slash from "slash";
5
- import { prependForwardSlash } from "../../core/path.js";
4
+ import { prependForwardSlash, slash } from "../../core/path.js";
6
5
  import { imageMetadata } from "./metadata.js";
7
6
  async function emitESMImage(id, watchMode, fileEmitter) {
8
7
  if (!id) {
@@ -9,7 +9,7 @@ import { CONTENT_FLAGS } from './consts.js';
9
9
  /**
10
10
  * Amap from a collection + slug to the local file path.
11
11
  * This is used internally to resolve entry imports when using `getEntry()`.
12
- * @see `src/content/virtual-mod.mjs`
12
+ * @see `content-module.template.mjs`
13
13
  */
14
14
  export type ContentLookupMap = {
15
15
  [collectionName: string]: {
@@ -164,7 +164,6 @@ export type ContentPaths = {
164
164
  cacheDir: URL;
165
165
  typesTemplate: URL;
166
166
  virtualModTemplate: URL;
167
- virtualAssetsModTemplate: URL;
168
167
  config: {
169
168
  exists: boolean;
170
169
  url: URL;
@@ -288,14 +288,13 @@ function contentObservable(initialCtx) {
288
288
  }
289
289
  function getContentPaths({ srcDir, root }, fs = fsMod) {
290
290
  const configStats = search(fs, srcDir);
291
- const templateDir = new URL("../../src/content/template/", import.meta.url);
291
+ const pkgBase = new URL("../../", import.meta.url);
292
292
  return {
293
293
  cacheDir: new URL(".astro/", root),
294
294
  contentDir: new URL("./content/", srcDir),
295
295
  assetsDir: new URL("./assets/", srcDir),
296
- typesTemplate: new URL("types.d.ts", templateDir),
297
- virtualModTemplate: new URL("virtual-mod.mjs", templateDir),
298
- virtualAssetsModTemplate: new URL("virtual-mod-assets.mjs", templateDir),
296
+ typesTemplate: new URL("content-types.template.d.ts", pkgBase),
297
+ virtualModTemplate: new URL("content-module.template.mjs", pkgBase),
299
298
  config: configStats
300
299
  };
301
300
  }
@@ -277,7 +277,6 @@ function stringifyEntryData(data) {
277
277
  });
278
278
  } else {
279
279
  throw new AstroError({
280
- code: 99999,
281
280
  message: "Unexpected error processing content collection data."
282
281
  });
283
282
  }
@@ -10,7 +10,7 @@ export declare function astroContentVirtualModPlugin({ settings, }: AstroContent
10
10
  /**
11
11
  * Generate a map from a collection + slug to the local file path.
12
12
  * This is used internally to resolve entry imports when using `getEntry()`.
13
- * @see `src/content/virtual-mod.mjs`
13
+ * @see `content-module.template.mjs`
14
14
  */
15
15
  export declare function getStringifiedLookupMap({ contentPaths, contentEntryConfigByExt, dataEntryExts, root, fs, }: {
16
16
  contentEntryConfigByExt: Map<string, ContentEntryType>;
@@ -4,6 +4,7 @@ import { extname } from "node:path";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import pLimit from "p-limit";
6
6
  import { AstroError, AstroErrorData } from "../core/errors/index.js";
7
+ import { appendForwardSlash } from "../core/path.js";
7
8
  import { rootRelativePath } from "../core/util.js";
8
9
  import { VIRTUAL_MODULE_ID } from "./consts.js";
9
10
  import {
@@ -164,7 +165,12 @@ const UnexpectedLookupMapError = new AstroError({
164
165
  });
165
166
  function globWithUnderscoresIgnored(relContentDir, exts) {
166
167
  const extGlob = getExtGlob(exts);
167
- return [`${relContentDir}/**/*${extGlob}`, `!**/_*/**${extGlob}`, `!**/_*${extGlob}`];
168
+ const contentDir = appendForwardSlash(relContentDir);
169
+ return [
170
+ `${contentDir}**/*${extGlob}`,
171
+ `!${contentDir}_*/**${extGlob}`,
172
+ `!${contentDir}_*${extGlob}`
173
+ ];
168
174
  }
169
175
  export {
170
176
  astroContentVirtualModPlugin,
@@ -1,11 +1,17 @@
1
1
  import parser from '@babel/parser';
2
2
  import * as t from '@babel/types';
3
3
  export declare const visit: {
4
- <S>(parent: t.Node | t.Node[] | null | undefined, opts: import("@babel/traverse").TraverseOptions<S>, scope: import("@babel/traverse").Scope | undefined, state: S, parentPath?: import("@babel/traverse").NodePath<t.Node> | undefined): void;
5
- (parent: t.Node | t.Node[] | null | undefined, opts?: import("@babel/traverse").TraverseOptions<t.Node> | undefined, scope?: import("@babel/traverse").Scope | undefined, state?: any, parentPath?: import("@babel/traverse").NodePath<t.Node> | undefined): void;
4
+ <S>(parent: t.Node, opts: import("@babel/traverse").TraverseOptions<S>, scope: import("@babel/traverse").Scope | undefined, state: S, parentPath?: import("@babel/traverse").NodePath<t.Node> | undefined): void;
5
+ (parent: t.Node, opts?: import("@babel/traverse").TraverseOptions<t.Node> | undefined, scope?: import("@babel/traverse").Scope | undefined, state?: any, parentPath?: import("@babel/traverse").NodePath<t.Node> | undefined): void;
6
6
  visitors: typeof import("@babel/traverse").visitors;
7
7
  verify: typeof import("@babel/traverse").visitors.verify;
8
8
  explode: typeof import("@babel/traverse").visitors.explode;
9
+ cheap: (node: t.Node, enter: (node: t.Node) => void) => void;
10
+ node: (node: t.Node, opts: import("@babel/traverse").TraverseOptions<t.Node>, scope?: import("@babel/traverse").Scope | undefined, state?: any, path?: import("@babel/traverse").NodePath<t.Node> | undefined, skipKeys?: Record<string, boolean> | undefined) => void;
11
+ clearNode: (node: t.Node, opts?: t.RemovePropertiesOptions | undefined) => void;
12
+ removeProperties: (tree: t.Node, opts?: t.RemovePropertiesOptions | undefined) => t.Node;
13
+ hasType: (tree: t.Node, type: "JSXAttribute" | "JSXSpreadAttribute" | "JSXIdentifier" | "JSXNamespacedName" | "Identifier" | "JSXElement" | "JSXOpeningElement" | "JSXMemberExpression" | "AnyTypeAnnotation" | "ArgumentPlaceholder" | "ArrayExpression" | "ArrayPattern" | "ArrayTypeAnnotation" | "ArrowFunctionExpression" | "AssignmentExpression" | "AssignmentPattern" | "AwaitExpression" | "BigIntLiteral" | "BinaryExpression" | "BindExpression" | "BlockStatement" | "BooleanLiteral" | "BooleanLiteralTypeAnnotation" | "BooleanTypeAnnotation" | "BreakStatement" | "CallExpression" | "CatchClause" | "ClassAccessorProperty" | "ClassBody" | "ClassDeclaration" | "ClassExpression" | "ClassImplements" | "ClassMethod" | "ClassPrivateMethod" | "ClassPrivateProperty" | "ClassProperty" | "ConditionalExpression" | "ContinueStatement" | "DebuggerStatement" | "DecimalLiteral" | "DeclareClass" | "DeclareExportAllDeclaration" | "DeclareExportDeclaration" | "DeclareFunction" | "DeclareInterface" | "DeclareModule" | "DeclareModuleExports" | "DeclareOpaqueType" | "DeclareTypeAlias" | "DeclareVariable" | "DeclaredPredicate" | "Decorator" | "Directive" | "DirectiveLiteral" | "DoExpression" | "DoWhileStatement" | "EmptyStatement" | "EmptyTypeAnnotation" | "EnumBooleanBody" | "EnumBooleanMember" | "EnumDeclaration" | "EnumDefaultedMember" | "EnumNumberBody" | "EnumNumberMember" | "EnumStringBody" | "EnumStringMember" | "EnumSymbolBody" | "ExistsTypeAnnotation" | "ExportAllDeclaration" | "ExportDefaultDeclaration" | "ExportDefaultSpecifier" | "ExportNamedDeclaration" | "ExportNamespaceSpecifier" | "ExportSpecifier" | "ExpressionStatement" | "File" | "ForInStatement" | "ForOfStatement" | "ForStatement" | "FunctionDeclaration" | "FunctionExpression" | "FunctionTypeAnnotation" | "FunctionTypeParam" | "GenericTypeAnnotation" | "IfStatement" | "Import" | "ImportAttribute" | "ImportDeclaration" | "ImportDefaultSpecifier" | "ImportNamespaceSpecifier" | "ImportSpecifier" | "IndexedAccessType" | "InferredPredicate" | "InterfaceDeclaration" | "InterfaceExtends" | "InterfaceTypeAnnotation" | "InterpreterDirective" | "IntersectionTypeAnnotation" | "JSXClosingElement" | "JSXClosingFragment" | "JSXEmptyExpression" | "JSXExpressionContainer" | "JSXFragment" | "JSXOpeningFragment" | "JSXSpreadChild" | "JSXText" | "LabeledStatement" | "LogicalExpression" | "MemberExpression" | "MetaProperty" | "MixedTypeAnnotation" | "ModuleExpression" | "NewExpression" | "Noop" | "NullLiteral" | "NullLiteralTypeAnnotation" | "NullableTypeAnnotation" | "NumberLiteral" | "NumberLiteralTypeAnnotation" | "NumberTypeAnnotation" | "NumericLiteral" | "ObjectExpression" | "ObjectMethod" | "ObjectPattern" | "ObjectProperty" | "ObjectTypeAnnotation" | "ObjectTypeCallProperty" | "ObjectTypeIndexer" | "ObjectTypeInternalSlot" | "ObjectTypeProperty" | "ObjectTypeSpreadProperty" | "OpaqueType" | "OptionalCallExpression" | "OptionalIndexedAccessType" | "OptionalMemberExpression" | "ParenthesizedExpression" | "PipelineBareFunction" | "PipelinePrimaryTopicReference" | "PipelineTopicExpression" | "Placeholder" | "PrivateName" | "Program" | "QualifiedTypeIdentifier" | "RecordExpression" | "RegExpLiteral" | "RegexLiteral" | "RestElement" | "RestProperty" | "ReturnStatement" | "SequenceExpression" | "SpreadElement" | "SpreadProperty" | "StaticBlock" | "StringLiteral" | "StringLiteralTypeAnnotation" | "StringTypeAnnotation" | "Super" | "SwitchCase" | "SwitchStatement" | "SymbolTypeAnnotation" | "TSAnyKeyword" | "TSArrayType" | "TSAsExpression" | "TSBigIntKeyword" | "TSBooleanKeyword" | "TSCallSignatureDeclaration" | "TSConditionalType" | "TSConstructSignatureDeclaration" | "TSConstructorType" | "TSDeclareFunction" | "TSDeclareMethod" | "TSEnumDeclaration" | "TSEnumMember" | "TSExportAssignment" | "TSExpressionWithTypeArguments" | "TSExternalModuleReference" | "TSFunctionType" | "TSImportEqualsDeclaration" | "TSImportType" | "TSIndexSignature" | "TSIndexedAccessType" | "TSInferType" | "TSInstantiationExpression" | "TSInterfaceBody" | "TSInterfaceDeclaration" | "TSIntersectionType" | "TSIntrinsicKeyword" | "TSLiteralType" | "TSMappedType" | "TSMethodSignature" | "TSModuleBlock" | "TSModuleDeclaration" | "TSNamedTupleMember" | "TSNamespaceExportDeclaration" | "TSNeverKeyword" | "TSNonNullExpression" | "TSNullKeyword" | "TSNumberKeyword" | "TSObjectKeyword" | "TSOptionalType" | "TSParameterProperty" | "TSParenthesizedType" | "TSPropertySignature" | "TSQualifiedName" | "TSRestType" | "TSSatisfiesExpression" | "TSStringKeyword" | "TSSymbolKeyword" | "TSThisType" | "TSTupleType" | "TSTypeAliasDeclaration" | "TSTypeAnnotation" | "TSTypeAssertion" | "TSTypeLiteral" | "TSTypeOperator" | "TSTypeParameter" | "TSTypeParameterDeclaration" | "TSTypeParameterInstantiation" | "TSTypePredicate" | "TSTypeQuery" | "TSTypeReference" | "TSUndefinedKeyword" | "TSUnionType" | "TSUnknownKeyword" | "TSVoidKeyword" | "TaggedTemplateExpression" | "TemplateElement" | "TemplateLiteral" | "ThisExpression" | "ThisTypeAnnotation" | "ThrowStatement" | "TopicReference" | "TryStatement" | "TupleExpression" | "TupleTypeAnnotation" | "TypeAlias" | "TypeAnnotation" | "TypeCastExpression" | "TypeParameter" | "TypeParameterDeclaration" | "TypeParameterInstantiation" | "TypeofTypeAnnotation" | "UnaryExpression" | "UnionTypeAnnotation" | "UpdateExpression" | "V8IntrinsicIdentifier" | "VariableDeclaration" | "VariableDeclarator" | "Variance" | "VoidTypeAnnotation" | "WhileStatement" | "WithStatement" | "YieldExpression", denylistTypes?: string[] | undefined) => boolean;
14
+ cache: typeof import("@babel/traverse").cache;
9
15
  };
10
16
  export { t };
11
17
  export declare function generate(ast: t.File): Promise<string>;
@@ -1,14 +1,13 @@
1
- import type { RouteData } from '../../@types/astro';
2
- import type { SSRManifest as Manifest } from './types';
1
+ import type { RouteData, SSRManifest } from '../../@types/astro';
3
2
  export { deserializeManifest } from './common.js';
4
3
  export interface MatchOptions {
5
4
  matchNotFound?: boolean | undefined;
6
5
  }
7
6
  export declare class App {
8
7
  #private;
9
- constructor(manifest: Manifest, streaming?: boolean);
8
+ constructor(manifest: SSRManifest, streaming?: boolean);
10
9
  removeBase(pathname: string): string;
11
10
  match(request: Request, { matchNotFound }?: MatchOptions): RouteData | undefined;
12
- render(request: Request, routeData?: RouteData): Promise<Response>;
11
+ render(request: Request, routeData?: RouteData, locals?: object): Promise<Response>;
13
12
  setCookieHeaders(response: Response): Generator<string, string[], unknown>;
14
13
  }
@@ -95,7 +95,7 @@ class App {
95
95
  return void 0;
96
96
  }
97
97
  }
98
- async render(request, routeData) {
98
+ async render(request, routeData, locals) {
99
99
  let defaultStatus = 200;
100
100
  if (!routeData) {
101
101
  routeData = this.match(request);
@@ -110,7 +110,7 @@ class App {
110
110
  });
111
111
  }
112
112
  }
113
- Reflect.set(request, clientLocalsSymbol, {});
113
+ Reflect.set(request, clientLocalsSymbol, locals ?? {});
114
114
  if (routeData.route === "/404") {
115
115
  defaultStatus = 404;
116
116
  }
@@ -147,18 +147,26 @@ class App {
147
147
  if (route.type === "redirect") {
148
148
  return RedirectSinglePageBuiltModule;
149
149
  } else {
150
- const importComponentInstance = this.#manifest.pageMap.get(route.component);
151
- if (!importComponentInstance) {
150
+ if (this.#manifest.pageMap) {
151
+ const importComponentInstance = this.#manifest.pageMap.get(route.component);
152
+ if (!importComponentInstance) {
153
+ throw new Error(
154
+ `Unexpectedly unable to find a component instance for route ${route.route}`
155
+ );
156
+ }
157
+ const pageModule = await importComponentInstance();
158
+ return pageModule;
159
+ } else if (this.#manifest.pageModule) {
160
+ const importComponentInstance = this.#manifest.pageModule;
161
+ return importComponentInstance;
162
+ } else {
152
163
  throw new Error(
153
- `Unexpectedly unable to find a component instance for route ${route.route}`
164
+ "Astro couldn't find the correct page to render, probably because it wasn't correctly mapped for SSR usage. This is an internal error, please file an issue."
154
165
  );
155
166
  }
156
- const built = await importComponentInstance();
157
- return built;
158
167
  }
159
168
  }
160
169
  async #renderPage(request, routeData, page, status = 200) {
161
- var _a;
162
170
  const url = new URL(request.url);
163
171
  const pathname = prependForwardSlash(this.removeBase(url.pathname));
164
172
  const info = this.#routeDataToRouteInfo.get(routeData);
@@ -199,15 +207,14 @@ class App {
199
207
  site: this.#env.site,
200
208
  adapterName: this.#env.adapterName
201
209
  });
202
- const onRequest = (_a = page.middleware) == null ? void 0 : _a.onRequest;
203
210
  let response;
204
- if (onRequest) {
211
+ if (page.onRequest) {
205
212
  response = await callMiddleware(
206
213
  this.#env.logging,
207
- onRequest,
214
+ page.onRequest,
208
215
  apiContext,
209
216
  () => {
210
- return renderPage({ mod, renderContext, env: this.#env, apiContext });
217
+ return renderPage({ mod, renderContext, env: this.#env, cookies: apiContext.cookies });
211
218
  }
212
219
  );
213
220
  } else {
@@ -215,7 +222,7 @@ class App {
215
222
  mod,
216
223
  renderContext,
217
224
  env: this.#env,
218
- apiContext
225
+ cookies: apiContext.cookies
219
226
  });
220
227
  }
221
228
  Reflect.set(request, responseSentSymbol, true);
@@ -242,7 +249,7 @@ class App {
242
249
  env: this.#env,
243
250
  mod: handler
244
251
  });
245
- const result = await callEndpoint(handler, this.#env, ctx, this.#logging, page.middleware);
252
+ const result = await callEndpoint(handler, this.#env, ctx, this.#logging, page.onRequest);
246
253
  if (result.type === "response") {
247
254
  if (result.response.headers.get("X-Astro-Response") === "Not-Found") {
248
255
  const fourOhFourRequest = new Request(new URL("/404", request.url));
@@ -11,7 +11,7 @@ declare class NodeIncomingMessage extends IncomingMessage {
11
11
  }
12
12
  export declare class NodeApp extends App {
13
13
  match(req: NodeIncomingMessage | Request, opts?: MatchOptions): RouteData | undefined;
14
- render(req: NodeIncomingMessage | Request, routeData?: RouteData): Promise<Response>;
14
+ render(req: NodeIncomingMessage | Request, routeData?: RouteData, locals?: object): Promise<Response>;
15
15
  }
16
16
  export declare function loadManifest(rootFolder: URL): Promise<SSRManifest>;
17
17
  export declare function loadApp(rootFolder: URL): Promise<NodeApp>;
@@ -28,17 +28,19 @@ class NodeApp extends App {
28
28
  match(req, opts = {}) {
29
29
  return super.match(req instanceof Request ? req : createRequestFromNodeRequest(req), opts);
30
30
  }
31
- render(req, routeData) {
31
+ render(req, routeData, locals) {
32
32
  if (typeof req.body === "string" && req.body.length > 0) {
33
33
  return super.render(
34
34
  req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(req.body)),
35
- routeData
35
+ routeData,
36
+ locals
36
37
  );
37
38
  }
38
39
  if (typeof req.body === "object" && req.body !== null && Object.keys(req.body).length > 0) {
39
40
  return super.render(
40
41
  req instanceof Request ? req : createRequestFromNodeRequest(req, Buffer.from(JSON.stringify(req.body))),
41
- routeData
42
+ routeData,
43
+ locals
42
44
  );
43
45
  }
44
46
  if ("on" in req) {
@@ -57,13 +59,15 @@ class NodeApp extends App {
57
59
  return reqBodyComplete.then(() => {
58
60
  return super.render(
59
61
  req instanceof Request ? req : createRequestFromNodeRequest(req, body),
60
- routeData
62
+ routeData,
63
+ locals
61
64
  );
62
65
  });
63
66
  }
64
67
  return super.render(
65
68
  req instanceof Request ? req : createRequestFromNodeRequest(req),
66
- routeData
69
+ routeData,
70
+ locals
67
71
  );
68
72
  }
69
73
  }
@@ -25,15 +25,14 @@ export interface RouteInfo {
25
25
  export type SerializedRouteInfo = Omit<RouteInfo, 'routeData'> & {
26
26
  routeData: SerializedRouteData;
27
27
  };
28
- type ImportComponentInstance = () => Promise<SinglePageBuiltModule>;
29
- export interface SSRManifest {
28
+ export type ImportComponentInstance = () => Promise<SinglePageBuiltModule>;
29
+ export type SSRManifest = {
30
30
  adapterName: string;
31
31
  routes: RouteInfo[];
32
32
  site?: string;
33
33
  base?: string;
34
34
  assetsPrefix?: string;
35
35
  markdown: MarkdownRenderingOptions;
36
- pageMap: Map<ComponentPath, ImportComponentInstance>;
37
36
  renderers: SSRLoadedRenderer[];
38
37
  /**
39
38
  * Map of directive name (e.g. `load`) to the directive script code
@@ -42,7 +41,9 @@ export interface SSRManifest {
42
41
  entryModules: Record<string, string>;
43
42
  assets: Set<string>;
44
43
  componentMetadata: SSRResult['componentMetadata'];
45
- }
44
+ pageModule?: SinglePageBuiltModule;
45
+ pageMap?: Map<ComponentPath, ImportComponentInstance>;
46
+ };
46
47
  export type SerializedSSRManifest = Omit<SSRManifest, 'routes' | 'assets' | 'componentMetadata' | 'clientDirectives'> & {
47
48
  routes: SerializedRouteInfo[];
48
49
  assets: string[];
@@ -50,4 +51,3 @@ export type SerializedSSRManifest = Omit<SSRManifest, 'routes' | 'assets' | 'com
50
51
  clientDirectives: [string, string][];
51
52
  };
52
53
  export type AdapterCreateExports<T = any> = (manifest: SSRManifest, args?: T) => Record<string, any>;
53
- export {};
@@ -91,8 +91,7 @@ function chunkIsPage(settings, output, internals) {
91
91
  async function generatePages(opts, internals) {
92
92
  const timer = performance.now();
93
93
  const ssr = isServerLikeOutput(opts.settings.config);
94
- const serverEntry = opts.buildConfig.serverEntry;
95
- const outFolder = ssr ? opts.buildConfig.server : getOutDirWithinCwd(opts.settings.config.outDir);
94
+ const outFolder = ssr ? opts.settings.config.build.server : getOutDirWithinCwd(opts.settings.config.outDir);
96
95
  if (ssr && !hasPrerenderedPages(internals))
97
96
  return;
98
97
  const verb = ssr ? "prerendering" : "generating";
@@ -132,7 +131,6 @@ ${bgGreen(black(` generating optimized images `))}`);
132
131
  }
133
132
  await runHookBuildGenerated({
134
133
  config: opts.settings.config,
135
- buildConfig: opts.buildConfig,
136
134
  logging: opts.logging
137
135
  });
138
136
  info(opts.logging, null, dim(`Completed in ${getTimeStat(timer, performance.now())}.
@@ -161,7 +159,7 @@ async function generatePage(opts, internals, pageData, ssrEntry, builtPaths) {
161
159
  const scripts = (pageInfo == null ? void 0 : pageInfo.hoistedScript) ?? null;
162
160
  const styles = pageData.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
163
161
  const pageModulePromise = ssrEntry.page;
164
- const middleware = ssrEntry.middleware;
162
+ const onRequest = ssrEntry.onRequest;
165
163
  if (!pageModulePromise) {
166
164
  throw new Error(
167
165
  `Unable to find the module for ${pageData.component}. This is unexpected and likely a bug in Astro, please report.`
@@ -190,7 +188,7 @@ async function generatePage(opts, internals, pageData, ssrEntry, builtPaths) {
190
188
  const paths = await getPathsForRoute(pageData, pageModule, opts, builtPaths);
191
189
  for (let i = 0; i < paths.length; i++) {
192
190
  const path = paths[i];
193
- await generatePath(path, opts, generationOptions, middleware);
191
+ await generatePath(path, opts, generationOptions, onRequest);
194
192
  const timeEnd = performance.now();
195
193
  const timeChange = getTimeStat(timeStart, timeEnd);
196
194
  const timeIncrease = `(+${timeChange})`;
@@ -312,7 +310,7 @@ function getUrlForPath(pathname, base, origin, format, routeType) {
312
310
  const url = new URL(buildPathname, origin);
313
311
  return url;
314
312
  }
315
- async function generatePath(pathname, opts, gopts, middleware) {
313
+ async function generatePath(pathname, opts, gopts, onRequest) {
316
314
  const { settings, logging, origin, routeCache } = opts;
317
315
  const {
318
316
  mod,
@@ -416,7 +414,7 @@ async function generatePath(pathname, opts, gopts, middleware) {
416
414
  env,
417
415
  renderContext,
418
416
  logging,
419
- middleware
417
+ onRequest
420
418
  );
421
419
  if (result.type === "response") {
422
420
  throwIfRedirectNotAllowed(result.response, opts.settings.config);
@@ -438,7 +436,6 @@ async function generatePath(pathname, opts, gopts, middleware) {
438
436
  site: env.site,
439
437
  adapterName: env.adapterName
440
438
  });
441
- const onRequest = middleware == null ? void 0 : middleware.onRequest;
442
439
  if (onRequest) {
443
440
  response = await callMiddleware(
444
441
  env.logging,
@@ -449,8 +446,8 @@ async function generatePath(pathname, opts, gopts, middleware) {
449
446
  mod,
450
447
  renderContext,
451
448
  env,
452
- apiContext,
453
- isCompressHTML: settings.config.compressHTML
449
+ isCompressHTML: settings.config.compressHTML,
450
+ cookies: apiContext.cookies
454
451
  });
455
452
  }
456
453
  );
@@ -459,8 +456,8 @@ async function generatePath(pathname, opts, gopts, middleware) {
459
456
  mod,
460
457
  renderContext,
461
458
  env,
462
- apiContext,
463
- isCompressHTML: settings.config.compressHTML
459
+ isCompressHTML: settings.config.compressHTML,
460
+ cookies: apiContext.cookies
464
461
  });
465
462
  }
466
463
  } catch (err) {
@@ -81,11 +81,6 @@ class AstroBuilder {
81
81
  }
82
82
  /** Run the build logic. build() is marked private because usage should go through ".run()" */
83
83
  async build({ viteConfig }) {
84
- const buildConfig = {
85
- client: this.settings.config.build.client,
86
- server: this.settings.config.build.server,
87
- serverEntry: this.settings.config.build.serverEntry
88
- };
89
84
  await runHookBuildStart({ config: this.settings.config, logging: this.logging });
90
85
  this.validateConfig();
91
86
  info(this.logging, "build", `output target: ${colors.green(this.settings.config.output)}`);
@@ -117,8 +112,7 @@ class AstroBuilder {
117
112
  pageNames,
118
113
  routeCache: this.routeCache,
119
114
  teardownCompiler: this.teardownCompiler,
120
- viteConfig,
121
- buildConfig
115
+ viteConfig
122
116
  };
123
117
  const { internals } = await viteBuild(opts);
124
118
  await staticBuild(opts, internals);
@@ -134,7 +128,6 @@ class AstroBuilder {
134
128
  debug("build", timerMessage("Additional assets copied", this.timer.assetsStart));
135
129
  await runHookBuildDone({
136
130
  config: this.settings.config,
137
- buildConfig,
138
131
  pages: pageNames,
139
132
  routes: Object.values(allPages).map((pd) => pd.route),
140
133
  logging: this.logging
@@ -1,5 +1,5 @@
1
1
  import type { Rollup } from 'vite';
2
- import type { SSRResult } from '../../@types/astro';
2
+ import type { RouteData, SSRResult } from '../../@types/astro';
3
3
  import type { PageOptions } from '../../vite-plugin-astro/types';
4
4
  import type { PageBuildData, StylesheetAsset, ViteID } from './types';
5
5
  export interface BuildInternals {
@@ -61,6 +61,8 @@ export interface BuildInternals {
61
61
  discoveredScripts: Set<string>;
62
62
  staticFiles: Set<string>;
63
63
  ssrEntryChunk?: Rollup.OutputChunk;
64
+ entryPoints: Map<RouteData, URL>;
65
+ ssrSplitEntryChunks: Map<string, Rollup.OutputChunk>;
64
66
  componentMetadata: SSRResult['componentMetadata'];
65
67
  }
66
68
  /**
@@ -1,10 +1,7 @@
1
1
  import { prependForwardSlash, removeFileExtension } from "../path.js";
2
2
  import { viteID } from "../util.js";
3
- import {
4
- ASTRO_PAGE_EXTENSION_POST_PATTERN,
5
- ASTRO_PAGE_MODULE_ID,
6
- getVirtualModulePageIdFromPath
7
- } from "./plugins/plugin-pages.js";
3
+ import { ASTRO_PAGE_MODULE_ID, getVirtualModulePageIdFromPath } from "./plugins/plugin-pages.js";
4
+ import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from "./plugins/util.js";
8
5
  function createBuildInternals() {
9
6
  const hoistedScriptIdToHoistedMap = /* @__PURE__ */ new Map();
10
7
  const hoistedScriptIdToPagesMap = /* @__PURE__ */ new Map();
@@ -22,7 +19,9 @@ function createBuildInternals() {
22
19
  discoveredClientOnlyComponents: /* @__PURE__ */ new Map(),
23
20
  discoveredScripts: /* @__PURE__ */ new Set(),
24
21
  staticFiles: /* @__PURE__ */ new Set(),
25
- componentMetadata: /* @__PURE__ */ new Map()
22
+ componentMetadata: /* @__PURE__ */ new Map(),
23
+ ssrSplitEntryChunks: /* @__PURE__ */ new Map(),
24
+ entryPoints: /* @__PURE__ */ new Map()
26
25
  };
27
26
  }
28
27
  function trackPageData(internals, component, pageData, componentModuleId, componentURL) {
@@ -10,7 +10,7 @@ import { pluginMiddleware } from "./plugin-middleware.js";
10
10
  import { pluginPages } from "./plugin-pages.js";
11
11
  import { pluginPrerender } from "./plugin-prerender.js";
12
12
  import { pluginRenderers } from "./plugin-renderers.js";
13
- import { pluginSSR } from "./plugin-ssr.js";
13
+ import { pluginSSR, pluginSSRSplit } from "./plugin-ssr.js";
14
14
  function registerAllPlugins({ internals, options, register }) {
15
15
  register(pluginComponentEntry(internals));
16
16
  register(pluginAliasResolve(internals));
@@ -25,6 +25,7 @@ function registerAllPlugins({ internals, options, register }) {
25
25
  register(astroConfigBuildPlugin(options, internals));
26
26
  register(pluginHoistedScripts(options, internals));
27
27
  register(pluginSSR(options, internals));
28
+ register(pluginSSRSplit(options, internals));
28
29
  }
29
30
  export {
30
31
  registerAllPlugins
@@ -1,8 +1,13 @@
1
1
  import { MIDDLEWARE_PATH_SEGMENT_NAME } from "../../constants.js";
2
+ import { addRollupInput } from "../add-rollup-input.js";
2
3
  const MIDDLEWARE_MODULE_ID = "@astro-middleware";
4
+ const EMPTY_MIDDLEWARE = "\0empty-middleware";
3
5
  function vitePluginMiddleware(opts, _internals) {
4
6
  return {
5
7
  name: "@astro/plugin-middleware",
8
+ options(options) {
9
+ return addRollupInput(options, [MIDDLEWARE_MODULE_ID]);
10
+ },
6
11
  async resolveId(id) {
7
12
  if (id === MIDDLEWARE_MODULE_ID) {
8
13
  const middlewareId = await this.resolve(
@@ -10,8 +15,18 @@ function vitePluginMiddleware(opts, _internals) {
10
15
  );
11
16
  if (middlewareId) {
12
17
  return middlewareId.id;
18
+ } else {
19
+ return EMPTY_MIDDLEWARE;
13
20
  }
14
21
  }
22
+ if (id === EMPTY_MIDDLEWARE) {
23
+ return EMPTY_MIDDLEWARE;
24
+ }
25
+ },
26
+ load(id) {
27
+ if (id === EMPTY_MIDDLEWARE) {
28
+ return "export const onRequest = undefined";
29
+ }
15
30
  }
16
31
  };
17
32
  }
@@ -2,8 +2,7 @@ import { type BuildInternals } from '../internal.js';
2
2
  import type { AstroBuildPlugin } from '../plugin';
3
3
  import type { StaticBuildOptions } from '../types';
4
4
  export declare const ASTRO_PAGE_MODULE_ID = "@astro-page:";
5
- export declare const ASTRO_PAGE_RESOLVED_MODULE_ID = "\0@astro-page:";
6
- export declare const ASTRO_PAGE_EXTENSION_POST_PATTERN = "@_@";
5
+ export declare const ASTRO_PAGE_RESOLVED_MODULE_ID: string;
7
6
  /**
8
7
  * 1. We add a fixed prefix, which is used as virtual module naming convention;
9
8
  * 2. We replace the dot that belongs extension with an arbitrary string.