astro 5.10.2 → 5.11.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.
- package/dist/content/content-layer.js +3 -3
- package/dist/core/app/index.d.ts +9 -1
- package/dist/core/app/index.js +15 -2
- package/dist/core/app/node.d.ts +4 -2
- package/dist/core/app/node.js +6 -2
- package/dist/core/app/pipeline.js +1 -1
- package/dist/core/app/types.d.ts +7 -0
- package/dist/core/build/generate.js +20 -9
- package/dist/core/build/pipeline.js +1 -1
- package/dist/core/build/plugins/plugin-manifest.js +5 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/messages.js +2 -2
- package/dist/core/render-context.js +2 -1
- package/dist/core/routing/rewrite.d.ts +1 -1
- package/dist/integrations/hooks.d.ts +2 -2
- package/dist/runtime/server/render/server-islands.d.ts +7 -0
- package/dist/runtime/server/render/server-islands.js +64 -26
- package/dist/types/public/index.d.ts +1 -1
- package/dist/types/public/integrations.d.ts +6 -1
- package/package.json +3 -3
|
@@ -164,7 +164,7 @@ ${contentConfig.error.message}`);
|
|
|
164
164
|
logger.info("Content config changed");
|
|
165
165
|
shouldClear = true;
|
|
166
166
|
}
|
|
167
|
-
if (previousAstroVersion && previousAstroVersion !== "5.
|
|
167
|
+
if (previousAstroVersion && previousAstroVersion !== "5.11.0") {
|
|
168
168
|
logger.info("Astro version changed");
|
|
169
169
|
shouldClear = true;
|
|
170
170
|
}
|
|
@@ -172,8 +172,8 @@ ${contentConfig.error.message}`);
|
|
|
172
172
|
logger.info("Clearing content store");
|
|
173
173
|
this.#store.clearAll();
|
|
174
174
|
}
|
|
175
|
-
if ("5.
|
|
176
|
-
await this.#store.metaStore().set("astro-version", "5.
|
|
175
|
+
if ("5.11.0") {
|
|
176
|
+
await this.#store.metaStore().set("astro-version", "5.11.0");
|
|
177
177
|
}
|
|
178
178
|
if (currentConfigDigest) {
|
|
179
179
|
await this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
package/dist/core/app/index.d.ts
CHANGED
|
@@ -67,7 +67,15 @@ export declare class App {
|
|
|
67
67
|
getAdapterLogger(): AstroIntegrationLogger;
|
|
68
68
|
set setManifestData(newManifestData: RoutesList);
|
|
69
69
|
removeBase(pathname: string): string;
|
|
70
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Given a `Request`, it returns the `RouteData` that matches its `pathname`. By default, prerendered
|
|
72
|
+
* routes aren't returned, even if they are matched.
|
|
73
|
+
*
|
|
74
|
+
* When `allowPrerenderedRoutes` is `true`, the function returns matched prerendered routes too.
|
|
75
|
+
* @param request
|
|
76
|
+
* @param allowPrerenderedRoutes
|
|
77
|
+
*/
|
|
78
|
+
match(request: Request, allowPrerenderedRoutes?: boolean): RouteData | undefined;
|
|
71
79
|
render(request: Request, renderOptions?: RenderOptions): Promise<Response>;
|
|
72
80
|
setCookieHeaders(response: Response): Generator<string, string[], any>;
|
|
73
81
|
/**
|
package/dist/core/app/index.js
CHANGED
|
@@ -107,7 +107,15 @@ class App {
|
|
|
107
107
|
return pathname;
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Given a `Request`, it returns the `RouteData` that matches its `pathname`. By default, prerendered
|
|
112
|
+
* routes aren't returned, even if they are matched.
|
|
113
|
+
*
|
|
114
|
+
* When `allowPrerenderedRoutes` is `true`, the function returns matched prerendered routes too.
|
|
115
|
+
* @param request
|
|
116
|
+
* @param allowPrerenderedRoutes
|
|
117
|
+
*/
|
|
118
|
+
match(request, allowPrerenderedRoutes = false) {
|
|
111
119
|
const url = new URL(request.url);
|
|
112
120
|
if (this.#manifest.assets.has(url.pathname)) return void 0;
|
|
113
121
|
let pathname = this.#computePathnameFromDomain(request);
|
|
@@ -115,7 +123,12 @@ class App {
|
|
|
115
123
|
pathname = prependForwardSlash(this.removeBase(url.pathname));
|
|
116
124
|
}
|
|
117
125
|
let routeData = matchRoute(decodeURI(pathname), this.#manifestData);
|
|
118
|
-
if (!routeData
|
|
126
|
+
if (!routeData) return void 0;
|
|
127
|
+
if (allowPrerenderedRoutes) {
|
|
128
|
+
return routeData;
|
|
129
|
+
} else if (routeData.prerender) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
119
132
|
return routeData;
|
|
120
133
|
}
|
|
121
134
|
#computePathnameFromDomain(request) {
|
package/dist/core/app/node.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
|
2
2
|
import type { RouteData } from '../../types/public/internal.js';
|
|
3
3
|
import type { RenderOptions } from './index.js';
|
|
4
4
|
import { App } from './index.js';
|
|
5
|
-
import type { SSRManifest } from './types.js';
|
|
5
|
+
import type { NodeAppHeadersJson, SSRManifest } from './types.js';
|
|
6
6
|
export { apply as applyPolyfills } from '../polyfill.js';
|
|
7
7
|
/**
|
|
8
8
|
* Allow the request body to be explicitly overridden. For example, this
|
|
@@ -12,7 +12,9 @@ interface NodeRequest extends IncomingMessage {
|
|
|
12
12
|
body?: unknown;
|
|
13
13
|
}
|
|
14
14
|
export declare class NodeApp extends App {
|
|
15
|
-
|
|
15
|
+
headersMap: NodeAppHeadersJson | undefined;
|
|
16
|
+
setHeadersMap(headers: NodeAppHeadersJson): void;
|
|
17
|
+
match(req: NodeRequest | Request, allowPrerenderedRoutes?: boolean): RouteData | undefined;
|
|
16
18
|
render(request: NodeRequest | Request, options?: RenderOptions): Promise<Response>;
|
|
17
19
|
/**
|
|
18
20
|
* @deprecated Instead of passing `RouteData` and locals individually, pass an object with `routeData` and `locals` properties.
|
package/dist/core/app/node.js
CHANGED
|
@@ -6,13 +6,17 @@ import { createOutgoingHttpHeaders } from "./createOutgoingHttpHeaders.js";
|
|
|
6
6
|
import { App } from "./index.js";
|
|
7
7
|
import { apply } from "../polyfill.js";
|
|
8
8
|
class NodeApp extends App {
|
|
9
|
-
|
|
9
|
+
headersMap = void 0;
|
|
10
|
+
setHeadersMap(headers) {
|
|
11
|
+
this.headersMap = headers;
|
|
12
|
+
}
|
|
13
|
+
match(req, allowPrerenderedRoutes = false) {
|
|
10
14
|
if (!(req instanceof Request)) {
|
|
11
15
|
req = NodeApp.createRequest(req, {
|
|
12
16
|
skipBody: true
|
|
13
17
|
});
|
|
14
18
|
}
|
|
15
|
-
return super.match(req);
|
|
19
|
+
return super.match(req, allowPrerenderedRoutes);
|
|
16
20
|
}
|
|
17
21
|
render(req, routeDataOrOptions, maybeLocals) {
|
|
18
22
|
if (!(req instanceof Request)) {
|
|
@@ -66,7 +66,7 @@ class AppPipeline extends Pipeline {
|
|
|
66
66
|
trailingSlash: this.manifest.trailingSlash,
|
|
67
67
|
buildFormat: this.manifest.buildFormat,
|
|
68
68
|
base: this.manifest.base,
|
|
69
|
-
outDir: this.manifest.outDir
|
|
69
|
+
outDir: this.serverLike ? this.manifest.buildClientDir : this.manifest.outDir
|
|
70
70
|
});
|
|
71
71
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
72
72
|
return { newUrl, pathname, componentInstance, routeData };
|
package/dist/core/app/types.d.ts
CHANGED
|
@@ -110,4 +110,11 @@ export type SerializedSSRManifest = Omit<SSRManifest, 'middleware' | 'routes' |
|
|
|
110
110
|
serverIslandNameMap: [string, string][];
|
|
111
111
|
key: string;
|
|
112
112
|
};
|
|
113
|
+
export type NodeAppHeadersJson = {
|
|
114
|
+
pathname: string;
|
|
115
|
+
headers: {
|
|
116
|
+
key: string;
|
|
117
|
+
value: string;
|
|
118
|
+
}[];
|
|
119
|
+
}[];
|
|
113
120
|
export {};
|
|
@@ -146,7 +146,7 @@ async function generatePage(pageData, ssrEntry, builtPaths, pipeline, routeToHea
|
|
|
146
146
|
styles,
|
|
147
147
|
mod: pageModule
|
|
148
148
|
};
|
|
149
|
-
async function generatePathWithLogs(path, route, index, paths, isConcurrent) {
|
|
149
|
+
async function generatePathWithLogs(path, route, integrationRoute, index, paths, isConcurrent) {
|
|
150
150
|
const timeStart = performance.now();
|
|
151
151
|
pipeline.logger.debug("build", `Generating: ${path}`);
|
|
152
152
|
const filePath = getOutputFilename(config, path, pageData.route);
|
|
@@ -154,7 +154,14 @@ async function generatePage(pageData, ssrEntry, builtPaths, pipeline, routeToHea
|
|
|
154
154
|
if (!isConcurrent) {
|
|
155
155
|
logger.info(null, ` ${blue(lineIcon)} ${dim(filePath)}`, false);
|
|
156
156
|
}
|
|
157
|
-
const created = await generatePath(
|
|
157
|
+
const created = await generatePath(
|
|
158
|
+
path,
|
|
159
|
+
pipeline,
|
|
160
|
+
generationOptions,
|
|
161
|
+
route,
|
|
162
|
+
integrationRoute,
|
|
163
|
+
routeToHeaders
|
|
164
|
+
);
|
|
158
165
|
const timeEnd = performance.now();
|
|
159
166
|
const isSlow = timeEnd - timeStart > THRESHOLD_SLOW_RENDER_TIME_MS;
|
|
160
167
|
const timeIncrease = (isSlow ? red : dim)(`(+${getTimeStat(timeStart, timeEnd)})`);
|
|
@@ -166,6 +173,7 @@ async function generatePage(pageData, ssrEntry, builtPaths, pipeline, routeToHea
|
|
|
166
173
|
}
|
|
167
174
|
}
|
|
168
175
|
for (const route of eachRouteInRouteData(pageData)) {
|
|
176
|
+
const integrationRoute = toIntegrationResolvedRoute(route);
|
|
169
177
|
const icon = route.type === "page" || route.type === "redirect" || route.type === "fallback" ? green("\u25B6") : magenta("\u03BB");
|
|
170
178
|
logger.info(null, `${icon} ${getPrettyRouteName(route)}`);
|
|
171
179
|
const paths = await getPathsForRoute(route, pageModule, pipeline, builtPaths);
|
|
@@ -174,13 +182,15 @@ async function generatePage(pageData, ssrEntry, builtPaths, pipeline, routeToHea
|
|
|
174
182
|
const promises = [];
|
|
175
183
|
for (let i = 0; i < paths.length; i++) {
|
|
176
184
|
const path = paths[i];
|
|
177
|
-
promises.push(
|
|
185
|
+
promises.push(
|
|
186
|
+
limit(() => generatePathWithLogs(path, route, integrationRoute, i, paths, true))
|
|
187
|
+
);
|
|
178
188
|
}
|
|
179
189
|
await Promise.all(promises);
|
|
180
190
|
} else {
|
|
181
191
|
for (let i = 0; i < paths.length; i++) {
|
|
182
192
|
const path = paths[i];
|
|
183
|
-
await generatePathWithLogs(path, route, i, paths, false);
|
|
193
|
+
await generatePathWithLogs(path, route, integrationRoute, i, paths, false);
|
|
184
194
|
}
|
|
185
195
|
}
|
|
186
196
|
}
|
|
@@ -291,7 +301,7 @@ function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType)
|
|
|
291
301
|
}
|
|
292
302
|
return new URL(buildPathname, origin);
|
|
293
303
|
}
|
|
294
|
-
async function generatePath(pathname, pipeline, gopts, route, routeToHeaders) {
|
|
304
|
+
async function generatePath(pathname, pipeline, gopts, route, integrationRoute, routeToHeaders) {
|
|
295
305
|
const { mod } = gopts;
|
|
296
306
|
const { config, logger, options } = pipeline;
|
|
297
307
|
logger.debug("build", `Generating: ${pathname}`);
|
|
@@ -345,14 +355,12 @@ async function generatePath(pathname, pipeline, gopts, route, routeToHeaders) {
|
|
|
345
355
|
}
|
|
346
356
|
throw err;
|
|
347
357
|
}
|
|
348
|
-
|
|
349
|
-
routeToHeaders.set(toIntegrationResolvedRoute(route), response.headers);
|
|
350
|
-
}
|
|
358
|
+
const responseHeaders = response.headers;
|
|
351
359
|
if (response.status >= 300 && response.status < 400) {
|
|
352
360
|
if (routeIsRedirect(route) && !config.build.redirects) {
|
|
353
361
|
return void 0;
|
|
354
362
|
}
|
|
355
|
-
const locationSite = getRedirectLocationOrThrow(
|
|
363
|
+
const locationSite = getRedirectLocationOrThrow(responseHeaders);
|
|
356
364
|
const siteURL = config.site;
|
|
357
365
|
const location = siteURL ? new URL(locationSite, siteURL) : locationSite;
|
|
358
366
|
const fromPath = new URL(request.url).pathname;
|
|
@@ -380,6 +388,9 @@ async function generatePath(pathname, pipeline, gopts, route, routeToHeaders) {
|
|
|
380
388
|
} else {
|
|
381
389
|
route.distURL = [outFile];
|
|
382
390
|
}
|
|
391
|
+
if (pipeline.settings.adapter?.adapterFeatures?.experimentalStaticHeaders && pipeline.settings.config.experimental?.csp) {
|
|
392
|
+
routeToHeaders.set(pathname, { headers: responseHeaders, route: integrationRoute });
|
|
393
|
+
}
|
|
383
394
|
await fs.promises.mkdir(outFolder, { recursive: true });
|
|
384
395
|
await fs.promises.writeFile(outFile, body);
|
|
385
396
|
return true;
|
|
@@ -202,7 +202,7 @@ class BuildPipeline extends Pipeline {
|
|
|
202
202
|
trailingSlash: this.config.trailingSlash,
|
|
203
203
|
buildFormat: this.config.build.format,
|
|
204
204
|
base: this.config.base,
|
|
205
|
-
outDir: this.manifest.outDir
|
|
205
|
+
outDir: this.serverLike ? this.manifest.buildClientDir : this.manifest.outDir
|
|
206
206
|
});
|
|
207
207
|
const componentInstance = await this.getComponentByRoute(routeData);
|
|
208
208
|
return { routeData, componentInstance, newUrl, pathname };
|
|
@@ -189,9 +189,13 @@ async function buildManifest(opts, internals, staticFiles, encodedKey) {
|
|
|
189
189
|
});
|
|
190
190
|
staticFiles.push(file);
|
|
191
191
|
}
|
|
192
|
+
const needsStaticHeaders = settings.adapter?.adapterFeatures?.experimentalStaticHeaders ?? false;
|
|
192
193
|
for (const route of opts.routesList.routes) {
|
|
193
194
|
const pageData = internals.pagesByKeys.get(makePageDataKey(route.route, route.component));
|
|
194
|
-
if (
|
|
195
|
+
if (!pageData) continue;
|
|
196
|
+
if (route.prerender && !needsStaticHeaders) {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
195
199
|
const scripts = [];
|
|
196
200
|
if (settings.scripts.some((script) => script.stage === "page")) {
|
|
197
201
|
const src = entryModules[PAGE_SCRIPT_ID];
|
package/dist/core/constants.js
CHANGED
package/dist/core/dev/dev.js
CHANGED
|
@@ -22,7 +22,7 @@ async function dev(inlineConfig) {
|
|
|
22
22
|
await telemetry.record([]);
|
|
23
23
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
24
24
|
const logger = restart.container.logger;
|
|
25
|
-
const currentVersion = "5.
|
|
25
|
+
const currentVersion = "5.11.0";
|
|
26
26
|
const isPrerelease = currentVersion.includes("-");
|
|
27
27
|
if (!isPrerelease) {
|
|
28
28
|
try {
|
package/dist/core/messages.js
CHANGED
|
@@ -37,7 +37,7 @@ function serverStart({
|
|
|
37
37
|
host,
|
|
38
38
|
base
|
|
39
39
|
}) {
|
|
40
|
-
const version = "5.
|
|
40
|
+
const version = "5.11.0";
|
|
41
41
|
const localPrefix = `${dim("\u2503")} Local `;
|
|
42
42
|
const networkPrefix = `${dim("\u2503")} Network `;
|
|
43
43
|
const emptyPrefix = " ".repeat(11);
|
|
@@ -274,7 +274,7 @@ function printHelp({
|
|
|
274
274
|
message.push(
|
|
275
275
|
linebreak(),
|
|
276
276
|
` ${bgGreen(black(` ${commandName} `))} ${green(
|
|
277
|
-
`v${"5.
|
|
277
|
+
`v${"5.11.0"}`
|
|
278
278
|
)} ${headline}`
|
|
279
279
|
);
|
|
280
280
|
}
|
|
@@ -253,7 +253,8 @@ class RenderContext {
|
|
|
253
253
|
reroutePayload,
|
|
254
254
|
this.request
|
|
255
255
|
);
|
|
256
|
-
|
|
256
|
+
const isI18nFallback = routeData.fallbackRoutes && routeData.fallbackRoutes.length > 0;
|
|
257
|
+
if (this.pipeline.serverLike && !this.routeData.prerender && routeData.prerender && !isI18nFallback) {
|
|
257
258
|
throw new AstroError({
|
|
258
259
|
...ForbiddenRewrite,
|
|
259
260
|
message: ForbiddenRewrite.message(this.pathname, pathname, routeData.component),
|
|
@@ -9,7 +9,7 @@ type FindRouteToRewrite = {
|
|
|
9
9
|
trailingSlash: AstroConfig['trailingSlash'];
|
|
10
10
|
buildFormat: AstroConfig['build']['format'];
|
|
11
11
|
base: AstroConfig['base'];
|
|
12
|
-
outDir:
|
|
12
|
+
outDir: URL | string;
|
|
13
13
|
};
|
|
14
14
|
interface FindRouteToRewriteResult {
|
|
15
15
|
routeData: RouteData;
|
|
@@ -6,7 +6,7 @@ import type { PageBuildData } from '../core/build/types.js';
|
|
|
6
6
|
import type { Logger } from '../core/logger/core.js';
|
|
7
7
|
import type { AstroSettings } from '../types/astro.js';
|
|
8
8
|
import type { AstroConfig } from '../types/public/config.js';
|
|
9
|
-
import type { IntegrationResolvedRoute, RouteOptions } from '../types/public/integrations.js';
|
|
9
|
+
import type { IntegrationResolvedRoute, RouteOptions, RouteToHeaders } from '../types/public/integrations.js';
|
|
10
10
|
import type { RouteData } from '../types/public/internal.js';
|
|
11
11
|
export declare function getToolbarServerCommunicationHelpers(server: ViteDevServer): {
|
|
12
12
|
/**
|
|
@@ -87,7 +87,7 @@ export declare function runHookBuildSsr({ config, manifest, logger, entryPoints,
|
|
|
87
87
|
export declare function runHookBuildGenerated({ settings, logger, experimentalRouteToHeaders, }: {
|
|
88
88
|
settings: AstroSettings;
|
|
89
89
|
logger: Logger;
|
|
90
|
-
experimentalRouteToHeaders:
|
|
90
|
+
experimentalRouteToHeaders: RouteToHeaders;
|
|
91
91
|
}): Promise<void>;
|
|
92
92
|
type RunHookBuildDone = {
|
|
93
93
|
settings: AstroSettings;
|
|
@@ -10,8 +10,15 @@ export declare class ServerIslandComponent {
|
|
|
10
10
|
displayName: string;
|
|
11
11
|
hostId: string | undefined;
|
|
12
12
|
islandContent: string | undefined;
|
|
13
|
+
componentPath: string | undefined;
|
|
14
|
+
componentExport: string | undefined;
|
|
15
|
+
componentId: string | undefined;
|
|
13
16
|
constructor(result: SSRResult, props: Record<string | number, any>, slots: ComponentSlots, displayName: string);
|
|
14
17
|
init(): Promise<ThinHead>;
|
|
15
18
|
render(destination: RenderDestination): Promise<void>;
|
|
19
|
+
getComponentPath(): string;
|
|
20
|
+
getComponentExport(): string;
|
|
21
|
+
getHostId(): Promise<string>;
|
|
22
|
+
getIslandContent(): Promise<string>;
|
|
16
23
|
}
|
|
17
24
|
export declare const renderServerIslandRuntime: () => string;
|
|
@@ -39,6 +39,9 @@ class ServerIslandComponent {
|
|
|
39
39
|
displayName;
|
|
40
40
|
hostId;
|
|
41
41
|
islandContent;
|
|
42
|
+
componentPath;
|
|
43
|
+
componentExport;
|
|
44
|
+
componentId;
|
|
42
45
|
constructor(result, props, slots, displayName) {
|
|
43
46
|
this.result = result;
|
|
44
47
|
this.props = props;
|
|
@@ -46,8 +49,64 @@ class ServerIslandComponent {
|
|
|
46
49
|
this.displayName = displayName;
|
|
47
50
|
}
|
|
48
51
|
async init() {
|
|
52
|
+
const content = await this.getIslandContent();
|
|
53
|
+
if (this.result.cspDestination) {
|
|
54
|
+
this.result._metadata.extraScriptHashes.push(
|
|
55
|
+
await generateCspDigest(SERVER_ISLAND_REPLACER, this.result.cspAlgorithm)
|
|
56
|
+
);
|
|
57
|
+
const contentDigest = await generateCspDigest(content, this.result.cspAlgorithm);
|
|
58
|
+
this.result._metadata.extraScriptHashes.push(contentDigest);
|
|
59
|
+
}
|
|
60
|
+
return createThinHead();
|
|
61
|
+
}
|
|
62
|
+
async render(destination) {
|
|
63
|
+
const hostId = await this.getHostId();
|
|
64
|
+
const islandContent = await this.getIslandContent();
|
|
65
|
+
destination.write(createRenderInstruction({ type: "server-island-runtime" }));
|
|
66
|
+
destination.write("<!--[if astro]>server-island-start<![endif]-->");
|
|
67
|
+
for (const name in this.slots) {
|
|
68
|
+
if (name === "fallback") {
|
|
69
|
+
await renderChild(destination, this.slots.fallback(this.result));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
destination.write(
|
|
73
|
+
`<script type="module" data-astro-rerun data-island-id="${hostId}">${islandContent}</script>`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
getComponentPath() {
|
|
77
|
+
if (this.componentPath) {
|
|
78
|
+
return this.componentPath;
|
|
79
|
+
}
|
|
49
80
|
const componentPath = this.props["server:component-path"];
|
|
81
|
+
if (!componentPath) {
|
|
82
|
+
throw new Error(`Could not find server component path`);
|
|
83
|
+
}
|
|
84
|
+
this.componentPath = componentPath;
|
|
85
|
+
return componentPath;
|
|
86
|
+
}
|
|
87
|
+
getComponentExport() {
|
|
88
|
+
if (this.componentExport) {
|
|
89
|
+
return this.componentExport;
|
|
90
|
+
}
|
|
50
91
|
const componentExport = this.props["server:component-export"];
|
|
92
|
+
if (!componentExport) {
|
|
93
|
+
throw new Error(`Could not find server component export`);
|
|
94
|
+
}
|
|
95
|
+
this.componentExport = componentExport;
|
|
96
|
+
return componentExport;
|
|
97
|
+
}
|
|
98
|
+
async getHostId() {
|
|
99
|
+
if (!this.hostId) {
|
|
100
|
+
this.hostId = await crypto.randomUUID();
|
|
101
|
+
}
|
|
102
|
+
return this.hostId;
|
|
103
|
+
}
|
|
104
|
+
async getIslandContent() {
|
|
105
|
+
if (this.islandContent) {
|
|
106
|
+
return this.islandContent;
|
|
107
|
+
}
|
|
108
|
+
const componentPath = this.getComponentPath();
|
|
109
|
+
const componentExport = this.getComponentExport();
|
|
51
110
|
const componentId = this.result.serverIslandNameMap.get(componentPath);
|
|
52
111
|
if (!componentId) {
|
|
53
112
|
throw new Error(`Could not find server component name`);
|
|
@@ -60,13 +119,13 @@ class ServerIslandComponent {
|
|
|
60
119
|
const renderedSlots = {};
|
|
61
120
|
for (const name in this.slots) {
|
|
62
121
|
if (name !== "fallback") {
|
|
63
|
-
const
|
|
64
|
-
renderedSlots[name] =
|
|
122
|
+
const content = await renderSlotToString(this.result, this.slots[name]);
|
|
123
|
+
renderedSlots[name] = content.toString();
|
|
65
124
|
}
|
|
66
125
|
}
|
|
67
126
|
const key = await this.result.key;
|
|
68
127
|
const propsEncrypted = Object.keys(this.props).length === 0 ? "" : await encryptString(key, JSON.stringify(this.props));
|
|
69
|
-
const hostId =
|
|
128
|
+
const hostId = await this.getHostId();
|
|
70
129
|
const slash = this.result.base.endsWith("/") ? "" : "/";
|
|
71
130
|
let serverIslandUrl = `${this.result.base}${slash}_server-islands/${componentId}${this.result.trailingSlash === "always" ? "/" : ""}`;
|
|
72
131
|
const potentialSearchParams = createSearchParams(
|
|
@@ -98,29 +157,8 @@ let response = await fetch('${serverIslandUrl}', {
|
|
|
98
157
|
body: JSON.stringify(data),
|
|
99
158
|
});`
|
|
100
159
|
);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.result._metadata.extraScriptHashes.push(
|
|
104
|
-
await generateCspDigest(SERVER_ISLAND_REPLACER, this.result.cspAlgorithm)
|
|
105
|
-
);
|
|
106
|
-
const contentDigest = await generateCspDigest(content, this.result.cspAlgorithm);
|
|
107
|
-
this.result._metadata.extraScriptHashes.push(contentDigest);
|
|
108
|
-
}
|
|
109
|
-
this.islandContent = content;
|
|
110
|
-
this.hostId = hostId;
|
|
111
|
-
return createThinHead();
|
|
112
|
-
}
|
|
113
|
-
async render(destination) {
|
|
114
|
-
destination.write(createRenderInstruction({ type: "server-island-runtime" }));
|
|
115
|
-
destination.write("<!--[if astro]>server-island-start<![endif]-->");
|
|
116
|
-
for (const name in this.slots) {
|
|
117
|
-
if (name === "fallback") {
|
|
118
|
-
await renderChild(destination, this.slots.fallback(this.result));
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
destination.write(
|
|
122
|
-
`<script type="module" data-astro-rerun data-island-id="${this.hostId}">${this.islandContent}</script>`
|
|
123
|
-
);
|
|
160
|
+
this.islandContent = `${method}replaceServerIsland('${hostId}', response);`;
|
|
161
|
+
return this.islandContent;
|
|
124
162
|
}
|
|
125
163
|
}
|
|
126
164
|
const renderServerIslandRuntime = () => {
|
|
@@ -3,7 +3,7 @@ export type { MarkdownHeading, RehypePlugins, RemarkPlugins, ShikiConfig, } from
|
|
|
3
3
|
export type { ExternalImageService, ImageService, LocalImageService, } from '../../assets/services/service.js';
|
|
4
4
|
export type { GetImageResult, ImageInputFormat, ImageMetadata, ImageOutputFormat, ImageQuality, ImageQualityPreset, ImageTransform, UnresolvedImageTransform, } from '../../assets/types.js';
|
|
5
5
|
export type { ContainerRenderer } from '../../container/index.js';
|
|
6
|
-
export type { AssetsPrefix, SSRManifest } from '../../core/app/types.js';
|
|
6
|
+
export type { AssetsPrefix, NodeAppHeadersJson, SSRManifest } from '../../core/app/types.js';
|
|
7
7
|
export type { AstroCookieGetOptions, AstroCookieSetOptions, AstroCookies, } from '../../core/cookies/index.js';
|
|
8
8
|
export type { AstroIntegrationLogger } from '../../core/logger/core.js';
|
|
9
9
|
export { AstroSession } from '../../core/session.js';
|
|
@@ -204,7 +204,7 @@ export interface BaseIntegrationHooks {
|
|
|
204
204
|
'astro:build:generated': (options: {
|
|
205
205
|
dir: URL;
|
|
206
206
|
logger: AstroIntegrationLogger;
|
|
207
|
-
experimentalRouteToHeaders:
|
|
207
|
+
experimentalRouteToHeaders: RouteToHeaders;
|
|
208
208
|
}) => void | Promise<void>;
|
|
209
209
|
'astro:build:done': (options: {
|
|
210
210
|
pages: {
|
|
@@ -243,6 +243,11 @@ export type IntegrationRouteData = Omit<RouteData, 'isIndex' | 'fallbackRoutes'
|
|
|
243
243
|
*/
|
|
244
244
|
redirectRoute?: IntegrationRouteData;
|
|
245
245
|
};
|
|
246
|
+
export type RouteToHeaders = Map<string, HeaderPayload>;
|
|
247
|
+
export type HeaderPayload = {
|
|
248
|
+
headers: Headers;
|
|
249
|
+
route: IntegrationResolvedRoute;
|
|
250
|
+
};
|
|
246
251
|
export interface IntegrationResolvedRoute extends Pick<RouteData, 'generate' | 'params' | 'pathname' | 'segments' | 'type' | 'redirect' | 'origin'> {
|
|
247
252
|
/**
|
|
248
253
|
* {@link RouteData.route}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.11.0",
|
|
4
4
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "withastro",
|
|
@@ -158,8 +158,8 @@
|
|
|
158
158
|
"zod-to-json-schema": "^3.24.5",
|
|
159
159
|
"zod-to-ts": "^1.2.0",
|
|
160
160
|
"@astrojs/internal-helpers": "0.6.1",
|
|
161
|
-
"@astrojs/
|
|
162
|
-
"@astrojs/
|
|
161
|
+
"@astrojs/markdown-remark": "6.3.2",
|
|
162
|
+
"@astrojs/telemetry": "3.3.0"
|
|
163
163
|
},
|
|
164
164
|
"optionalDependencies": {
|
|
165
165
|
"sharp": "^0.33.3"
|