astro 6.0.3 → 6.0.5
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/actions/integration.js +9 -6
- package/dist/assets/runtime.d.ts +2 -1
- package/dist/assets/runtime.js +15 -4
- package/dist/assets/utils/svg.js +25 -7
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/content/content-layer.js +3 -3
- package/dist/content/server-listeners.js +4 -0
- package/dist/content/types-generator.js +4 -1
- package/dist/core/build/generate.js +92 -84
- package/dist/core/build/index.d.ts +39 -1
- package/dist/core/build/index.js +17 -10
- package/dist/core/build/plugins/plugin-internals.js +12 -13
- package/dist/core/build/static-build.js +33 -15
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/errors/dev/utils.js +1 -1
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/routing/helpers.d.ts +7 -0
- package/dist/core/routing/helpers.js +9 -0
- package/dist/core/server-islands/vite-plugin-server-islands.d.ts +1 -0
- package/dist/core/server-islands/vite-plugin-server-islands.js +89 -57
- package/dist/i18n/router.js +2 -1
- package/dist/prerender/utils.d.ts +4 -0
- package/dist/prerender/utils.js +4 -0
- package/dist/toolbar/vite-plugin-dev-toolbar.js +5 -1
- package/dist/vite-plugin-astro-server/plugin.js +2 -2
- package/dist/vite-plugin-astro-server/route-guard.js +7 -3
- package/dist/vite-plugin-environment/index.js +1 -1
- package/dist/vite-plugin-renderers/index.js +4 -6
- package/dist/vite-plugin-routes/index.js +5 -0
- package/dist/vite-plugin-scripts/index.js +1 -1
- package/package.json +4 -4
- package/templates/env.mjs +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AstroError } from "../core/errors/errors.js";
|
|
2
2
|
import { ActionsWithoutServerOutputError } from "../core/errors/errors-data.js";
|
|
3
|
+
import { hasNonPrerenderedProjectRoute } from "../core/routing/helpers.js";
|
|
3
4
|
import { viteID } from "../core/util.js";
|
|
4
5
|
import { ACTION_RPC_ROUTE_PATTERN, ACTIONS_TYPES_FILE, VIRTUAL_MODULE_ID } from "./consts.js";
|
|
5
6
|
function astroIntegrationActionsRouteHandler({
|
|
@@ -18,20 +19,22 @@ function astroIntegrationActionsRouteHandler({
|
|
|
18
19
|
});
|
|
19
20
|
},
|
|
20
21
|
"astro:config:done": async (params) => {
|
|
21
|
-
if (params.buildOutput === "static") {
|
|
22
|
-
const error = new AstroError(ActionsWithoutServerOutputError);
|
|
23
|
-
error.stack = void 0;
|
|
24
|
-
throw error;
|
|
25
|
-
}
|
|
26
22
|
const stringifiedActionsImport = JSON.stringify(
|
|
27
23
|
viteID(new URL(`./${filename}`, params.config.srcDir))
|
|
28
24
|
);
|
|
29
25
|
settings.injectedTypes.push({
|
|
30
26
|
filename: ACTIONS_TYPES_FILE,
|
|
31
27
|
content: `declare module "astro:actions" {
|
|
32
|
-
|
|
28
|
+
export const actions: typeof import(${stringifiedActionsImport})["server"];
|
|
33
29
|
}`
|
|
34
30
|
});
|
|
31
|
+
},
|
|
32
|
+
"astro:routes:resolved": ({ routes }) => {
|
|
33
|
+
if (!hasNonPrerenderedProjectRoute(routes)) {
|
|
34
|
+
const error = new AstroError(ActionsWithoutServerOutputError);
|
|
35
|
+
error.stack = void 0;
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
35
38
|
}
|
|
36
39
|
}
|
|
37
40
|
};
|
package/dist/assets/runtime.d.ts
CHANGED
|
@@ -3,8 +3,9 @@ export interface SvgComponentProps {
|
|
|
3
3
|
meta: ImageMetadata;
|
|
4
4
|
attributes: Record<string, string>;
|
|
5
5
|
children: string;
|
|
6
|
+
styles: string[];
|
|
6
7
|
}
|
|
7
|
-
export declare function createSvgComponent({ meta, attributes, children }: SvgComponentProps): import("../runtime/server/index.js").AstroComponentFactory & ImageMetadata;
|
|
8
|
+
export declare function createSvgComponent({ meta, attributes, children, styles }: SvgComponentProps): import("../runtime/server/index.js").AstroComponentFactory & ImageMetadata;
|
|
8
9
|
type SvgAttributes = Record<string, any>;
|
|
9
10
|
export declare function dropAttributes(attributes: SvgAttributes): SvgAttributes;
|
|
10
11
|
export {};
|
package/dist/assets/runtime.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
import { generateCspDigest } from "../core/encryption.js";
|
|
1
2
|
import {
|
|
2
3
|
createComponent,
|
|
3
4
|
render,
|
|
4
5
|
spreadAttributes,
|
|
5
6
|
unescapeHTML
|
|
6
7
|
} from "../runtime/server/index.js";
|
|
7
|
-
function createSvgComponent({ meta, attributes, children }) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
function createSvgComponent({ meta, attributes, children, styles }) {
|
|
9
|
+
const hasStyles = styles.length > 0;
|
|
10
|
+
const Component = createComponent({
|
|
11
|
+
async factory(result, props) {
|
|
12
|
+
const normalizedProps = normalizeProps(attributes, props);
|
|
13
|
+
if (hasStyles && result.cspDestination) {
|
|
14
|
+
for (const style of styles) {
|
|
15
|
+
const hash = await generateCspDigest(style, result.cspAlgorithm);
|
|
16
|
+
result._metadata.extraStyleHashes.push(hash);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return render`<svg${spreadAttributes(normalizedProps)}>${unescapeHTML(children)}</svg>`;
|
|
20
|
+
},
|
|
21
|
+
propagation: hasStyles ? "self" : "none"
|
|
11
22
|
});
|
|
12
23
|
if (import.meta.env.DEV) {
|
|
13
24
|
makeNonEnumerable(Component);
|
package/dist/assets/utils/svg.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { optimize } from "svgo";
|
|
2
|
-
import { parse, renderSync } from "ultrahtml";
|
|
2
|
+
import { ELEMENT_NODE, TEXT_NODE, parse, renderSync } from "ultrahtml";
|
|
3
3
|
import { AstroError, AstroErrorData } from "../../core/errors/index.js";
|
|
4
4
|
import { dropAttributes } from "../runtime.js";
|
|
5
5
|
function parseSvg({
|
|
@@ -25,18 +25,31 @@ function parseSvg({
|
|
|
25
25
|
}
|
|
26
26
|
const root = parse(processedContents);
|
|
27
27
|
const svgNode = root.children.find(
|
|
28
|
-
({ name, type }) => type ===
|
|
28
|
+
({ name, type }) => type === ELEMENT_NODE && name === "svg"
|
|
29
29
|
);
|
|
30
30
|
if (!svgNode) {
|
|
31
31
|
throw new Error("SVG file does not contain an <svg> element");
|
|
32
32
|
}
|
|
33
33
|
const { attributes, children } = svgNode;
|
|
34
34
|
const body = renderSync({ ...root, children });
|
|
35
|
-
|
|
35
|
+
const styles = [];
|
|
36
|
+
for (const child of children) {
|
|
37
|
+
if (child.type === ELEMENT_NODE && child.name === "style") {
|
|
38
|
+
const textContent = child.children?.filter((c) => c.type === TEXT_NODE).map((c) => c.value).join("");
|
|
39
|
+
if (textContent) {
|
|
40
|
+
styles.push(textContent);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return { attributes, body, styles };
|
|
36
45
|
}
|
|
37
46
|
function makeSvgComponent(meta, contents, svgoConfig) {
|
|
38
47
|
const file = typeof contents === "string" ? contents : contents.toString("utf-8");
|
|
39
|
-
const {
|
|
48
|
+
const {
|
|
49
|
+
attributes,
|
|
50
|
+
body: children,
|
|
51
|
+
styles
|
|
52
|
+
} = parseSvg({
|
|
40
53
|
path: meta.fsPath,
|
|
41
54
|
contents: file,
|
|
42
55
|
svgoConfig
|
|
@@ -44,19 +57,24 @@ function makeSvgComponent(meta, contents, svgoConfig) {
|
|
|
44
57
|
const props = {
|
|
45
58
|
meta,
|
|
46
59
|
attributes: dropAttributes(attributes),
|
|
47
|
-
children
|
|
60
|
+
children,
|
|
61
|
+
styles
|
|
48
62
|
};
|
|
49
63
|
return `import { createSvgComponent } from 'astro/assets/runtime';
|
|
50
64
|
export default createSvgComponent(${JSON.stringify(props)})`;
|
|
51
65
|
}
|
|
52
66
|
function parseSvgComponentData(meta, contents, svgoConfig) {
|
|
53
67
|
const file = typeof contents === "string" ? contents : contents.toString("utf-8");
|
|
54
|
-
const {
|
|
68
|
+
const {
|
|
69
|
+
attributes,
|
|
70
|
+
body: children,
|
|
71
|
+
styles
|
|
72
|
+
} = parseSvg({
|
|
55
73
|
path: meta.fsPath,
|
|
56
74
|
contents: file,
|
|
57
75
|
svgoConfig
|
|
58
76
|
});
|
|
59
|
-
return { attributes: dropAttributes(attributes), children };
|
|
77
|
+
return { attributes: dropAttributes(attributes), children, styles };
|
|
60
78
|
}
|
|
61
79
|
export {
|
|
62
80
|
makeSvgComponent,
|
|
@@ -189,7 +189,7 @@ ${contentConfig.error.message}`
|
|
|
189
189
|
logger.info("Content config changed");
|
|
190
190
|
shouldClear = true;
|
|
191
191
|
}
|
|
192
|
-
if (previousAstroVersion && previousAstroVersion !== "6.0.
|
|
192
|
+
if (previousAstroVersion && previousAstroVersion !== "6.0.5") {
|
|
193
193
|
logger.info("Astro version changed");
|
|
194
194
|
shouldClear = true;
|
|
195
195
|
}
|
|
@@ -197,8 +197,8 @@ ${contentConfig.error.message}`
|
|
|
197
197
|
logger.info("Clearing content store");
|
|
198
198
|
this.#store.clearAll();
|
|
199
199
|
}
|
|
200
|
-
if ("6.0.
|
|
201
|
-
this.#store.metaStore().set("astro-version", "6.0.
|
|
200
|
+
if ("6.0.5") {
|
|
201
|
+
this.#store.metaStore().set("astro-version", "6.0.5");
|
|
202
202
|
}
|
|
203
203
|
if (currentConfigDigest) {
|
|
204
204
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
@@ -6,6 +6,10 @@ async function attachContentServerListeners({
|
|
|
6
6
|
logger,
|
|
7
7
|
settings
|
|
8
8
|
}) {
|
|
9
|
+
const maxListeners = viteServer.watcher.getMaxListeners();
|
|
10
|
+
if (maxListeners !== 0 && maxListeners < 50) {
|
|
11
|
+
viteServer.watcher.setMaxListeners(50);
|
|
12
|
+
}
|
|
9
13
|
const contentGenerator = await createContentTypesGenerator({
|
|
10
14
|
fs,
|
|
11
15
|
settings,
|
|
@@ -463,7 +463,10 @@ async function generateJSONSchema(fsMod, collectionConfig, collectionKey, collec
|
|
|
463
463
|
ctx.jsonSchema.type = "string";
|
|
464
464
|
ctx.jsonSchema.format = "date-time";
|
|
465
465
|
}
|
|
466
|
-
}
|
|
466
|
+
},
|
|
467
|
+
// Collection schemas are used for parsing collection input, so we need to tell Zod to use the
|
|
468
|
+
// input shape when generating a JSON schema.
|
|
469
|
+
io: "input"
|
|
467
470
|
});
|
|
468
471
|
const schemaStr = JSON.stringify(schema, null, 2);
|
|
469
472
|
const schemaJsonPath = new URL(
|
|
@@ -61,102 +61,106 @@ async function generatePages(options, internals, prerenderOutputDir) {
|
|
|
61
61
|
const verb = ssr ? "prerendering" : "generating";
|
|
62
62
|
logger.info("SKIP_FORMAT", `
|
|
63
63
|
${colors.bgGreen(colors.black(` ${verb} static routes `))}`);
|
|
64
|
-
const pathsWithRoutes = await prerenderer.getStaticPaths();
|
|
65
64
|
const routeToHeaders = /* @__PURE__ */ new Map();
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
65
|
+
let staticImageList = getStaticImageList();
|
|
66
|
+
try {
|
|
67
|
+
const pathsWithRoutes = await prerenderer.getStaticPaths();
|
|
68
|
+
const hasI18nDomains = ssr && options.settings.config.i18n?.domains && Object.keys(options.settings.config.i18n.domains).length > 0;
|
|
69
|
+
const { config } = options.settings;
|
|
70
|
+
const builtPaths = /* @__PURE__ */ new Set();
|
|
71
|
+
const filteredPaths = pathsWithRoutes.filter(({ pathname, route }) => {
|
|
72
|
+
if (hasI18nDomains && route.prerender) {
|
|
73
|
+
throw new AstroError({
|
|
74
|
+
...AstroErrorData.NoPrerenderedRoutesWithDomains,
|
|
75
|
+
message: AstroErrorData.NoPrerenderedRoutesWithDomains.message(route.component)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const normalized = removeTrailingForwardSlash(pathname);
|
|
79
|
+
if (!builtPaths.has(normalized)) {
|
|
80
|
+
builtPaths.add(normalized);
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
const matchedRoute = matchRoute(decodeURI(pathname), options.routesList);
|
|
84
|
+
if (!matchedRoute) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
if (matchedRoute === route) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
if (config.prerenderConflictBehavior === "error") {
|
|
91
|
+
throw new AstroError({
|
|
92
|
+
...AstroErrorData.PrerenderRouteConflict,
|
|
93
|
+
message: AstroErrorData.PrerenderRouteConflict.message(
|
|
94
|
+
matchedRoute.route,
|
|
95
|
+
route.route,
|
|
96
|
+
normalized
|
|
97
|
+
),
|
|
98
|
+
hint: AstroErrorData.PrerenderRouteConflict.hint(matchedRoute.route, route.route)
|
|
99
|
+
});
|
|
100
|
+
} else if (config.prerenderConflictBehavior === "warn") {
|
|
101
|
+
const msg = AstroErrorData.PrerenderRouteConflict.message(
|
|
92
102
|
matchedRoute.route,
|
|
93
103
|
route.route,
|
|
94
104
|
normalized
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
() => generatePathWithPrerenderer(
|
|
118
|
-
prerenderer,
|
|
119
|
-
pathname,
|
|
120
|
-
route,
|
|
121
|
-
options,
|
|
122
|
-
routeToHeaders,
|
|
123
|
-
logger
|
|
105
|
+
);
|
|
106
|
+
logger.warn("build", msg);
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
});
|
|
110
|
+
if (config.build.concurrency > 1) {
|
|
111
|
+
const limit = PLimit(config.build.concurrency);
|
|
112
|
+
const BATCH_SIZE = 1e5;
|
|
113
|
+
for (let i = 0; i < filteredPaths.length; i += BATCH_SIZE) {
|
|
114
|
+
const batch = filteredPaths.slice(i, i + BATCH_SIZE);
|
|
115
|
+
const promises = [];
|
|
116
|
+
for (const { pathname, route } of batch) {
|
|
117
|
+
promises.push(
|
|
118
|
+
limit(
|
|
119
|
+
() => generatePathWithPrerenderer(
|
|
120
|
+
prerenderer,
|
|
121
|
+
pathname,
|
|
122
|
+
route,
|
|
123
|
+
options,
|
|
124
|
+
routeToHeaders,
|
|
125
|
+
logger
|
|
126
|
+
)
|
|
124
127
|
)
|
|
125
|
-
)
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
await Promise.all(promises);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
for (const { pathname, route } of filteredPaths) {
|
|
134
|
+
await generatePathWithPrerenderer(
|
|
135
|
+
prerenderer,
|
|
136
|
+
pathname,
|
|
137
|
+
route,
|
|
138
|
+
options,
|
|
139
|
+
routeToHeaders,
|
|
140
|
+
logger
|
|
126
141
|
);
|
|
127
142
|
}
|
|
128
|
-
await Promise.all(promises);
|
|
129
|
-
}
|
|
130
|
-
} else {
|
|
131
|
-
for (const { pathname, route } of filteredPaths) {
|
|
132
|
-
await generatePathWithPrerenderer(
|
|
133
|
-
prerenderer,
|
|
134
|
-
pathname,
|
|
135
|
-
route,
|
|
136
|
-
options,
|
|
137
|
-
routeToHeaders,
|
|
138
|
-
logger
|
|
139
|
-
);
|
|
140
143
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
144
|
+
for (const { route: generatedRoute } of filteredPaths) {
|
|
145
|
+
if (generatedRoute.distURL && generatedRoute.distURL.length > 0) {
|
|
146
|
+
for (const pageData of Object.values(options.allPages)) {
|
|
147
|
+
if (pageData.route.route === generatedRoute.route && pageData.route.component === generatedRoute.component) {
|
|
148
|
+
pageData.route.distURL = generatedRoute.distURL;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
148
151
|
}
|
|
149
152
|
}
|
|
150
153
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
staticImageList = getStaticImageList();
|
|
155
|
+
if (prerenderer.collectStaticImages) {
|
|
156
|
+
const adapterImages = await prerenderer.collectStaticImages();
|
|
157
|
+
for (const [path, entry] of adapterImages) {
|
|
158
|
+
staticImageList.set(path, entry);
|
|
159
|
+
}
|
|
157
160
|
}
|
|
161
|
+
} finally {
|
|
162
|
+
await prerenderer.teardown?.();
|
|
158
163
|
}
|
|
159
|
-
await prerenderer.teardown?.();
|
|
160
164
|
logger.info(
|
|
161
165
|
null,
|
|
162
166
|
colors.green(`\u2713 Completed in ${getTimeStat(generatePagesTimer, performance.now())}.
|
|
@@ -328,7 +332,11 @@ function getUrlForPath(pathname, base, origin, format, trailingSlash, routeType)
|
|
|
328
332
|
}
|
|
329
333
|
let buildPathname;
|
|
330
334
|
if (pathname === "/" || pathname === "") {
|
|
331
|
-
|
|
335
|
+
if (format === "file") {
|
|
336
|
+
buildPathname = joinPaths(base, "index.html");
|
|
337
|
+
} else {
|
|
338
|
+
buildPathname = collapseDuplicateTrailingSlashes(base + ending, trailingSlash !== "never");
|
|
339
|
+
}
|
|
332
340
|
} else if (routeType === "endpoint") {
|
|
333
341
|
const buildPathRelative = removeLeadingForwardSlash(pathname);
|
|
334
342
|
buildPathname = joinPaths(base, buildPathRelative);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AstroSettings, RoutesList } from '../../types/astro.js';
|
|
2
|
+
import type { AstroInlineConfig, RuntimeMode } from '../../types/public/config.js';
|
|
3
|
+
import type { Logger } from '../logger/core.js';
|
|
2
4
|
interface BuildOptions {
|
|
3
5
|
/**
|
|
4
6
|
* Output a development-based build similar to code transformed in `astro dev`. This
|
|
@@ -25,4 +27,40 @@ interface BuildOptions {
|
|
|
25
27
|
* @experimental The JavaScript API is experimental
|
|
26
28
|
*/
|
|
27
29
|
export default function build(inlineConfig: AstroInlineConfig, options?: BuildOptions): Promise<void>;
|
|
30
|
+
interface AstroBuilderOptions extends BuildOptions {
|
|
31
|
+
logger: Logger;
|
|
32
|
+
mode: string;
|
|
33
|
+
runtimeMode: RuntimeMode;
|
|
34
|
+
/**
|
|
35
|
+
* Provide a pre-built routes list to skip filesystem route scanning.
|
|
36
|
+
* Useful for testing builds with in-memory virtual modules.
|
|
37
|
+
*/
|
|
38
|
+
routesList?: RoutesList;
|
|
39
|
+
/**
|
|
40
|
+
* Whether to run `syncInternal` during setup. Defaults to true.
|
|
41
|
+
* Set to false for in-memory builds that don't need type generation.
|
|
42
|
+
*/
|
|
43
|
+
sync?: boolean;
|
|
44
|
+
}
|
|
45
|
+
export declare class AstroBuilder {
|
|
46
|
+
private settings;
|
|
47
|
+
private logger;
|
|
48
|
+
private mode;
|
|
49
|
+
private runtimeMode;
|
|
50
|
+
private origin;
|
|
51
|
+
private routesList;
|
|
52
|
+
private timer;
|
|
53
|
+
private teardownCompiler;
|
|
54
|
+
private sync;
|
|
55
|
+
constructor(settings: AstroSettings, options: AstroBuilderOptions);
|
|
56
|
+
/** Setup Vite and run any async setup logic that couldn't run inside of the constructor. */
|
|
57
|
+
private setup;
|
|
58
|
+
/** Run the build logic. build() is marked private because usage should go through ".run()" */
|
|
59
|
+
private build;
|
|
60
|
+
/** Build the given Astro project. */
|
|
61
|
+
run(): Promise<void>;
|
|
62
|
+
private validateConfig;
|
|
63
|
+
/** Stats */
|
|
64
|
+
private printStats;
|
|
65
|
+
}
|
|
28
66
|
export {};
|
package/dist/core/build/index.js
CHANGED
|
@@ -56,14 +56,16 @@ class AstroBuilder {
|
|
|
56
56
|
routesList;
|
|
57
57
|
timer;
|
|
58
58
|
teardownCompiler;
|
|
59
|
+
sync;
|
|
59
60
|
constructor(settings, options) {
|
|
60
61
|
this.mode = options.mode;
|
|
61
62
|
this.runtimeMode = options.runtimeMode;
|
|
62
63
|
this.settings = settings;
|
|
63
64
|
this.logger = options.logger;
|
|
64
65
|
this.teardownCompiler = options.teardownCompiler ?? true;
|
|
66
|
+
this.sync = options.sync ?? true;
|
|
65
67
|
this.origin = settings.config.site ? new URL(settings.config.site).origin : `http://localhost:${settings.config.server.port}`;
|
|
66
|
-
this.routesList = { routes: [] };
|
|
68
|
+
this.routesList = options.routesList ?? { routes: [] };
|
|
67
69
|
this.timer = {};
|
|
68
70
|
}
|
|
69
71
|
/** Setup Vite and run any async setup logic that couldn't run inside of the constructor. */
|
|
@@ -77,7 +79,9 @@ class AstroBuilder {
|
|
|
77
79
|
logger
|
|
78
80
|
});
|
|
79
81
|
this.settings.buildOutput = getPrerenderDefault(this.settings.config) ? "static" : "server";
|
|
80
|
-
this.routesList
|
|
82
|
+
if (this.routesList.routes.length === 0) {
|
|
83
|
+
this.routesList = await createRoutesList({ settings: this.settings }, this.logger);
|
|
84
|
+
}
|
|
81
85
|
await runHookConfigDone({ settings: this.settings, logger, command: "build" });
|
|
82
86
|
if (!this.settings.config.adapter && this.settings.buildOutput === "server") {
|
|
83
87
|
throw new AstroError(AstroErrorData.NoAdapterInstalled);
|
|
@@ -98,14 +102,16 @@ class AstroBuilder {
|
|
|
98
102
|
sync: false
|
|
99
103
|
}
|
|
100
104
|
);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
105
|
+
if (this.sync) {
|
|
106
|
+
const { syncInternal } = await import("../sync/index.js");
|
|
107
|
+
await syncInternal({
|
|
108
|
+
mode: this.mode,
|
|
109
|
+
settings: this.settings,
|
|
110
|
+
logger,
|
|
111
|
+
fs,
|
|
112
|
+
command: "build"
|
|
113
|
+
});
|
|
114
|
+
}
|
|
109
115
|
return { viteConfig };
|
|
110
116
|
}
|
|
111
117
|
/** Run the build logic. build() is marked private because usage should go through ".run()" */
|
|
@@ -215,5 +221,6 @@ class AstroBuilder {
|
|
|
215
221
|
}
|
|
216
222
|
}
|
|
217
223
|
export {
|
|
224
|
+
AstroBuilder,
|
|
218
225
|
build as default
|
|
219
226
|
};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { normalizeEntryId } from "./plugin-component-entry.js";
|
|
2
2
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../../constants.js";
|
|
3
|
+
function getRollupInputAsSet(rollupInput) {
|
|
4
|
+
if (Array.isArray(rollupInput)) {
|
|
5
|
+
return new Set(rollupInput);
|
|
6
|
+
} else if (typeof rollupInput === "string") {
|
|
7
|
+
return /* @__PURE__ */ new Set([rollupInput]);
|
|
8
|
+
} else if (rollupInput && typeof rollupInput === "object") {
|
|
9
|
+
return new Set(Object.values(rollupInput));
|
|
10
|
+
} else {
|
|
11
|
+
return /* @__PURE__ */ new Set();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
3
14
|
function pluginInternals(options, internals) {
|
|
4
|
-
let input;
|
|
5
15
|
return {
|
|
6
16
|
name: "@astro/plugin-build-internals",
|
|
7
17
|
applyToEnvironment(environment) {
|
|
@@ -27,19 +37,8 @@ function pluginInternals(options, internals) {
|
|
|
27
37
|
};
|
|
28
38
|
}
|
|
29
39
|
},
|
|
30
|
-
configResolved(config) {
|
|
31
|
-
const rollupInput = config.build?.rollupOptions?.input;
|
|
32
|
-
if (Array.isArray(rollupInput)) {
|
|
33
|
-
input = new Set(rollupInput);
|
|
34
|
-
} else if (typeof rollupInput === "string") {
|
|
35
|
-
input = /* @__PURE__ */ new Set([rollupInput]);
|
|
36
|
-
} else if (rollupInput && typeof rollupInput === "object") {
|
|
37
|
-
input = new Set(Object.values(rollupInput));
|
|
38
|
-
} else {
|
|
39
|
-
input = /* @__PURE__ */ new Set();
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
40
|
async generateBundle(_options, bundle) {
|
|
41
|
+
const input = getRollupInputAsSet(this.environment?.config.build.rollupOptions.input);
|
|
43
42
|
const promises = [];
|
|
44
43
|
const mapping = /* @__PURE__ */ new Map();
|
|
45
44
|
const allInput = /* @__PURE__ */ new Set([...input, ...internals.clientInput]);
|
|
@@ -10,7 +10,11 @@ import { emptyDir, removeEmptyDirs } from "../../core/fs/index.js";
|
|
|
10
10
|
import { appendForwardSlash, prependForwardSlash } from "../../core/path.js";
|
|
11
11
|
import { runHookBuildSetup } from "../../integrations/hooks.js";
|
|
12
12
|
import { SERIALIZED_MANIFEST_RESOLVED_ID } from "../../manifest/serialized.js";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
getClientOutputDirectory,
|
|
15
|
+
getPrerenderOutputDirectory,
|
|
16
|
+
getServerOutputDirectory
|
|
17
|
+
} from "../../prerender/utils.js";
|
|
14
18
|
import { VIRTUAL_PAGE_RESOLVED_MODULE_ID } from "../../vite-plugin-pages/const.js";
|
|
15
19
|
import { PAGE_SCRIPT_ID } from "../../vite-plugin-scripts/index.js";
|
|
16
20
|
import { routeIsRedirect } from "../routing/helpers.js";
|
|
@@ -30,6 +34,7 @@ import { encodeName, getTimeStat, viteBuildReturnToRollupOutputs } from "./util.
|
|
|
30
34
|
import { NOOP_MODULE_ID } from "./plugins/plugin-noop.js";
|
|
31
35
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js";
|
|
32
36
|
import { getSSRAssets } from "./internal.js";
|
|
37
|
+
import { SERVER_ISLAND_MAP_MARKER } from "../server-islands/vite-plugin-server-islands.js";
|
|
33
38
|
const PRERENDER_ENTRY_FILENAME_PREFIX = "prerender-entry";
|
|
34
39
|
function extractRelevantChunks(outputs, prerender) {
|
|
35
40
|
const extracted = [];
|
|
@@ -38,7 +43,8 @@ function extractRelevantChunks(outputs, prerender) {
|
|
|
38
43
|
if (chunk.type === "asset") continue;
|
|
39
44
|
const needsContentInjection = chunk.code.includes(LINKS_PLACEHOLDER);
|
|
40
45
|
const needsManifestInjection = chunk.moduleIds.includes(SERIALIZED_MANIFEST_RESOLVED_ID);
|
|
41
|
-
|
|
46
|
+
const needsServerIslandInjection = chunk.code.includes(SERVER_ISLAND_MAP_MARKER);
|
|
47
|
+
if (needsContentInjection || needsManifestInjection || needsServerIslandInjection) {
|
|
42
48
|
extracted.push({
|
|
43
49
|
fileName: chunk.fileName,
|
|
44
50
|
code: chunk.code,
|
|
@@ -82,6 +88,7 @@ async function buildEnvironments(opts, internals) {
|
|
|
82
88
|
const flatPlugins = buildPlugins.flat().filter(Boolean);
|
|
83
89
|
const plugins = [...flatPlugins, ...viteConfig.plugins || []];
|
|
84
90
|
let currentRollupInput = void 0;
|
|
91
|
+
let buildPostHooks = [];
|
|
85
92
|
plugins.push({
|
|
86
93
|
name: "astro:resolve-input",
|
|
87
94
|
// When the rollup input is safe to update, we normalize it to always be an object
|
|
@@ -107,8 +114,13 @@ async function buildEnvironments(opts, internals) {
|
|
|
107
114
|
buildApp: {
|
|
108
115
|
order: "post",
|
|
109
116
|
async handler() {
|
|
110
|
-
await runManifestInjection(
|
|
111
|
-
|
|
117
|
+
await runManifestInjection(
|
|
118
|
+
opts,
|
|
119
|
+
internals,
|
|
120
|
+
internals.extractedChunks ?? [],
|
|
121
|
+
buildPostHooks
|
|
122
|
+
);
|
|
123
|
+
const prerenderOutputDir = getPrerenderOutputDirectory(settings);
|
|
112
124
|
if (settings.buildOutput === "static") {
|
|
113
125
|
settings.timer.start("Static generate");
|
|
114
126
|
await ssrMoveAssets(opts, internals, prerenderOutputDir);
|
|
@@ -206,6 +218,13 @@ async function buildEnvironments(opts, internals) {
|
|
|
206
218
|
// This takes precedence over platform plugin fallbacks (e.g., Cloudflare)
|
|
207
219
|
builder: {
|
|
208
220
|
async buildApp(builder2) {
|
|
221
|
+
settings.timer.start("Prerender build");
|
|
222
|
+
let prerenderOutput = await builder2.build(builder2.environments.prerender);
|
|
223
|
+
settings.timer.end("Prerender build");
|
|
224
|
+
extractPrerenderEntryFileName(internals, prerenderOutput);
|
|
225
|
+
const prerenderOutputs = viteBuildReturnToRollupOutputs(prerenderOutput);
|
|
226
|
+
const prerenderChunks = extractRelevantChunks(prerenderOutputs, true);
|
|
227
|
+
prerenderOutput = void 0;
|
|
209
228
|
let ssrChunks = [];
|
|
210
229
|
if (settings.buildOutput !== "static") {
|
|
211
230
|
settings.timer.start("SSR build");
|
|
@@ -217,13 +236,10 @@ async function buildEnvironments(opts, internals) {
|
|
|
217
236
|
ssrChunks = extractRelevantChunks(ssrOutputs, false);
|
|
218
237
|
ssrOutput = void 0;
|
|
219
238
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const prerenderOutputs = viteBuildReturnToRollupOutputs(prerenderOutput);
|
|
225
|
-
const prerenderChunks = extractRelevantChunks(prerenderOutputs, true);
|
|
226
|
-
prerenderOutput = void 0;
|
|
239
|
+
const ssrPlugins = builder2.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr]?.config.plugins ?? [];
|
|
240
|
+
buildPostHooks = ssrPlugins.map(
|
|
241
|
+
(plugin) => typeof plugin.api?.buildPostHook === "function" ? plugin.api.buildPostHook : void 0
|
|
242
|
+
).filter(Boolean);
|
|
227
243
|
internals.clientInput = getClientInput(internals, settings);
|
|
228
244
|
if (!internals.clientInput.size) {
|
|
229
245
|
internals.clientInput.add(NOOP_MODULE_ID);
|
|
@@ -244,7 +260,7 @@ async function buildEnvironments(opts, internals) {
|
|
|
244
260
|
[ASTRO_VITE_ENVIRONMENT_NAMES.prerender]: {
|
|
245
261
|
build: {
|
|
246
262
|
emitAssets: true,
|
|
247
|
-
outDir: fileURLToPath(
|
|
263
|
+
outDir: fileURLToPath(getPrerenderOutputDirectory(settings)),
|
|
248
264
|
rollupOptions: {
|
|
249
265
|
// Only skip the default prerender entrypoint if an adapter with `entrypointResolution: 'self'` is used
|
|
250
266
|
// AND provides a custom prerenderer. Otherwise, use the default.
|
|
@@ -318,7 +334,7 @@ function getPrerenderEntryFileName(prerenderOutput) {
|
|
|
318
334
|
function extractPrerenderEntryFileName(internals, prerenderOutput) {
|
|
319
335
|
internals.prerenderEntryFileName = getPrerenderEntryFileName(prerenderOutput);
|
|
320
336
|
}
|
|
321
|
-
async function runManifestInjection(opts, internals, chunks) {
|
|
337
|
+
async function runManifestInjection(opts, internals, chunks, buildPostHooks) {
|
|
322
338
|
const mutations = /* @__PURE__ */ new Map();
|
|
323
339
|
const mutate = (fileName, newCode, prerender) => {
|
|
324
340
|
mutations.set(fileName, { code: newCode, prerender });
|
|
@@ -330,16 +346,18 @@ async function runManifestInjection(opts, internals, chunks) {
|
|
|
330
346
|
internals,
|
|
331
347
|
{ chunks, mutate }
|
|
332
348
|
);
|
|
349
|
+
for (const buildPostHook of buildPostHooks) {
|
|
350
|
+
await buildPostHook({ chunks, mutate });
|
|
351
|
+
}
|
|
333
352
|
await writeMutatedChunks(opts, mutations);
|
|
334
353
|
}
|
|
335
354
|
async function writeMutatedChunks(opts, mutations) {
|
|
336
355
|
const { settings } = opts;
|
|
337
356
|
const config = settings.config;
|
|
338
|
-
const serverOutputDir = getServerOutputDirectory(settings);
|
|
339
357
|
for (const [fileName, mutation] of mutations) {
|
|
340
358
|
let root;
|
|
341
359
|
if (mutation.prerender) {
|
|
342
|
-
root =
|
|
360
|
+
root = getPrerenderOutputDirectory(settings);
|
|
343
361
|
} else if (settings.buildOutput === "server") {
|
|
344
362
|
root = config.build.server;
|
|
345
363
|
} else {
|
package/dist/core/constants.js
CHANGED
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.5";
|
|
30
30
|
const isPrerelease = currentVersion.includes("-");
|
|
31
31
|
if (!isPrerelease) {
|
|
32
32
|
try {
|
|
@@ -90,7 +90,7 @@ function collectErrorMetadata(e, rootFolder) {
|
|
|
90
90
|
function generateHint(err) {
|
|
91
91
|
const commonBrowserAPIs = ["document", "window"];
|
|
92
92
|
if (/Unknown file extension "\.(?:jsx|vue|svelte|astro|css)" for /.test(err.message)) {
|
|
93
|
-
return "You likely need to add this package to `vite.
|
|
93
|
+
return "You likely need to add this package to `vite.resolve.noExternal` in your astro config file.";
|
|
94
94
|
} else if (commonBrowserAPIs.some((api) => err.toString().includes(api))) {
|
|
95
95
|
const hint = `Browser APIs are not available on the server.
|
|
96
96
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RouteData } from '../../types/public/internal.js';
|
|
2
|
+
import type { IntegrationResolvedRoute } from '../../types/public/integrations.js';
|
|
2
3
|
import type { RouteInfo } from '../app/types.js';
|
|
3
4
|
import type { RoutesList } from '../../types/astro.js';
|
|
4
5
|
type RedirectRouteData = RouteData & {
|
|
@@ -31,4 +32,10 @@ export declare function getCustom404Route(manifestData: RoutesList): RouteData |
|
|
|
31
32
|
* Return a user-provided 500 route if one exists.
|
|
32
33
|
*/
|
|
33
34
|
export declare function getCustom500Route(manifestData: RoutesList): RouteData | undefined;
|
|
35
|
+
export declare function hasNonPrerenderedProjectRoute(routes: Array<Pick<RouteData, 'type' | 'origin' | 'prerender'>>, options?: {
|
|
36
|
+
includeEndpoints?: boolean;
|
|
37
|
+
}): boolean;
|
|
38
|
+
export declare function hasNonPrerenderedProjectRoute(routes: Array<Pick<IntegrationResolvedRoute, 'type' | 'origin' | 'isPrerendered'>>, options?: {
|
|
39
|
+
includeEndpoints?: boolean;
|
|
40
|
+
}): boolean;
|
|
34
41
|
export {};
|
|
@@ -25,10 +25,19 @@ function getCustom404Route(manifestData) {
|
|
|
25
25
|
function getCustom500Route(manifestData) {
|
|
26
26
|
return manifestData.routes.find((r) => isRoute500(r.route));
|
|
27
27
|
}
|
|
28
|
+
function hasNonPrerenderedProjectRoute(routes, options) {
|
|
29
|
+
const includeEndpoints = options?.includeEndpoints ?? true;
|
|
30
|
+
const routeTypes = includeEndpoints ? ["page", "endpoint"] : ["page"];
|
|
31
|
+
return routes.some((route) => {
|
|
32
|
+
const isPrerendered = "isPrerendered" in route ? route.isPrerendered : route.prerender;
|
|
33
|
+
return routeTypes.includes(route.type) && route.origin === "project" && !isPrerendered;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
28
36
|
export {
|
|
29
37
|
getCustom404Route,
|
|
30
38
|
getCustom500Route,
|
|
31
39
|
getFallbackRoute,
|
|
40
|
+
hasNonPrerenderedProjectRoute,
|
|
32
41
|
routeIsFallback,
|
|
33
42
|
routeIsRedirect
|
|
34
43
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Plugin as VitePlugin } from 'vite';
|
|
2
2
|
import type { AstroPluginOptions } from '../../types/astro.js';
|
|
3
3
|
export declare const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest";
|
|
4
|
+
export declare const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$";
|
|
4
5
|
export declare function vitePluginServerIslands({ settings }: AstroPluginOptions): VitePlugin;
|
|
@@ -1,22 +1,56 @@
|
|
|
1
|
-
import MagicString from "magic-string";
|
|
2
|
-
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
3
1
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js";
|
|
2
|
+
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
4
3
|
const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest";
|
|
5
4
|
const RESOLVED_SERVER_ISLAND_MANIFEST = "\0" + SERVER_ISLAND_MANIFEST;
|
|
6
5
|
const serverIslandPlaceholderMap = "'$$server-islands-map$$'";
|
|
7
6
|
const serverIslandPlaceholderNameMap = "'$$server-islands-name-map$$'";
|
|
7
|
+
const SERVER_ISLAND_MAP_MARKER = "$$server-islands-map$$";
|
|
8
|
+
const serverIslandMapReplaceExp = /['"]\$\$server-islands-map\$\$['"]/g;
|
|
9
|
+
const serverIslandNameMapReplaceExp = /['"]\$\$server-islands-name-map\$\$['"]/g;
|
|
10
|
+
function createServerIslandImportMapSource(entries, toImportPath) {
|
|
11
|
+
const mappings = Array.from(entries, ([islandName, fileName]) => {
|
|
12
|
+
const importPath = toImportPath(fileName);
|
|
13
|
+
return ` [${JSON.stringify(islandName)}, () => import(${JSON.stringify(importPath)})],`;
|
|
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
|
+
}
|
|
8
22
|
function vitePluginServerIslands({ settings }) {
|
|
9
23
|
let command = "serve";
|
|
10
24
|
let ssrEnvironment = null;
|
|
11
|
-
const referenceIdMap = /* @__PURE__ */ new Map();
|
|
12
25
|
const serverIslandMap = /* @__PURE__ */ new Map();
|
|
13
26
|
const serverIslandNameMap = /* @__PURE__ */ new Map();
|
|
27
|
+
const serverIslandSourceMap = /* @__PURE__ */ new Map();
|
|
28
|
+
const referenceIdMap = /* @__PURE__ */ new Map();
|
|
29
|
+
function ensureServerIslandReferenceIds(ctx) {
|
|
30
|
+
for (const [resolvedPath, islandName] of serverIslandNameMap) {
|
|
31
|
+
if (referenceIdMap.has(resolvedPath)) continue;
|
|
32
|
+
const source = serverIslandSourceMap.get(resolvedPath);
|
|
33
|
+
const referenceId = ctx.emitFile({
|
|
34
|
+
type: "chunk",
|
|
35
|
+
id: source?.id ?? resolvedPath,
|
|
36
|
+
importer: source?.importer,
|
|
37
|
+
name: islandName
|
|
38
|
+
});
|
|
39
|
+
referenceIdMap.set(resolvedPath, referenceId);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
14
42
|
return {
|
|
15
43
|
name: "astro:server-islands",
|
|
16
44
|
enforce: "post",
|
|
17
45
|
config(_config, { command: _command }) {
|
|
18
46
|
command = _command;
|
|
19
47
|
},
|
|
48
|
+
buildStart() {
|
|
49
|
+
if (command !== "build" || this.environment?.name !== ASTRO_VITE_ENVIRONMENT_NAMES.ssr) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
ensureServerIslandReferenceIds(this);
|
|
53
|
+
},
|
|
20
54
|
configureServer(server) {
|
|
21
55
|
ssrEnvironment = server.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr];
|
|
22
56
|
},
|
|
@@ -43,16 +77,13 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
43
77
|
transform: {
|
|
44
78
|
filter: {
|
|
45
79
|
id: {
|
|
46
|
-
include: [
|
|
47
|
-
// Allows server islands in astro and mdx files
|
|
48
|
-
/\.(astro|mdx)$/,
|
|
49
|
-
new RegExp(`^${RESOLVED_SERVER_ISLAND_MANIFEST}$`)
|
|
50
|
-
]
|
|
80
|
+
include: [/\.(astro|mdx)$/, new RegExp(`^${RESOLVED_SERVER_ISLAND_MANIFEST}$`)]
|
|
51
81
|
}
|
|
52
82
|
},
|
|
53
83
|
async handler(_code, id) {
|
|
54
84
|
const info = this.getModuleInfo(id);
|
|
55
85
|
const astro = info ? info.meta.astro : void 0;
|
|
86
|
+
const isBuildSsr = command === "build" && this.environment?.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr;
|
|
56
87
|
if (astro) {
|
|
57
88
|
for (const comp of astro.serverComponents) {
|
|
58
89
|
if (!serverIslandNameMap.has(comp.resolvedPath)) {
|
|
@@ -61,23 +92,23 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
61
92
|
}
|
|
62
93
|
let name = comp.localName;
|
|
63
94
|
let idx = 1;
|
|
64
|
-
while (
|
|
65
|
-
if (!serverIslandMap.has(name)) {
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
95
|
+
while (serverIslandMap.has(name)) {
|
|
68
96
|
name += idx++;
|
|
69
97
|
}
|
|
70
98
|
serverIslandNameMap.set(comp.resolvedPath, name);
|
|
71
99
|
serverIslandMap.set(name, comp.resolvedPath);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
100
|
+
serverIslandSourceMap.set(comp.resolvedPath, { id: comp.specifier, importer: id });
|
|
101
|
+
}
|
|
102
|
+
if (isBuildSsr && !referenceIdMap.has(comp.resolvedPath)) {
|
|
103
|
+
const islandName = serverIslandNameMap.get(comp.resolvedPath);
|
|
104
|
+
const source = serverIslandSourceMap.get(comp.resolvedPath);
|
|
105
|
+
const referenceId = this.emitFile({
|
|
106
|
+
type: "chunk",
|
|
107
|
+
id: source?.id ?? comp.resolvedPath,
|
|
108
|
+
importer: source?.importer,
|
|
109
|
+
name: islandName
|
|
110
|
+
});
|
|
111
|
+
referenceIdMap.set(comp.resolvedPath, referenceId);
|
|
81
112
|
}
|
|
82
113
|
}
|
|
83
114
|
}
|
|
@@ -94,59 +125,60 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
94
125
|
throw new AstroError(AstroErrorData.NoAdapterInstalledServerIslands);
|
|
95
126
|
}
|
|
96
127
|
}
|
|
97
|
-
if (serverIslandNameMap.size > 0 && serverIslandMap.size > 0) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
mapSource += "]);";
|
|
128
|
+
if (command !== "build" && serverIslandNameMap.size > 0 && serverIslandMap.size > 0) {
|
|
129
|
+
const mapSource = createServerIslandImportMapSource(
|
|
130
|
+
serverIslandMap,
|
|
131
|
+
(fileName) => fileName
|
|
132
|
+
);
|
|
133
|
+
const nameMapSource = createNameMapSource(serverIslandNameMap);
|
|
104
134
|
return {
|
|
105
135
|
code: `
|
|
106
|
-
|
|
107
|
-
|
|
136
|
+
export const serverIslandMap = ${mapSource};
|
|
108
137
|
|
|
109
|
-
export const serverIslandNameMap =
|
|
110
|
-
|
|
138
|
+
export const serverIslandNameMap = ${nameMapSource};
|
|
139
|
+
`
|
|
111
140
|
};
|
|
112
141
|
}
|
|
113
142
|
}
|
|
114
143
|
}
|
|
115
144
|
},
|
|
116
145
|
renderChunk(code, chunk) {
|
|
117
|
-
if (code.includes(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
mapSource
|
|
132
|
-
|
|
146
|
+
if (!code.includes(SERVER_ISLAND_MAP_MARKER)) return;
|
|
147
|
+
if (command === "build") {
|
|
148
|
+
const envName = this.environment?.name;
|
|
149
|
+
let mapSource;
|
|
150
|
+
if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr) {
|
|
151
|
+
const isRelativeChunk = !chunk.isEntry;
|
|
152
|
+
const dots = isRelativeChunk ? ".." : ".";
|
|
153
|
+
const mapEntries = [];
|
|
154
|
+
for (const [resolvedPath, referenceId] of referenceIdMap) {
|
|
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,
|
|
162
|
+
(fileName) => `${dots}/${fileName}`
|
|
163
|
+
);
|
|
164
|
+
} else {
|
|
165
|
+
mapSource = createServerIslandImportMapSource(serverIslandMap, (fileName) => fileName);
|
|
133
166
|
}
|
|
134
|
-
nameMapSource
|
|
135
|
-
mapSource += "\n])";
|
|
136
|
-
nameMapSource += "\n)";
|
|
137
|
-
referenceIdMap.clear();
|
|
138
|
-
const ms = new MagicString(code);
|
|
139
|
-
ms.replace(serverIslandPlaceholderMap, mapSource);
|
|
140
|
-
ms.replace(serverIslandPlaceholderNameMap, nameMapSource);
|
|
167
|
+
const nameMapSource = createNameMapSource(serverIslandNameMap);
|
|
141
168
|
return {
|
|
142
|
-
code:
|
|
143
|
-
map:
|
|
169
|
+
code: code.replace(serverIslandMapReplaceExp, mapSource).replace(serverIslandNameMapReplaceExp, nameMapSource),
|
|
170
|
+
map: null
|
|
144
171
|
};
|
|
145
172
|
}
|
|
173
|
+
return {
|
|
174
|
+
code: code.replace(serverIslandMapReplaceExp, "new Map();").replace(serverIslandNameMapReplaceExp, "new Map()"),
|
|
175
|
+
map: null
|
|
176
|
+
};
|
|
146
177
|
}
|
|
147
178
|
};
|
|
148
179
|
}
|
|
149
180
|
export {
|
|
150
181
|
SERVER_ISLAND_MANIFEST,
|
|
182
|
+
SERVER_ISLAND_MAP_MARKER,
|
|
151
183
|
vitePluginServerIslands
|
|
152
184
|
};
|
package/dist/i18n/router.js
CHANGED
|
@@ -74,9 +74,10 @@ class I18nRouter {
|
|
|
74
74
|
matchPrefixAlways(pathname, _context) {
|
|
75
75
|
const isRoot = pathname === this.#base + "/" || pathname === this.#base;
|
|
76
76
|
if (isRoot) {
|
|
77
|
+
const basePrefix = this.#base === "/" ? "" : this.#base;
|
|
77
78
|
return {
|
|
78
79
|
type: "redirect",
|
|
79
|
-
location: `${
|
|
80
|
+
location: `${basePrefix}/${this.#defaultLocale}`
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
if (!pathHasLocale(pathname, this.#locales)) {
|
|
@@ -5,6 +5,10 @@ export declare function getPrerenderDefault(config: AstroConfig): boolean;
|
|
|
5
5
|
* Returns the correct output directory of the SSR build based on the configuration
|
|
6
6
|
*/
|
|
7
7
|
export declare function getServerOutputDirectory(settings: AstroSettings): URL;
|
|
8
|
+
/**
|
|
9
|
+
* Returns the output directory used by the prerender environment.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getPrerenderOutputDirectory(settings: AstroSettings): URL;
|
|
8
12
|
/**
|
|
9
13
|
* Returns the correct output directory of the client build based on the configuration
|
|
10
14
|
*/
|
package/dist/prerender/utils.js
CHANGED
|
@@ -5,6 +5,9 @@ function getPrerenderDefault(config) {
|
|
|
5
5
|
function getServerOutputDirectory(settings) {
|
|
6
6
|
return settings.buildOutput === "server" ? settings.config.build.server : getOutDirWithinCwd(settings.config.outDir);
|
|
7
7
|
}
|
|
8
|
+
function getPrerenderOutputDirectory(settings) {
|
|
9
|
+
return new URL("./.prerender/", getServerOutputDirectory(settings));
|
|
10
|
+
}
|
|
8
11
|
function getClientOutputDirectory(settings) {
|
|
9
12
|
const preserveStructure = settings.adapter?.adapterFeatures?.preserveBuildClientDir;
|
|
10
13
|
if (settings.buildOutput === "server" || preserveStructure) {
|
|
@@ -15,5 +18,6 @@ function getClientOutputDirectory(settings) {
|
|
|
15
18
|
export {
|
|
16
19
|
getClientOutputDirectory,
|
|
17
20
|
getPrerenderDefault,
|
|
21
|
+
getPrerenderOutputDirectory,
|
|
18
22
|
getServerOutputDirectory
|
|
19
23
|
};
|
|
@@ -10,7 +10,11 @@ function astroDevToolbar({ settings, logger }) {
|
|
|
10
10
|
return {
|
|
11
11
|
optimizeDeps: {
|
|
12
12
|
// Optimize CJS dependencies used by the dev toolbar
|
|
13
|
-
include: [
|
|
13
|
+
include: [
|
|
14
|
+
"astro > aria-query",
|
|
15
|
+
"astro > axobject-query",
|
|
16
|
+
...settings.devToolbarApps.length > 0 ? ["astro/toolbar"] : []
|
|
17
|
+
]
|
|
14
18
|
}
|
|
15
19
|
};
|
|
16
20
|
},
|
|
@@ -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 { matchAllRoutes } from "../core/routing/match.js";
|
|
22
|
+
import { isRouteServerIsland, 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";
|
|
@@ -130,7 +130,7 @@ function createVitePluginAstroServer({
|
|
|
130
130
|
const { routes } = await prerenderHandler.environment.runner.import("virtual:astro:routes");
|
|
131
131
|
const routesList = { routes: routes.map((r) => r.routeData) };
|
|
132
132
|
const matches = matchAllRoutes(pathname, routesList);
|
|
133
|
-
if (!matches.some((route) => route.prerender)) {
|
|
133
|
+
if (!matches.some((route) => route.prerender || isRouteServerIsland(route))) {
|
|
134
134
|
return next();
|
|
135
135
|
}
|
|
136
136
|
localStorage.run(request, () => {
|
|
@@ -42,9 +42,13 @@ function routeGuardMiddleware(settings) {
|
|
|
42
42
|
return next();
|
|
43
43
|
}
|
|
44
44
|
const rootFilePath = new URL("." + pathname, config.root);
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
45
|
+
try {
|
|
46
|
+
const stat = fs.statSync(rootFilePath);
|
|
47
|
+
if (stat.isFile()) {
|
|
48
|
+
const html = notFoundTemplate(pathname);
|
|
49
|
+
return writeHtmlResponse(res, 404, html);
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
48
52
|
}
|
|
49
53
|
return next();
|
|
50
54
|
};
|
|
@@ -62,7 +62,7 @@ function vitePluginEnvironment({
|
|
|
62
62
|
// For the dev toolbar
|
|
63
63
|
"astro > html-escaper"
|
|
64
64
|
],
|
|
65
|
-
exclude: ["astro:*", "virtual:astro:*"],
|
|
65
|
+
exclude: ["astro:*", "virtual:astro:*", "astro/virtual-modules/prefetch.js"],
|
|
66
66
|
// Astro files can't be rendered on the client
|
|
67
67
|
entries: [`${srcDirPattern}**/*.{jsx,tsx,vue,svelte,html}`]
|
|
68
68
|
};
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
|
|
2
|
+
import { hasNonPrerenderedProjectRoute } from "../core/routing/helpers.js";
|
|
2
3
|
const ASTRO_RENDERERS_MODULE_ID = "virtual:astro:renderers";
|
|
3
4
|
const RESOLVED_ASTRO_RENDERERS_MODULE_ID = `\0${ASTRO_RENDERERS_MODULE_ID}`;
|
|
4
|
-
function ssrBuildNeedsRenderers(routesList) {
|
|
5
|
-
return routesList.routes.some(
|
|
6
|
-
(route) => route.type === "page" && !route.prerender && route.origin !== "internal"
|
|
7
|
-
);
|
|
8
|
-
}
|
|
9
5
|
function vitePluginRenderers(options) {
|
|
10
6
|
const renderers = options.settings.renderers;
|
|
11
7
|
return {
|
|
@@ -24,7 +20,9 @@ function vitePluginRenderers(options) {
|
|
|
24
20
|
id: new RegExp(`^${RESOLVED_ASTRO_RENDERERS_MODULE_ID}$`)
|
|
25
21
|
},
|
|
26
22
|
handler() {
|
|
27
|
-
if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !
|
|
23
|
+
if (options.command === "build" && this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr && renderers.length > 0 && !hasNonPrerenderedProjectRoute(options.routesList.routes, {
|
|
24
|
+
includeEndpoints: false
|
|
25
|
+
})) {
|
|
28
26
|
return { code: `export const renderers = [];` };
|
|
29
27
|
}
|
|
30
28
|
if (renderers.length > 0) {
|
|
@@ -11,6 +11,7 @@ import { rootRelativePath } from "../core/viteUtils.js";
|
|
|
11
11
|
import { createDefaultAstroMetadata } from "../vite-plugin-astro/metadata.js";
|
|
12
12
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../core/constants.js";
|
|
13
13
|
import { isAstroServerEnvironment } from "../environments.js";
|
|
14
|
+
import { RESOLVED_MODULE_DEV_CSS_ALL } from "../vite-plugin-css/const.js";
|
|
14
15
|
import { PAGE_SCRIPT_ID } from "../vite-plugin-scripts/index.js";
|
|
15
16
|
const ASTRO_ROUTES_MODULE_ID = "virtual:astro:routes";
|
|
16
17
|
const ASTRO_ROUTES_MODULE_ID_RESOLVED = "\0" + ASTRO_ROUTES_MODULE_ID;
|
|
@@ -91,6 +92,10 @@ async function astroPluginRoutes({
|
|
|
91
92
|
const virtualMod = environment.moduleGraph.getModuleById(ASTRO_ROUTES_MODULE_ID_RESOLVED);
|
|
92
93
|
if (!virtualMod) continue;
|
|
93
94
|
environment.moduleGraph.invalidateModule(virtualMod);
|
|
95
|
+
const cssMod = environment.moduleGraph.getModuleById(RESOLVED_MODULE_DEV_CSS_ALL);
|
|
96
|
+
if (cssMod) {
|
|
97
|
+
environment.moduleGraph.invalidateModule(cssMod);
|
|
98
|
+
}
|
|
94
99
|
environment.hot.send("astro:routes-updated", {});
|
|
95
100
|
}
|
|
96
101
|
}
|
|
@@ -38,7 +38,7 @@ function astroScriptsPlugin({ settings }) {
|
|
|
38
38
|
},
|
|
39
39
|
buildStart() {
|
|
40
40
|
const hasHydrationScripts = settings.scripts.some((s) => s.stage === "before-hydration");
|
|
41
|
-
if (hasHydrationScripts && (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender || this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr)) {
|
|
41
|
+
if (hasHydrationScripts && (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client || this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.prerender || this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.ssr)) {
|
|
42
42
|
this.emitFile({
|
|
43
43
|
type: "chunk",
|
|
44
44
|
id: BEFORE_HYDRATION_SCRIPT_ID,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.5",
|
|
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",
|
|
@@ -154,8 +154,8 @@
|
|
|
154
154
|
"yargs-parser": "^22.0.0",
|
|
155
155
|
"zod": "^4.3.6",
|
|
156
156
|
"@astrojs/markdown-remark": "7.0.0",
|
|
157
|
-
"@astrojs/
|
|
158
|
-
"@astrojs/
|
|
157
|
+
"@astrojs/internal-helpers": "0.8.0",
|
|
158
|
+
"@astrojs/telemetry": "3.3.0"
|
|
159
159
|
},
|
|
160
160
|
"optionalDependencies": {
|
|
161
161
|
"sharp": "^0.34.0"
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
"undici": "^7.22.0",
|
|
191
191
|
"unified": "^11.0.5",
|
|
192
192
|
"vitest": "^3.2.4",
|
|
193
|
-
"@astrojs/check": "0.9.
|
|
193
|
+
"@astrojs/check": "0.9.8",
|
|
194
194
|
"astro-scripts": "0.0.14"
|
|
195
195
|
},
|
|
196
196
|
"engines": {
|
package/templates/env.mjs
CHANGED