astro 2.6.6 → 2.7.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 (57) hide show
  1. package/dist/@types/astro.d.ts +30 -1
  2. package/dist/content/utils.d.ts +1 -2
  3. package/dist/content/utils.js +3 -4
  4. package/dist/content/vite-plugin-content-virtual-mod.d.ts +1 -1
  5. package/dist/core/add/babel.d.ts +8 -2
  6. package/dist/core/app/index.d.ts +3 -4
  7. package/dist/core/app/index.js +21 -14
  8. package/dist/core/app/node.d.ts +1 -1
  9. package/dist/core/app/node.js +9 -5
  10. package/dist/core/app/types.d.ts +5 -5
  11. package/dist/core/build/generate.js +8 -9
  12. package/dist/core/build/internal.d.ts +3 -1
  13. package/dist/core/build/internal.js +5 -6
  14. package/dist/core/build/plugins/index.js +2 -1
  15. package/dist/core/build/plugins/plugin-middleware.js +15 -0
  16. package/dist/core/build/plugins/plugin-pages.d.ts +1 -2
  17. package/dist/core/build/plugins/plugin-pages.js +6 -9
  18. package/dist/core/build/plugins/plugin-ssr.d.ts +13 -2
  19. package/dist/core/build/plugins/plugin-ssr.js +220 -73
  20. package/dist/core/build/plugins/util.d.ts +15 -0
  21. package/dist/core/build/plugins/util.js +17 -1
  22. package/dist/core/build/static-build.d.ts +33 -0
  23. package/dist/core/build/static-build.js +50 -19
  24. package/dist/core/build/types.d.ts +5 -2
  25. package/dist/core/config/schema.d.ts +12 -0
  26. package/dist/core/config/schema.js +6 -3
  27. package/dist/core/config/settings.js +1 -1
  28. package/dist/core/constants.js +1 -1
  29. package/dist/core/dev/dev.js +1 -1
  30. package/dist/core/endpoint/dev/index.js +1 -1
  31. package/dist/core/endpoint/index.d.ts +2 -2
  32. package/dist/core/endpoint/index.js +3 -3
  33. package/dist/core/errors/errors-data.d.ts +30 -0
  34. package/dist/core/errors/errors-data.js +11 -1
  35. package/dist/core/errors/errors.d.ts +2 -1
  36. package/dist/core/errors/utils.d.ts +3 -1
  37. package/dist/core/messages.js +2 -2
  38. package/dist/core/redirects/component.js +1 -4
  39. package/dist/core/render/context.d.ts +1 -0
  40. package/dist/core/render/context.js +17 -1
  41. package/dist/core/render/core.d.ts +3 -3
  42. package/dist/core/render/core.js +3 -4
  43. package/dist/core/render/dev/index.js +18 -8
  44. package/dist/core/request.d.ts +2 -1
  45. package/dist/core/request.js +3 -2
  46. package/dist/core/routing/manifest/create.js +2 -2
  47. package/dist/integrations/index.d.ts +3 -2
  48. package/dist/integrations/index.js +6 -7
  49. package/dist/jsx/babel.js +3 -3
  50. package/dist/vite-plugin-astro-server/route.js +4 -1
  51. package/dist/vite-plugin-markdown/content-entry-type.d.ts +0 -5
  52. package/dist/vite-plugin-markdown/content-entry-type.js +1 -26
  53. package/package.json +38 -37
  54. package/dist/content/template/types.d.js +0 -0
  55. package/dist/content/template/virtual-mod.d.mts +0 -7
  56. /package/{src/content/template/virtual-mod.mjs → content-module.template.mjs} +0 -0
  57. /package/{src/content/template/types.d.ts → content-types.template.d.ts} +0 -0
@@ -773,6 +773,29 @@ export interface AstroUserConfig {
773
773
  * ```
774
774
  */
775
775
  inlineStylesheets?: 'always' | 'auto' | 'never';
776
+ /**
777
+ * @docs
778
+ * @name build.split
779
+ * @type {boolean}
780
+ * @default {false}
781
+ * @version 2.7.0
782
+ * @description
783
+ * Defines how the SSR code should be bundled when built.
784
+ *
785
+ * When `split` is `true`, Astro will emit a file for each page.
786
+ * Each file emitted will render only one page. The pages will be emitted
787
+ * inside a `dist/pages/` directory, and the emitted files will keep the same file paths
788
+ * of the `src/pages` directory.
789
+ *
790
+ * ```js
791
+ * {
792
+ * build: {
793
+ * split: true
794
+ * }
795
+ * }
796
+ * ```
797
+ */
798
+ split?: boolean;
776
799
  };
777
800
  /**
778
801
  * @docs
@@ -793,7 +816,7 @@ export interface AstroUserConfig {
793
816
  * ```js
794
817
  * {
795
818
  * // Example: Use the function syntax to customize based on command
796
- * server: (command) => ({ port: command === 'dev' ? 3000 : 4000 })
819
+ * server: ({ command }) => ({ port: command === 'dev' ? 3000 : 4000 })
797
820
  * }
798
821
  * ```
799
822
  */
@@ -1173,6 +1196,7 @@ export type InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' |
1173
1196
  export interface InjectedRoute {
1174
1197
  pattern: string;
1175
1198
  entryPoint: string;
1199
+ prerender?: boolean;
1176
1200
  }
1177
1201
  export interface AstroConfig extends z.output<typeof AstroConfigSchema> {
1178
1202
  integrations: AstroIntegration[];
@@ -1649,6 +1673,11 @@ export interface AstroIntegration {
1649
1673
  'astro:server:done'?: () => void | Promise<void>;
1650
1674
  'astro:build:ssr'?: (options: {
1651
1675
  manifest: SerializedSSRManifest;
1676
+ /**
1677
+ * This maps a {@link RouteData} to an {@link URL}, this URL represents
1678
+ * the physical file you should import.
1679
+ */
1680
+ entryPoints: Map<RouteData, URL>;
1652
1681
  }) => void | Promise<void>;
1653
1682
  'astro:build:start'?: () => void | Promise<void>;
1654
1683
  'astro:build:setup'?: (options: {
@@ -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
  }
@@ -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>;
@@ -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 {};
@@ -161,7 +161,7 @@ async function generatePage(opts, internals, pageData, ssrEntry, builtPaths) {
161
161
  const scripts = (pageInfo == null ? void 0 : pageInfo.hoistedScript) ?? null;
162
162
  const styles = pageData.styles.sort(cssOrder).map(({ sheet }) => sheet).reduce(mergeInlineCss, []);
163
163
  const pageModulePromise = ssrEntry.page;
164
- const middleware = ssrEntry.middleware;
164
+ const onRequest = ssrEntry.onRequest;
165
165
  if (!pageModulePromise) {
166
166
  throw new Error(
167
167
  `Unable to find the module for ${pageData.component}. This is unexpected and likely a bug in Astro, please report.`
@@ -190,7 +190,7 @@ async function generatePage(opts, internals, pageData, ssrEntry, builtPaths) {
190
190
  const paths = await getPathsForRoute(pageData, pageModule, opts, builtPaths);
191
191
  for (let i = 0; i < paths.length; i++) {
192
192
  const path = paths[i];
193
- await generatePath(path, opts, generationOptions, middleware);
193
+ await generatePath(path, opts, generationOptions, onRequest);
194
194
  const timeEnd = performance.now();
195
195
  const timeChange = getTimeStat(timeStart, timeEnd);
196
196
  const timeIncrease = `(+${timeChange})`;
@@ -312,7 +312,7 @@ function getUrlForPath(pathname, base, origin, format, routeType) {
312
312
  const url = new URL(buildPathname, origin);
313
313
  return url;
314
314
  }
315
- async function generatePath(pathname, opts, gopts, middleware) {
315
+ async function generatePath(pathname, opts, gopts, onRequest) {
316
316
  const { settings, logging, origin, routeCache } = opts;
317
317
  const {
318
318
  mod,
@@ -416,7 +416,7 @@ async function generatePath(pathname, opts, gopts, middleware) {
416
416
  env,
417
417
  renderContext,
418
418
  logging,
419
- middleware
419
+ onRequest
420
420
  );
421
421
  if (result.type === "response") {
422
422
  throwIfRedirectNotAllowed(result.response, opts.settings.config);
@@ -438,7 +438,6 @@ async function generatePath(pathname, opts, gopts, middleware) {
438
438
  site: env.site,
439
439
  adapterName: env.adapterName
440
440
  });
441
- const onRequest = middleware == null ? void 0 : middleware.onRequest;
442
441
  if (onRequest) {
443
442
  response = await callMiddleware(
444
443
  env.logging,
@@ -449,8 +448,8 @@ async function generatePath(pathname, opts, gopts, middleware) {
449
448
  mod,
450
449
  renderContext,
451
450
  env,
452
- apiContext,
453
- isCompressHTML: settings.config.compressHTML
451
+ isCompressHTML: settings.config.compressHTML,
452
+ cookies: apiContext.cookies
454
453
  });
455
454
  }
456
455
  );
@@ -459,8 +458,8 @@ async function generatePath(pathname, opts, gopts, middleware) {
459
458
  mod,
460
459
  renderContext,
461
460
  env,
462
- apiContext,
463
- isCompressHTML: settings.config.compressHTML
461
+ isCompressHTML: settings.config.compressHTML,
462
+ cookies: apiContext.cookies
464
463
  });
465
464
  }
466
465
  } catch (err) {
@@ -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.
@@ -3,9 +3,9 @@ import { routeIsRedirect } from "../../redirects/index.js";
3
3
  import { addRollupInput } from "../add-rollup-input.js";
4
4
  import { MIDDLEWARE_MODULE_ID } from "./plugin-middleware.js";
5
5
  import { RENDERERS_MODULE_ID } from "./plugin-renderers.js";
6
+ import { ASTRO_PAGE_EXTENSION_POST_PATTERN, getPathFromVirtualModulePageName } from "./util.js";
6
7
  const ASTRO_PAGE_MODULE_ID = "@astro-page:";
7
- const ASTRO_PAGE_RESOLVED_MODULE_ID = "\0@astro-page:";
8
- const ASTRO_PAGE_EXTENSION_POST_PATTERN = "@_@";
8
+ const ASTRO_PAGE_RESOLVED_MODULE_ID = "\0" + ASTRO_PAGE_MODULE_ID;
9
9
  function getVirtualModulePageNameFromPath(path) {
10
10
  const extension = extname(path);
11
11
  return `${ASTRO_PAGE_MODULE_ID}${path.replace(
@@ -41,10 +41,8 @@ function vitePluginPages(opts, internals) {
41
41
  if (id.startsWith(ASTRO_PAGE_RESOLVED_MODULE_ID)) {
42
42
  const imports = [];
43
43
  const exports = [];
44
- const pageName = id.slice(ASTRO_PAGE_RESOLVED_MODULE_ID.length);
45
- const pageData = internals.pagesByComponent.get(
46
- `${pageName.replace(ASTRO_PAGE_EXTENSION_POST_PATTERN, ".")}`
47
- );
44
+ const pageName = getPathFromVirtualModulePageName(ASTRO_PAGE_RESOLVED_MODULE_ID, id);
45
+ const pageData = internals.pagesByComponent.get(pageName);
48
46
  if (pageData) {
49
47
  const resolvedPage = await this.resolve(pageData.moduleSpecifier);
50
48
  if (resolvedPage) {
@@ -54,8 +52,8 @@ function vitePluginPages(opts, internals) {
54
52
  exports.push(`export { renderers };`);
55
53
  const middlewareModule = await this.resolve(MIDDLEWARE_MODULE_ID);
56
54
  if (middlewareModule) {
57
- imports.push(`import * as middleware from "${middlewareModule.id}";`);
58
- exports.push(`export { middleware };`);
55
+ imports.push(`import { onRequest } from "${middlewareModule.id}";`);
56
+ exports.push(`export { onRequest };`);
59
57
  }
60
58
  return `${imports.join("\n")}${exports.join("\n")}`;
61
59
  }
@@ -77,7 +75,6 @@ function pluginPages(opts, internals) {
77
75
  };
78
76
  }
79
77
  export {
80
- ASTRO_PAGE_EXTENSION_POST_PATTERN,
81
78
  ASTRO_PAGE_MODULE_ID,
82
79
  ASTRO_PAGE_RESOLVED_MODULE_ID,
83
80
  getVirtualModulePageIdFromPath,
@@ -1,6 +1,17 @@
1
+ import type { SerializedSSRManifest } from '../../app/types';
1
2
  import { type BuildInternals } from '../internal.js';
2
3
  import type { AstroBuildPlugin } from '../plugin';
3
- import type { StaticBuildOptions } from '../types';
4
+ import type { OutputChunk, StaticBuildOptions } from '../types';
4
5
  export declare const SSR_VIRTUAL_MODULE_ID = "@astrojs-ssr-virtual-entry";
5
- export declare function injectManifest(buildOpts: StaticBuildOptions, internals: BuildInternals): Promise<string>;
6
6
  export declare function pluginSSR(options: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin;
7
+ export declare const SPLIT_MODULE_ID = "@astro-page-split:";
8
+ export declare const RESOLVED_SPLIT_MODULE_ID = "\0@astro-page-split:";
9
+ export declare function pluginSSRSplit(options: StaticBuildOptions, internals: BuildInternals): AstroBuildPlugin;
10
+ /**
11
+ * It injects the manifest in the given output rollup chunk. It returns the new emitted code
12
+ * @param buildOpts
13
+ * @param internals
14
+ * @param chunk
15
+ */
16
+ export declare function injectManifest(manifest: SerializedSSRManifest, chunk: Readonly<OutputChunk>): string;
17
+ export declare function createManifest(buildOpts: StaticBuildOptions, internals: BuildInternals): Promise<SerializedSSRManifest>;