astro 6.0.3 → 6.0.4
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 +3 -3
- package/dist/core/build/index.d.ts +39 -1
- package/dist/core/build/index.js +17 -10
- package/dist/core/build/static-build.js +26 -8
- 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/server-islands/vite-plugin-server-islands.d.ts +1 -0
- package/dist/core/server-islands/vite-plugin-server-islands.js +123 -30
- 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/route-guard.js +7 -3
- package/dist/vite-plugin-environment/index.js +1 -1
- package/dist/vite-plugin-routes/index.js +5 -0
- package/package.json +3 -3
- package/templates/env.mjs +0 -1
|
@@ -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.4") {
|
|
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.4") {
|
|
201
|
+
this.#store.metaStore().set("astro-version", "6.0.4");
|
|
202
202
|
}
|
|
203
203
|
if (currentConfigDigest) {
|
|
204
204
|
this.#store.metaStore().set("content-config-digest", currentConfigDigest);
|
|
@@ -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
|
};
|
|
@@ -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 { serverIslandPlaceholderMap } 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(serverIslandPlaceholderMap);
|
|
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);
|
|
@@ -224,6 +236,10 @@ async function buildEnvironments(opts, internals) {
|
|
|
224
236
|
const prerenderOutputs = viteBuildReturnToRollupOutputs(prerenderOutput);
|
|
225
237
|
const prerenderChunks = extractRelevantChunks(prerenderOutputs, true);
|
|
226
238
|
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.4";
|
|
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 { 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 serverIslandPlaceholderMap = "'$$server-islands-map$$'";
|
|
4
5
|
export declare function vitePluginServerIslands({ settings }: AstroPluginOptions): VitePlugin;
|
|
@@ -1,16 +1,32 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import { getPrerenderOutputDirectory, getServerOutputDirectory } from "../../prerender/utils.js";
|
|
2
3
|
import { AstroError, AstroErrorData } from "../errors/index.js";
|
|
4
|
+
import { appendForwardSlash } from "../path.js";
|
|
3
5
|
import { ASTRO_VITE_ENVIRONMENT_NAMES } from "../constants.js";
|
|
4
6
|
const SERVER_ISLAND_MANIFEST = "virtual:astro:server-island-manifest";
|
|
5
7
|
const RESOLVED_SERVER_ISLAND_MANIFEST = "\0" + SERVER_ISLAND_MANIFEST;
|
|
6
8
|
const serverIslandPlaceholderMap = "'$$server-islands-map$$'";
|
|
7
9
|
const serverIslandPlaceholderNameMap = "'$$server-islands-name-map$$'";
|
|
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
25
|
const referenceIdMap = /* @__PURE__ */ new Map();
|
|
12
26
|
const serverIslandMap = /* @__PURE__ */ new Map();
|
|
13
27
|
const serverIslandNameMap = /* @__PURE__ */ new Map();
|
|
28
|
+
const resolvedIslandImports = /* @__PURE__ */ new Map();
|
|
29
|
+
let ssrManifestChunk = null;
|
|
14
30
|
return {
|
|
15
31
|
name: "astro:server-islands",
|
|
16
32
|
enforce: "post",
|
|
@@ -70,7 +86,7 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
70
86
|
serverIslandNameMap.set(comp.resolvedPath, name);
|
|
71
87
|
serverIslandMap.set(name, comp.resolvedPath);
|
|
72
88
|
if (command === "build") {
|
|
73
|
-
|
|
89
|
+
const referenceId = this.emitFile({
|
|
74
90
|
type: "chunk",
|
|
75
91
|
id: comp.specifier,
|
|
76
92
|
importer: id,
|
|
@@ -95,18 +111,17 @@ export const serverIslandNameMap = ${serverIslandPlaceholderNameMap};`
|
|
|
95
111
|
}
|
|
96
112
|
}
|
|
97
113
|
if (serverIslandNameMap.size > 0 && serverIslandMap.size > 0) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
mapSource += "]);";
|
|
114
|
+
const mapSource = createServerIslandImportMapSource(
|
|
115
|
+
serverIslandMap,
|
|
116
|
+
(fileName) => fileName
|
|
117
|
+
);
|
|
118
|
+
const nameMapSource = createNameMapSource(serverIslandNameMap);
|
|
104
119
|
return {
|
|
105
120
|
code: `
|
|
106
121
|
export const serverIslandMap = ${mapSource};
|
|
107
122
|
|
|
108
123
|
|
|
109
|
-
export const serverIslandNameMap =
|
|
124
|
+
export const serverIslandNameMap = ${nameMapSource};
|
|
110
125
|
`
|
|
111
126
|
};
|
|
112
127
|
}
|
|
@@ -115,38 +130,116 @@ export const serverIslandNameMap = new Map(${JSON.stringify(Array.from(serverIsl
|
|
|
115
130
|
},
|
|
116
131
|
renderChunk(code, chunk) {
|
|
117
132
|
if (code.includes(serverIslandPlaceholderMap)) {
|
|
118
|
-
if (
|
|
133
|
+
if (command === "build") {
|
|
134
|
+
if (referenceIdMap.size === 0) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const isRelativeChunk = !chunk.isEntry;
|
|
138
|
+
const dots = isRelativeChunk ? ".." : ".";
|
|
139
|
+
const mapEntries = [];
|
|
140
|
+
for (const [resolvedPath, referenceId] of referenceIdMap) {
|
|
141
|
+
const fileName = this.getFileName(referenceId);
|
|
142
|
+
const islandName = serverIslandNameMap.get(resolvedPath);
|
|
143
|
+
if (!islandName) continue;
|
|
144
|
+
if (!resolvedIslandImports.has(islandName)) {
|
|
145
|
+
resolvedIslandImports.set(islandName, fileName);
|
|
146
|
+
}
|
|
147
|
+
mapEntries.push([islandName, fileName]);
|
|
148
|
+
}
|
|
149
|
+
const mapSource = createServerIslandImportMapSource(
|
|
150
|
+
mapEntries,
|
|
151
|
+
(fileName) => `${dots}/${fileName}`
|
|
152
|
+
);
|
|
153
|
+
const nameMapSource = createNameMapSource(serverIslandNameMap);
|
|
119
154
|
return {
|
|
120
|
-
code: code.replace(serverIslandPlaceholderMap,
|
|
155
|
+
code: code.replace(serverIslandPlaceholderMap, mapSource).replace(serverIslandPlaceholderNameMap, nameMapSource),
|
|
121
156
|
map: null
|
|
122
157
|
};
|
|
123
158
|
}
|
|
124
|
-
const isRelativeChunk = !chunk.isEntry;
|
|
125
|
-
const dots = isRelativeChunk ? ".." : ".";
|
|
126
|
-
let mapSource = "new Map([";
|
|
127
|
-
let nameMapSource = "new Map(";
|
|
128
|
-
for (let [resolvedPath, referenceId] of referenceIdMap) {
|
|
129
|
-
const fileName = this.getFileName(referenceId);
|
|
130
|
-
const islandName = serverIslandNameMap.get(resolvedPath);
|
|
131
|
-
mapSource += `
|
|
132
|
-
['${islandName}', () => import('${dots}/${fileName}')],`;
|
|
133
|
-
}
|
|
134
|
-
nameMapSource += `${JSON.stringify(Array.from(serverIslandNameMap.entries()), null, 2)}`;
|
|
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);
|
|
141
159
|
return {
|
|
142
|
-
code:
|
|
143
|
-
map:
|
|
160
|
+
code: code.replace(serverIslandPlaceholderMap, "new Map();").replace(serverIslandPlaceholderNameMap, "new Map()"),
|
|
161
|
+
map: null
|
|
144
162
|
};
|
|
145
163
|
}
|
|
164
|
+
},
|
|
165
|
+
generateBundle(_options, bundle) {
|
|
166
|
+
const envName = this.environment?.name;
|
|
167
|
+
if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.ssr) {
|
|
168
|
+
for (const chunk of Object.values(bundle)) {
|
|
169
|
+
if (chunk.type === "chunk" && chunk.code.includes(serverIslandPlaceholderMap)) {
|
|
170
|
+
ssrManifestChunk = chunk;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (envName === ASTRO_VITE_ENVIRONMENT_NAMES.prerender && ssrManifestChunk) {
|
|
176
|
+
if (resolvedIslandImports.size > 0) {
|
|
177
|
+
const isRelativeChunk = ssrManifestChunk.fileName.includes("/");
|
|
178
|
+
const dots = isRelativeChunk ? ".." : ".";
|
|
179
|
+
const mapSource = createServerIslandImportMapSource(
|
|
180
|
+
resolvedIslandImports,
|
|
181
|
+
(fileName) => `${dots}/${fileName}`
|
|
182
|
+
);
|
|
183
|
+
const nameMapSource = createNameMapSource(serverIslandNameMap);
|
|
184
|
+
ssrManifestChunk.code = ssrManifestChunk.code.replace(serverIslandPlaceholderMap, mapSource).replace(serverIslandPlaceholderNameMap, nameMapSource);
|
|
185
|
+
} else {
|
|
186
|
+
ssrManifestChunk.code = ssrManifestChunk.code.replace(serverIslandPlaceholderMap, "new Map()").replace(serverIslandPlaceholderNameMap, "new Map()");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
api: {
|
|
191
|
+
/**
|
|
192
|
+
* Post-build hook that patches SSR chunks containing server island placeholders.
|
|
193
|
+
*
|
|
194
|
+
* During build, SSR can run before all server islands are discovered (e.g. islands
|
|
195
|
+
* only used in prerendered pages). This hook runs after SSR + prerender builds and:
|
|
196
|
+
* 1) replaces placeholders with the complete map of discovered islands
|
|
197
|
+
* 2) copies island chunks emitted in prerender into the SSR output directory
|
|
198
|
+
*
|
|
199
|
+
* Two cases:
|
|
200
|
+
* 1. Islands were discovered: Replace placeholders with real import maps.
|
|
201
|
+
* 2. No islands found: Replace placeholders with empty maps.
|
|
202
|
+
*/
|
|
203
|
+
async buildPostHook({
|
|
204
|
+
chunks,
|
|
205
|
+
mutate
|
|
206
|
+
}) {
|
|
207
|
+
const ssrChunkWithPlaceholder = chunks.find(
|
|
208
|
+
(c) => !c.prerender && c.code.includes(serverIslandPlaceholderMap)
|
|
209
|
+
);
|
|
210
|
+
if (!ssrChunkWithPlaceholder) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
if (resolvedIslandImports.size > 0) {
|
|
214
|
+
const isRelativeChunk = ssrChunkWithPlaceholder.fileName.includes("/");
|
|
215
|
+
const dots = isRelativeChunk ? ".." : ".";
|
|
216
|
+
const mapSource = createServerIslandImportMapSource(
|
|
217
|
+
resolvedIslandImports,
|
|
218
|
+
(fileName) => `${dots}/${fileName}`
|
|
219
|
+
);
|
|
220
|
+
const nameMapSource = createNameMapSource(serverIslandNameMap);
|
|
221
|
+
const newCode = ssrChunkWithPlaceholder.code.replace(serverIslandPlaceholderMap, mapSource).replace(serverIslandPlaceholderNameMap, nameMapSource);
|
|
222
|
+
mutate(ssrChunkWithPlaceholder.fileName, newCode, false);
|
|
223
|
+
const serverOutputDir = getServerOutputDirectory(settings);
|
|
224
|
+
const prerenderOutputDir = getPrerenderOutputDirectory(settings);
|
|
225
|
+
for (const [, fileName] of resolvedIslandImports) {
|
|
226
|
+
const srcPath = new URL(fileName, appendForwardSlash(prerenderOutputDir.toString()));
|
|
227
|
+
const destPath = new URL(fileName, appendForwardSlash(serverOutputDir.toString()));
|
|
228
|
+
if (!fs.existsSync(srcPath)) continue;
|
|
229
|
+
const destDir = new URL("./", destPath);
|
|
230
|
+
await fs.promises.mkdir(destDir, { recursive: true });
|
|
231
|
+
await fs.promises.copyFile(srcPath, destPath);
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
const newCode = ssrChunkWithPlaceholder.code.replace(serverIslandPlaceholderMap, "new Map()").replace(serverIslandPlaceholderNameMap, "new Map()");
|
|
235
|
+
mutate(ssrChunkWithPlaceholder.fileName, newCode, false);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
146
238
|
}
|
|
147
239
|
};
|
|
148
240
|
}
|
|
149
241
|
export {
|
|
150
242
|
SERVER_ISLAND_MANIFEST,
|
|
243
|
+
serverIslandPlaceholderMap,
|
|
151
244
|
vitePluginServerIslands
|
|
152
245
|
};
|
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
|
},
|
|
@@ -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
|
};
|
|
@@ -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
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "astro",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.4",
|
|
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",
|
|
@@ -153,9 +153,9 @@
|
|
|
153
153
|
"xxhash-wasm": "^1.1.0",
|
|
154
154
|
"yargs-parser": "^22.0.0",
|
|
155
155
|
"zod": "^4.3.6",
|
|
156
|
+
"@astrojs/internal-helpers": "0.8.0",
|
|
156
157
|
"@astrojs/markdown-remark": "7.0.0",
|
|
157
|
-
"@astrojs/telemetry": "3.3.0"
|
|
158
|
-
"@astrojs/internal-helpers": "0.8.0"
|
|
158
|
+
"@astrojs/telemetry": "3.3.0"
|
|
159
159
|
},
|
|
160
160
|
"optionalDependencies": {
|
|
161
161
|
"sharp": "^0.34.0"
|
package/templates/env.mjs
CHANGED