astro 6.0.6 → 6.0.7
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/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/content-layer.js +7 -4
- package/dist/core/app/entrypoints/node.d.ts +1 -1
- package/dist/core/app/entrypoints/node.js +9 -1
- package/dist/core/app/middlewares.d.ts +1 -0
- package/dist/core/app/middlewares.js +2 -1
- package/dist/core/app/node.d.ts +17 -0
- package/dist/core/app/node.js +1 -0
- package/dist/core/constants.js +1 -1
- package/dist/core/create-vite.js +4 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/render-context.js +7 -0
- package/dist/core/routing/match.js +8 -0
- package/dist/core/routing/rewrite.js +13 -0
- package/dist/core/server-islands/shared-state.d.ts +44 -0
- package/dist/core/server-islands/shared-state.js +96 -0
- package/dist/core/server-islands/vite-plugin-server-islands.d.ts +4 -1
- package/dist/core/server-islands/vite-plugin-server-islands.js +34 -60
- package/dist/i18n/middleware.js +14 -7
- package/dist/i18n/utils.d.ts +6 -0
- package/dist/i18n/utils.js +22 -0
- package/dist/manifest/serialized.js +11 -3
- package/dist/vite-plugin-astro-server/plugin.js +2 -2
- package/dist/vite-plugin-css/index.js +20 -0
- package/dist/vite-plugin-renderers/index.d.ts +2 -0
- package/dist/vite-plugin-renderers/index.js +1 -1
- package/package.json +1 -1
|
@@ -117,7 +117,10 @@ class ContentLayer {
|
|
|
117
117
|
});
|
|
118
118
|
return {
|
|
119
119
|
html: code,
|
|
120
|
-
metadata
|
|
120
|
+
metadata: {
|
|
121
|
+
...metadata,
|
|
122
|
+
imagePaths: (metadata.localImagePaths ?? []).concat(metadata.remoteImagePaths ?? [])
|
|
123
|
+
}
|
|
121
124
|
};
|
|
122
125
|
}
|
|
123
126
|
/**
|
|
@@ -189,7 +192,7 @@ ${contentConfig.error.message}`
|
|
|
189
192
|
logger.info("Content config changed");
|
|
190
193
|
shouldClear = true;
|
|
191
194
|
}
|
|
192
|
-
if (previousAstroVersion && previousAstroVersion !== "6.0.
|
|
195
|
+
if (previousAstroVersion && previousAstroVersion !== "6.0.7") {
|
|
193
196
|
logger.info("Astro version changed");
|
|
194
197
|
shouldClear = true;
|
|
195
198
|
}
|
|
@@ -197,8 +200,8 @@ ${contentConfig.error.message}`
|
|
|
197
200
|
logger.info("Clearing content store");
|
|
198
201
|
this.#store.clearAll();
|
|
199
202
|
}
|
|
200
|
-
if ("6.0.
|
|
201
|
-
this.#store.metaStore().set("astro-version", "6.0.
|
|
203
|
+
if ("6.0.7") {
|
|
204
|
+
this.#store.metaStore().set("astro-version", "6.0.7");
|
|
202
205
|
}
|
|
203
206
|
if (currentConfigDigest) {
|
|
204
207
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { NodeApp, loadApp, loadManifest, createRequest, writeResponse } from '../node.js';
|
|
1
|
+
export { NodeApp, loadApp, loadManifest, createRequest, writeResponse, getAbortControllerCleanup, } from '../node.js';
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
NodeApp,
|
|
3
|
+
loadApp,
|
|
4
|
+
loadManifest,
|
|
5
|
+
createRequest,
|
|
6
|
+
writeResponse,
|
|
7
|
+
getAbortControllerCleanup
|
|
8
|
+
} from "../node.js";
|
|
2
9
|
export {
|
|
3
10
|
NodeApp,
|
|
4
11
|
createRequest,
|
|
12
|
+
getAbortControllerCleanup,
|
|
5
13
|
loadApp,
|
|
6
14
|
loadManifest,
|
|
7
15
|
writeResponse
|
package/dist/core/app/node.d.ts
CHANGED
|
@@ -90,6 +90,23 @@ export declare class NodeApp extends App {
|
|
|
90
90
|
*/
|
|
91
91
|
static writeResponse: typeof writeResponse;
|
|
92
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Returns the cleanup function for the AbortController and socket listeners created by `createRequest()`
|
|
95
|
+
* for the NodeJS IncomingMessage. This should only be called directly if the request is not
|
|
96
|
+
* being handled by Astro, i.e. if not calling `writeResponse()` after `createRequest()`.
|
|
97
|
+
* ```js
|
|
98
|
+
* import { createRequest, getAbortControllerCleanup } from 'astro/app/node';
|
|
99
|
+
* import { createServer } from 'node:http';
|
|
100
|
+
*
|
|
101
|
+
* const server = createServer(async (req, res) => {
|
|
102
|
+
* const request = createRequest(req);
|
|
103
|
+
* const cleanup = getAbortControllerCleanup(req);
|
|
104
|
+
* if (cleanup) cleanup();
|
|
105
|
+
* // can now safely call another handler
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export declare function getAbortControllerCleanup(req?: NodeRequest): (() => void) | undefined;
|
|
93
110
|
/** @deprecated This will be removed in a future major version. */
|
|
94
111
|
export declare function loadManifest(rootFolder: URL): Promise<SSRManifest>;
|
|
95
112
|
/** @deprecated This will be removed in a future major version. */
|
package/dist/core/app/node.js
CHANGED
package/dist/core/constants.js
CHANGED
package/dist/core/create-vite.js
CHANGED
|
@@ -43,6 +43,7 @@ import astroScriptsPageSSRPlugin from "../vite-plugin-scripts/page-ssr.js";
|
|
|
43
43
|
import { createViteLogger } from "./logger/vite.js";
|
|
44
44
|
import { vitePluginMiddleware } from "./middleware/vite-plugin.js";
|
|
45
45
|
import { joinPaths } from "./path.js";
|
|
46
|
+
import { ServerIslandsState } from "./server-islands/shared-state.js";
|
|
46
47
|
import { vitePluginServerIslands } from "./server-islands/vite-plugin-server-islands.js";
|
|
47
48
|
import { vitePluginCacheProvider } from "./cache/vite-plugin.js";
|
|
48
49
|
import { vitePluginSessionDriver } from "./session/vite-plugin.js";
|
|
@@ -80,6 +81,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
|
|
|
80
81
|
mode,
|
|
81
82
|
config: settings.config
|
|
82
83
|
});
|
|
84
|
+
const serverIslandsState = new ServerIslandsState();
|
|
83
85
|
validateEnvPrefixAgainstSchema(settings.config);
|
|
84
86
|
const commonConfig = {
|
|
85
87
|
// Tell Vite not to combine config from vite.config.js with our provided inline config
|
|
@@ -96,6 +98,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
|
|
|
96
98
|
vitePluginRenderers({
|
|
97
99
|
settings,
|
|
98
100
|
routesList,
|
|
101
|
+
serverIslandsState,
|
|
99
102
|
command: command === "dev" ? "serve" : "build"
|
|
100
103
|
}),
|
|
101
104
|
vitePluginStaticPaths(),
|
|
@@ -133,7 +136,7 @@ async function createVite(commandConfig, { settings, logger, mode, command, fs =
|
|
|
133
136
|
vitePluginFileURL(),
|
|
134
137
|
astroInternationalization({ settings }),
|
|
135
138
|
vitePluginActions({ fs, settings }),
|
|
136
|
-
vitePluginServerIslands({ settings, logger }),
|
|
139
|
+
vitePluginServerIslands({ settings, logger, serverIslandsState }),
|
|
137
140
|
vitePluginSessionDriver({ settings }),
|
|
138
141
|
vitePluginCacheProvider({ settings }),
|
|
139
142
|
astroContainer(),
|
package/dist/core/dev/dev.js
CHANGED
|
@@ -26,7 +26,7 @@ async function dev(inlineConfig) {
|
|
|
26
26
|
await telemetry.record([]);
|
|
27
27
|
const restart = await createContainerWithAutomaticRestart({ inlineConfig, fs });
|
|
28
28
|
const logger = restart.container.logger;
|
|
29
|
-
const currentVersion = "6.0.
|
|
29
|
+
const currentVersion = "6.0.7";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -4,6 +4,7 @@ import { getActionContext } from "../actions/runtime/server.js";
|
|
|
4
4
|
import { createCallAction, createGetActionResult, hasActionPayload } from "../actions/utils.js";
|
|
5
5
|
import {
|
|
6
6
|
computeCurrentLocale,
|
|
7
|
+
computeCurrentLocaleFromParams,
|
|
7
8
|
computePreferredLocale,
|
|
8
9
|
computePreferredLocaleList
|
|
9
10
|
} from "../i18n/utils.js";
|
|
@@ -737,6 +738,12 @@ class RenderContext {
|
|
|
737
738
|
}
|
|
738
739
|
pathname = pathname && !isRoute404or500(routeData) ? pathname : url.pathname;
|
|
739
740
|
computedLocale = computeCurrentLocale(pathname, locales, defaultLocale);
|
|
741
|
+
if (routeData.params.length > 0) {
|
|
742
|
+
const localeFromParams = computeCurrentLocaleFromParams(this.params, locales);
|
|
743
|
+
if (localeFromParams) {
|
|
744
|
+
computedLocale = localeFromParams;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
740
747
|
}
|
|
741
748
|
this.#currentLocale = computedLocale ?? fallbackTo;
|
|
742
749
|
return this.#currentLocale;
|
|
@@ -2,6 +2,14 @@ import { redirectIsExternal } from "../redirects/render.js";
|
|
|
2
2
|
import { SERVER_ISLAND_COMPONENT } from "../server-islands/endpoint.js";
|
|
3
3
|
import { isRoute404, isRoute500 } from "./internal/route-errors.js";
|
|
4
4
|
function matchRoute(pathname, manifest) {
|
|
5
|
+
if (isRoute404(pathname)) {
|
|
6
|
+
const errorRoute = manifest.routes.find((route) => isRoute404(route.route));
|
|
7
|
+
if (errorRoute) return errorRoute;
|
|
8
|
+
}
|
|
9
|
+
if (isRoute500(pathname)) {
|
|
10
|
+
const errorRoute = manifest.routes.find((route) => isRoute500(route.route));
|
|
11
|
+
if (errorRoute) return errorRoute;
|
|
12
|
+
}
|
|
5
13
|
return manifest.routes.find((route) => {
|
|
6
14
|
return route.pattern.test(pathname) || route.fallbackRoutes.some((fallbackRoute) => fallbackRoute.pattern.test(pathname));
|
|
7
15
|
});
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "../path.js";
|
|
11
11
|
import { createRequest } from "../request.js";
|
|
12
12
|
import { DEFAULT_404_ROUTE } from "./internal/astro-designed-error-pages.js";
|
|
13
|
+
import { isRoute404, isRoute500 } from "./internal/route-errors.js";
|
|
13
14
|
function findRouteToRewrite({
|
|
14
15
|
payload,
|
|
15
16
|
routes,
|
|
@@ -53,6 +54,18 @@ function findRouteToRewrite({
|
|
|
53
54
|
newUrl.pathname = joinPaths(...[base, pathname].filter(Boolean));
|
|
54
55
|
}
|
|
55
56
|
const decodedPathname = decodeURI(pathname);
|
|
57
|
+
if (isRoute404(decodedPathname)) {
|
|
58
|
+
const errorRoute = routes.find((route) => route.route === "/404");
|
|
59
|
+
if (errorRoute) {
|
|
60
|
+
return { routeData: errorRoute, newUrl, pathname: decodedPathname };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (isRoute500(decodedPathname)) {
|
|
64
|
+
const errorRoute = routes.find((route) => route.route === "/500");
|
|
65
|
+
if (errorRoute) {
|
|
66
|
+
return { routeData: errorRoute, newUrl, pathname: decodedPathname };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
56
69
|
let foundRoute;
|
|
57
70
|
for (const route of routes) {
|
|
58
71
|
if (route.pattern.test(decodedPathname)) {
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
type ServerIslandDiscovery = {
|
|
2
|
+
resolvedPath: string;
|
|
3
|
+
localName: string;
|
|
4
|
+
specifier: string;
|
|
5
|
+
importer: string;
|
|
6
|
+
};
|
|
7
|
+
type ServerIslandRecord = Omit<ServerIslandDiscovery, 'resolvedPath'> & {
|
|
8
|
+
islandName: string;
|
|
9
|
+
};
|
|
10
|
+
export declare class ServerIslandsState {
|
|
11
|
+
private islandsByResolvedPath;
|
|
12
|
+
private resolvedPathByIslandName;
|
|
13
|
+
private referenceIdByResolvedPath;
|
|
14
|
+
hasIslands(): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Record a discovered server island.
|
|
17
|
+
*
|
|
18
|
+
* Dedupe is based on `resolvedPath`: if the same resolved path is discovered
|
|
19
|
+
* again from a different importer/specifier, the first record is preserved.
|
|
20
|
+
* This keeps island names stable across repeated scans.
|
|
21
|
+
*/
|
|
22
|
+
discover(island: ServerIslandDiscovery): ServerIslandRecord;
|
|
23
|
+
getDiscoveredIslands(): Iterable<ServerIslandRecord>;
|
|
24
|
+
hasReferenceId(resolvedPath: string): boolean;
|
|
25
|
+
setReferenceId(resolvedPath: string, referenceId: string): void;
|
|
26
|
+
getDiscoveredIslandEntries(): Iterable<[string, ServerIslandRecord]>;
|
|
27
|
+
/**
|
|
28
|
+
* Build import-map source from discovered islands.
|
|
29
|
+
*
|
|
30
|
+
* Used by non-SSR build output and dev replacement paths where we can import
|
|
31
|
+
* directly from discovered component paths.
|
|
32
|
+
*/
|
|
33
|
+
createImportMapSourceFromDiscovered(toImportPath: (fileName: string) => string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Build import-map source from Rollup reference ids.
|
|
36
|
+
*
|
|
37
|
+
* Used by SSR build output: reference ids are resolved to final emitted chunk
|
|
38
|
+
* file names before generating import() mappings.
|
|
39
|
+
*/
|
|
40
|
+
createImportMapSourceFromReferences(resolveFileName: (referenceId: string) => string, toImportPath: (fileName: string) => string): string;
|
|
41
|
+
createNameMapSource(): string;
|
|
42
|
+
private createImportMapSource;
|
|
43
|
+
}
|
|
44
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
class ServerIslandsState {
|
|
2
|
+
// Canonical source of discovered islands keyed by resolved component path.
|
|
3
|
+
islandsByResolvedPath = /* @__PURE__ */ new Map();
|
|
4
|
+
// Reverse lookup used to keep island names unique and stable.
|
|
5
|
+
resolvedPathByIslandName = /* @__PURE__ */ new Map();
|
|
6
|
+
// Rollup reference ids emitted for SSR chunks, keyed by resolved path.
|
|
7
|
+
referenceIdByResolvedPath = /* @__PURE__ */ new Map();
|
|
8
|
+
hasIslands() {
|
|
9
|
+
return this.islandsByResolvedPath.size > 0;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Record a discovered server island.
|
|
13
|
+
*
|
|
14
|
+
* Dedupe is based on `resolvedPath`: if the same resolved path is discovered
|
|
15
|
+
* again from a different importer/specifier, the first record is preserved.
|
|
16
|
+
* This keeps island names stable across repeated scans.
|
|
17
|
+
*/
|
|
18
|
+
discover(island) {
|
|
19
|
+
const { resolvedPath, ...discovery } = island;
|
|
20
|
+
const existing = this.islandsByResolvedPath.get(resolvedPath);
|
|
21
|
+
if (existing) {
|
|
22
|
+
return existing;
|
|
23
|
+
}
|
|
24
|
+
let name = island.localName;
|
|
25
|
+
let idx = 1;
|
|
26
|
+
while (this.resolvedPathByIslandName.has(name)) {
|
|
27
|
+
name += idx++;
|
|
28
|
+
}
|
|
29
|
+
const record = {
|
|
30
|
+
...discovery,
|
|
31
|
+
islandName: name
|
|
32
|
+
};
|
|
33
|
+
this.islandsByResolvedPath.set(resolvedPath, record);
|
|
34
|
+
this.resolvedPathByIslandName.set(name, resolvedPath);
|
|
35
|
+
return record;
|
|
36
|
+
}
|
|
37
|
+
getDiscoveredIslands() {
|
|
38
|
+
return this.islandsByResolvedPath.values();
|
|
39
|
+
}
|
|
40
|
+
hasReferenceId(resolvedPath) {
|
|
41
|
+
return this.referenceIdByResolvedPath.has(resolvedPath);
|
|
42
|
+
}
|
|
43
|
+
setReferenceId(resolvedPath, referenceId) {
|
|
44
|
+
this.referenceIdByResolvedPath.set(resolvedPath, referenceId);
|
|
45
|
+
}
|
|
46
|
+
getDiscoveredIslandEntries() {
|
|
47
|
+
return this.islandsByResolvedPath.entries();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build import-map source from discovered islands.
|
|
51
|
+
*
|
|
52
|
+
* Used by non-SSR build output and dev replacement paths where we can import
|
|
53
|
+
* directly from discovered component paths.
|
|
54
|
+
*/
|
|
55
|
+
createImportMapSourceFromDiscovered(toImportPath) {
|
|
56
|
+
const entries = Array.from(
|
|
57
|
+
this.islandsByResolvedPath,
|
|
58
|
+
([resolvedPath, island]) => [island.islandName, resolvedPath]
|
|
59
|
+
);
|
|
60
|
+
return this.createImportMapSource(entries, toImportPath);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build import-map source from Rollup reference ids.
|
|
64
|
+
*
|
|
65
|
+
* Used by SSR build output: reference ids are resolved to final emitted chunk
|
|
66
|
+
* file names before generating import() mappings.
|
|
67
|
+
*/
|
|
68
|
+
createImportMapSourceFromReferences(resolveFileName, toImportPath) {
|
|
69
|
+
const entries = [];
|
|
70
|
+
for (const [resolvedPath, referenceId] of this.referenceIdByResolvedPath) {
|
|
71
|
+
const island = this.islandsByResolvedPath.get(resolvedPath);
|
|
72
|
+
if (!island) continue;
|
|
73
|
+
entries.push([island.islandName, resolveFileName(referenceId)]);
|
|
74
|
+
}
|
|
75
|
+
return this.createImportMapSource(entries, toImportPath);
|
|
76
|
+
}
|
|
77
|
+
createNameMapSource() {
|
|
78
|
+
const entries = Array.from(
|
|
79
|
+
this.islandsByResolvedPath,
|
|
80
|
+
([resolvedPath, island]) => [resolvedPath, island.islandName]
|
|
81
|
+
);
|
|
82
|
+
return `new Map(${JSON.stringify(entries, null, 2)})`;
|
|
83
|
+
}
|
|
84
|
+
createImportMapSource(entries, toImportPath) {
|
|
85
|
+
const mappings = Array.from(entries, ([islandName, fileName]) => {
|
|
86
|
+
const importPath = toImportPath(fileName);
|
|
87
|
+
return ` [${JSON.stringify(islandName)}, () => import(${JSON.stringify(importPath)})],`;
|
|
88
|
+
});
|
|
89
|
+
return `new Map([
|
|
90
|
+
${mappings.join("\n")}
|
|
91
|
+
])`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export {
|
|
95
|
+
ServerIslandsState
|
|
96
|
+
};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Plugin as VitePlugin } from 'vite';
|
|
2
2
|
import type { AstroPluginOptions } from '../../types/astro.js';
|
|
3
|
+
import type { ServerIslandsState } from './shared-state.js';
|
|
3
4
|
export declare const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest";
|
|
4
5
|
export declare const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$";
|
|
5
|
-
export declare function vitePluginServerIslands({ settings }: AstroPluginOptions
|
|
6
|
+
export declare function vitePluginServerIslands({ settings, serverIslandsState, }: AstroPluginOptions & {
|
|
7
|
+
serverIslandsState: ServerIslandsState;
|
|
8
|
+
}): VitePlugin;
|
|
@@ -7,36 +7,22 @@ const serverIslandPlaceholderNameMap = "'$$server-islands-name-map$$'";
|
|
|
7
7
|
const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$";
|
|
8
8
|
const serverIslandMapReplaceExp = /['"]\$\$server-islands-map\$\$['"]/g;
|
|
9
9
|
const serverIslandNameMapReplaceExp = /['"]\$\$server-islands-name-map\$\$['"]/g;
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
});
|
|
15
|
-
return `new Map([
|
|
16
|
-
${mappings.join("\n")}
|
|
17
|
-
])`;
|
|
18
|
-
}
|
|
19
|
-
function createNameMapSource(entries) {
|
|
20
|
-
return `new Map(${JSON.stringify(Array.from(entries), null, 2)})`;
|
|
21
|
-
}
|
|
22
|
-
function vitePluginServerIslands({ settings }) {
|
|
10
|
+
function vitePluginServerIslands({
|
|
11
|
+
settings,
|
|
12
|
+
serverIslandsState
|
|
13
|
+
}) {
|
|
23
14
|
let command = "serve";
|
|
24
15
|
let ssrEnvironment = null;
|
|
25
|
-
const serverIslandMap = /* @__PURE__ */ new Map();
|
|
26
|
-
const serverIslandNameMap = /* @__PURE__ */ new Map();
|
|
27
|
-
const serverIslandSourceMap = /* @__PURE__ */ new Map();
|
|
28
|
-
const referenceIdMap = /* @__PURE__ */ new Map();
|
|
29
16
|
function ensureServerIslandReferenceIds(ctx) {
|
|
30
|
-
for (const [resolvedPath,
|
|
31
|
-
if (
|
|
32
|
-
const source = serverIslandSourceMap.get(resolvedPath);
|
|
17
|
+
for (const [resolvedPath, island] of serverIslandsState.getDiscoveredIslandEntries()) {
|
|
18
|
+
if (serverIslandsState.hasReferenceId(resolvedPath)) continue;
|
|
33
19
|
const referenceId = ctx.emitFile({
|
|
34
20
|
type: "chunk",
|
|
35
|
-
id:
|
|
36
|
-
importer:
|
|
37
|
-
name: islandName
|
|
21
|
+
id: island.specifier,
|
|
22
|
+
importer: island.importer,
|
|
23
|
+
name: island.islandName
|
|
38
24
|
});
|
|
39
|
-
|
|
25
|
+
serverIslandsState.setReferenceId(resolvedPath, referenceId);
|
|
40
26
|
}
|
|
41
27
|
}
|
|
42
28
|
return {
|
|
@@ -86,33 +72,27 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
86
72
|
const isBuildSsr = command === "build" && this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
|
|
87
73
|
if (astro) {
|
|
88
74
|
for (const comp of astro.serverComponents) {
|
|
89
|
-
if (!
|
|
90
|
-
|
|
91
|
-
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
|
92
|
-
}
|
|
93
|
-
let name = comp.localName;
|
|
94
|
-
let idx = 1;
|
|
95
|
-
while (serverIslandMap.has(name)) {
|
|
96
|
-
name += idx++;
|
|
97
|
-
}
|
|
98
|
-
serverIslandNameMap.set(comp.resolvedPath, name);
|
|
99
|
-
serverIslandMap.set(name, comp.resolvedPath);
|
|
100
|
-
serverIslandSourceMap.set(comp.resolvedPath, { id: comp.specifier, importer: id });
|
|
75
|
+
if (!settings.adapter) {
|
|
76
|
+
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
|
101
77
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
78
|
+
const island = serverIslandsState.discover({
|
|
79
|
+
resolvedPath: comp.resolvedPath,
|
|
80
|
+
localName: comp.localName,
|
|
81
|
+
specifier: comp.specifier ?? comp.resolvedPath,
|
|
82
|
+
importer: id
|
|
83
|
+
});
|
|
84
|
+
if (isBuildSsr && !serverIslandsState.hasReferenceId(comp.resolvedPath)) {
|
|
105
85
|
const referenceId = this.emitFile({
|
|
106
86
|
type: "chunk",
|
|
107
|
-
id:
|
|
108
|
-
importer:
|
|
109
|
-
name: islandName
|
|
87
|
+
id: island.specifier,
|
|
88
|
+
importer: island.importer,
|
|
89
|
+
name: island.islandName
|
|
110
90
|
});
|
|
111
|
-
|
|
91
|
+
serverIslandsState.setReferenceId(comp.resolvedPath, referenceId);
|
|
112
92
|
}
|
|
113
93
|
}
|
|
114
94
|
}
|
|
115
|
-
if (
|
|
95
|
+
if (serverIslandsState.hasIslands() && ssrEnvironment) {
|
|
116
96
|
const mod = ssrEnvironment.moduleGraph.getModuleById(RESOLVED_SERVER_ISLAND_MANIFEST);
|
|
117
97
|
if (mod) {
|
|
118
98
|
ssrEnvironment.moduleGraph.invalidateModule(mod);
|
|
@@ -120,17 +100,16 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
120
100
|
}
|
|
121
101
|
if (id === RESOLVED_SERVER_ISLAND_MANIFEST) {
|
|
122
102
|
if (command === "build" && settings.buildOutput) {
|
|
123
|
-
const hasServerIslands =
|
|
103
|
+
const hasServerIslands = serverIslandsState.hasIslands();
|
|
124
104
|
if (hasServerIslands && settings.buildOutput !== "server") {
|
|
125
105
|
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
|
126
106
|
}
|
|
127
107
|
}
|
|
128
|
-
if (command !== "build" &&
|
|
129
|
-
const mapSource =
|
|
130
|
-
serverIslandMap,
|
|
108
|
+
if (command !== "build" && serverIslandsState.hasIslands()) {
|
|
109
|
+
const mapSource = serverIslandsState.createImportMapSourceFromDiscovered(
|
|
131
110
|
(fileName) => fileName
|
|
132
111
|
);
|
|
133
|
-
const nameMapSource = createNameMapSource(
|
|
112
|
+
const nameMapSource = serverIslandsState.createNameMapSource();
|
|
134
113
|
return {
|
|
135
114
|
code: `
|
|
136
115
|
export const serverIslandMap = ${mapSource};
|
|
@@ -150,21 +129,16 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
150
129
|
if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr) {
|
|
151
130
|
const isRelativeChunk = !chunk.isEntry;
|
|
152
131
|
const dots = isRelativeChunk ? ".." : ".";
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const fileName = this.getFileName(referenceId);
|
|
156
|
-
const islandName = serverIslandNameMap.get(resolvedPath);
|
|
157
|
-
if (!islandName) continue;
|
|
158
|
-
mapEntries.push([islandName, fileName]);
|
|
159
|
-
}
|
|
160
|
-
mapSource = createServerIslandImportMapSource(
|
|
161
|
-
mapEntries,
|
|
132
|
+
mapSource = serverIslandsState.createImportMapSourceFromReferences(
|
|
133
|
+
(referenceId) => this.getFileName(referenceId),
|
|
162
134
|
(fileName) => `${dots}/${fileName}`
|
|
163
135
|
);
|
|
164
136
|
} else {
|
|
165
|
-
mapSource =
|
|
137
|
+
mapSource = serverIslandsState.createImportMapSourceFromDiscovered(
|
|
138
|
+
(fileName) => fileName
|
|
139
|
+
);
|
|
166
140
|
}
|
|
167
|
-
const nameMapSource = createNameMapSource(
|
|
141
|
+
const nameMapSource = serverIslandsState.createNameMapSource();
|
|
168
142
|
return {
|
|
169
143
|
code: code.replace(serverIslandMapReplaceExp, mapSource).replace(serverIslandNameMapReplaceExp, nameMapSource),
|
|
170
144
|
map: null
|
package/dist/i18n/middleware.js
CHANGED
|
@@ -48,15 +48,22 @@ function createI18nMiddleware(i18n, base, trailingSlash, format) {
|
|
|
48
48
|
return context.redirect(location, routeDecision.status);
|
|
49
49
|
}
|
|
50
50
|
case "notFound": {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
if (context.isPrerendered) {
|
|
52
|
+
const prerenderedRes = new Response(response.body, {
|
|
53
|
+
status: 404,
|
|
54
|
+
headers: response.headers
|
|
55
|
+
});
|
|
56
|
+
prerenderedRes.headers.set(REROUTE_DIRECTIVE_HEADER, "no");
|
|
57
|
+
if (routeDecision.location) {
|
|
58
|
+
prerenderedRes.headers.set("Location", routeDecision.location);
|
|
59
|
+
}
|
|
60
|
+
return prerenderedRes;
|
|
61
|
+
}
|
|
62
|
+
const headers = new Headers();
|
|
56
63
|
if (routeDecision.location) {
|
|
57
|
-
|
|
64
|
+
headers.set("Location", routeDecision.location);
|
|
58
65
|
}
|
|
59
|
-
return
|
|
66
|
+
return new Response(null, { status: 404, headers });
|
|
60
67
|
}
|
|
61
68
|
case "continue":
|
|
62
69
|
break;
|
package/dist/i18n/utils.d.ts
CHANGED
|
@@ -21,4 +21,10 @@ export declare function parseLocale(header: string): BrowserLocale[];
|
|
|
21
21
|
export declare function computePreferredLocale(request: Request, locales: Locales): string | undefined;
|
|
22
22
|
export declare function computePreferredLocaleList(request: Request, locales: Locales): string[];
|
|
23
23
|
export declare function computeCurrentLocale(pathname: string, locales: Locales, defaultLocale: string): string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Check if any of the route's resolved param values match a configured locale.
|
|
26
|
+
* This handles dynamic routes like `[locale]` or `[...path]` where the locale
|
|
27
|
+
* isn't in a static segment of the route pathname.
|
|
28
|
+
*/
|
|
29
|
+
export declare function computeCurrentLocaleFromParams(params: Record<string, string | undefined>, locales: Locales): string | undefined;
|
|
24
30
|
export {};
|
package/dist/i18n/utils.js
CHANGED
|
@@ -134,8 +134,30 @@ function computeCurrentLocale(pathname, locales, defaultLocale) {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
function computeCurrentLocaleFromParams(params, locales) {
|
|
138
|
+
const byNormalizedCode = /* @__PURE__ */ new Map();
|
|
139
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
140
|
+
for (const locale of locales) {
|
|
141
|
+
if (typeof locale === "string") {
|
|
142
|
+
byNormalizedCode.set(normalizeTheLocale(locale), locale);
|
|
143
|
+
} else {
|
|
144
|
+
byPath.set(locale.path, locale.codes[0]);
|
|
145
|
+
for (const code of locale.codes) {
|
|
146
|
+
byNormalizedCode.set(normalizeTheLocale(code), code);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const value of Object.values(params)) {
|
|
151
|
+
if (!value) continue;
|
|
152
|
+
const pathMatch = byPath.get(value);
|
|
153
|
+
if (pathMatch) return pathMatch;
|
|
154
|
+
const codeMatch = byNormalizedCode.get(normalizeTheLocale(value));
|
|
155
|
+
if (codeMatch) return codeMatch;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
137
158
|
export {
|
|
138
159
|
computeCurrentLocale,
|
|
160
|
+
computeCurrentLocaleFromParams,
|
|
139
161
|
computePreferredLocale,
|
|
140
162
|
computePreferredLocaleList,
|
|
141
163
|
parseLocale
|
|
@@ -34,6 +34,14 @@ function serializedManifestPlugin({
|
|
|
34
34
|
sync
|
|
35
35
|
}) {
|
|
36
36
|
const normalizedSrcDir = normalizePath(fileURLToPath(settings.config.srcDir));
|
|
37
|
+
let encodedKeyPromise;
|
|
38
|
+
function getEncodedKey() {
|
|
39
|
+
encodedKeyPromise ??= (async () => {
|
|
40
|
+
const key = hasEnvironmentKey() ? await getEnvironmentKey() : await createKey();
|
|
41
|
+
return encodeKey(key);
|
|
42
|
+
})();
|
|
43
|
+
return encodedKeyPromise;
|
|
44
|
+
}
|
|
37
45
|
function reloadManifest(path, server) {
|
|
38
46
|
if (path != null && normalizePath(path).startsWith(normalizedSrcDir)) {
|
|
39
47
|
const environment = server.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr];
|
|
@@ -67,7 +75,7 @@ function serializedManifestPlugin({
|
|
|
67
75
|
if (command === "build" && !sync) {
|
|
68
76
|
manifestData = `'${MANIFEST_REPLACE}'`;
|
|
69
77
|
} else {
|
|
70
|
-
const serialized = await createSerializedManifest(settings);
|
|
78
|
+
const serialized = await createSerializedManifest(settings, await getEncodedKey());
|
|
71
79
|
manifestData = JSON.stringify(serialized);
|
|
72
80
|
}
|
|
73
81
|
const hasCacheConfig = !!settings.config.experimental?.cache?.provider;
|
|
@@ -103,7 +111,7 @@ function serializedManifestPlugin({
|
|
|
103
111
|
}
|
|
104
112
|
};
|
|
105
113
|
}
|
|
106
|
-
async function createSerializedManifest(settings) {
|
|
114
|
+
async function createSerializedManifest(settings, encodedKey) {
|
|
107
115
|
let i18nManifest;
|
|
108
116
|
let csp;
|
|
109
117
|
if (settings.config.i18n) {
|
|
@@ -161,7 +169,7 @@ async function createSerializedManifest(settings) {
|
|
|
161
169
|
// 1mb default
|
|
162
170
|
serverIslandBodySizeLimit: settings.config.security?.serverIslandBodySizeLimit ? settings.config.security.serverIslandBodySizeLimit : 1024 * 1024,
|
|
163
171
|
// 1mb default
|
|
164
|
-
key: await encodeKey(hasEnvironmentKey() ? await getEnvironmentKey() : await createKey()),
|
|
172
|
+
key: encodedKey ?? await encodeKey(hasEnvironmentKey() ? await getEnvironmentKey() : await createKey()),
|
|
165
173
|
sessionConfig: sessionConfigToManifest(settings.config.session),
|
|
166
174
|
cacheConfig: cacheConfigToManifest(
|
|
167
175
|
settings.config.experimental?.cache,
|
|
@@ -19,7 +19,7 @@ import { getViteErrorPayload } from "../core/errors/dev/index.js";
|
|
|
19
19
|
import { AstroError, AstroErrorData } from "../core/errors/index.js";
|
|
20
20
|
import { NOOP_MIDDLEWARE_FN } from "../core/middleware/noop-middleware.js";
|
|
21
21
|
import { createViteLoader } from "../core/module-loader/index.js";
|
|
22
|
-
import {
|
|
22
|
+
import { matchAllRoutes } from "../core/routing/match.js";
|
|
23
23
|
import { resolveMiddlewareMode } from "../integrations/adapter-utils.js";
|
|
24
24
|
import { SERIALIZED_MANIFEST_ID } from "../manifest/serialized.js";
|
|
25
25
|
import { ASTRO_DEV_SERVER_APP_ID } from "../vite-plugin-app/index.js";
|
|
@@ -126,7 +126,7 @@ function createVitePluginAstroServer({
|
|
|
126
126
|
const { routes } = await prerenderHandler.environment.runner.import("virtual:astro:routes");
|
|
127
127
|
const routesList = { routes: routes.map((r) => r.routeData) };
|
|
128
128
|
const matches = matchAllRoutes(pathname, routesList);
|
|
129
|
-
if (!matches.some((route) => route.prerender
|
|
129
|
+
if (!matches.some((route) => route.prerender)) {
|
|
130
130
|
return next();
|
|
131
131
|
}
|
|
132
132
|
localStorage.run(request, () => {
|
|
@@ -18,6 +18,23 @@ import {
|
|
|
18
18
|
function getComponentFromVirtualModuleCssName(virtualModulePrefix, id) {
|
|
19
19
|
return id.slice(virtualModulePrefix.length).replace(new RegExp(ASTRO_CSS_EXTENSION_POST_PATTERN, "g"), ".");
|
|
20
20
|
}
|
|
21
|
+
async function ensureModulesLoaded(env, mod, seen = /* @__PURE__ */ new Set()) {
|
|
22
|
+
const id = mod.id ?? mod.url;
|
|
23
|
+
if (seen.has(id)) return;
|
|
24
|
+
seen.add(id);
|
|
25
|
+
for (const imp of mod.importedModules) {
|
|
26
|
+
if (!imp.id) continue;
|
|
27
|
+
if (seen.has(imp.id)) continue;
|
|
28
|
+
if (imp.id.includes(PROPAGATED_ASSET_QUERY_PARAM)) continue;
|
|
29
|
+
if (!imp.transformResult) {
|
|
30
|
+
try {
|
|
31
|
+
await env.fetchModule(imp.id);
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
await ensureModulesLoaded(env, imp, seen);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
21
38
|
function* collectCSSWithOrder(id, mod, seen = /* @__PURE__ */ new Set()) {
|
|
22
39
|
seen.add(id);
|
|
23
40
|
if (id.includes(PROPAGATED_ASSET_QUERY_PARAM)) {
|
|
@@ -98,6 +115,9 @@ function astroDevCssPlugin({ routesList, command }) {
|
|
|
98
115
|
code: "export const css = new Set()"
|
|
99
116
|
};
|
|
100
117
|
}
|
|
118
|
+
if (env) {
|
|
119
|
+
await ensureModulesLoaded(env, mod);
|
|
120
|
+
}
|
|
101
121
|
for (const collected of collectCSSWithOrder(componentPageId, mod)) {
|
|
102
122
|
if (!cssWithOrder.has(collected.idKey)) {
|
|
103
123
|
const content = cssContentCache.get(collected.id) || collected.content;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ConfigEnv, Plugin as VitePlugin } from 'vite';
|
|
2
|
+
import type { ServerIslandsState } from '../core/server-islands/shared-state.js';
|
|
2
3
|
import type { AstroSettings, RoutesList } from '../types/astro.js';
|
|
3
4
|
export declare const ASTRO_RENDERERS_MODULE_ID = "virtual:astro:renderers";
|
|
4
5
|
interface PluginOptions {
|
|
5
6
|
settings: AstroSettings;
|
|
6
7
|
routesList: RoutesList;
|
|
8
|
+
serverIslandsState: ServerIslandsState;
|
|
7
9
|
command: ConfigEnv['command'];
|
|
8
10
|
}
|
|
9
11
|
export default function vitePluginRenderers(options: PluginOptions): VitePlugin;
|
|
@@ -20,7 +20,7 @@ function vitePluginRenderers(options) {
|
|
|
20
20
|
id: new RegExp(`^${RESOLVED_ASTRO_RENDERERS_MODULE_ID}$`)
|
|
21
21
|
},
|
|
22
22
|
handler() {
|
|
23
|
-
if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !hasNonPrerenderedProjectRoute(options.routesList.routes, {
|
|
23
|
+
if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !options.serverIslandsState.hasIslands() && !hasNonPrerenderedProjectRoute(options.routesList.routes, {
|
|
24
24
|
includeEndpoints: false
|
|
25
25
|
})) {
|
|
26
26
|
return { code: `export const renderers = [];` };
|