Skip to content

Commit 3323f5c

Browse files
feat: improve rolldown compatibility (#13519)
* feat: improve rolldown compatibility * chore: remove moduleType * feat: use object shape * chore: changeset
1 parent 90b0ac1 commit 3323f5c

21 files changed

+175
-140
lines changed

.changeset/brave-pandas-make.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Refactors some internals to improve Rolldown compatibility

packages/astro/src/actions/plugins.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export function vitePluginActions({
126126
shouldAppendForwardSlash(settings.config.trailingSlash, settings.config.build.format),
127127
),
128128
);
129-
return code;
129+
return { code };
130130
},
131131
};
132132
}

packages/astro/src/assets/vite-plugin-assets.ts

+40-34
Original file line numberDiff line numberDiff line change
@@ -117,32 +117,34 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
117117
},
118118
load(id) {
119119
if (id === resolvedVirtualModuleId) {
120-
return /* ts */ `
121-
export { getConfiguredImageService, isLocalService } from "astro/assets";
122-
import { getImage as getImageInternal } from "astro/assets";
123-
export { default as Image } from "astro/components/${imageComponentPrefix}Image.astro";
124-
export { default as Picture } from "astro/components/${imageComponentPrefix}Picture.astro";
125-
export { inferRemoteSize } from "astro/assets/utils/inferRemoteSize.js";
126-
127-
export const imageConfig = ${JSON.stringify({ ...settings.config.image, experimentalResponsiveImages: settings.config.experimental.responsiveImages })};
128-
// This is used by the @astrojs/node integration to locate images.
129-
// It's unused on other platforms, but on some platforms like Netlify (and presumably also Vercel)
130-
// new URL("dist/...") is interpreted by the bundler as a signal to include that directory
131-
// in the Lambda bundle, which would bloat the bundle with images.
132-
// To prevent this, we mark the URL construction as pure,
133-
// so that it's tree-shaken away for all platforms that don't need it.
134-
export const outDir = /* #__PURE__ */ new URL(${JSON.stringify(
135-
new URL(
136-
settings.buildOutput === 'server'
137-
? settings.config.build.client
138-
: settings.config.outDir,
139-
),
140-
)});
141-
export const assetsDir = /* #__PURE__ */ new URL(${JSON.stringify(
142-
settings.config.build.assets,
143-
)}, outDir);
144-
export const getImage = async (options) => await getImageInternal(options, imageConfig);
145-
`;
120+
return {
121+
code: `
122+
export { getConfiguredImageService, isLocalService } from "astro/assets";
123+
import { getImage as getImageInternal } from "astro/assets";
124+
export { default as Image } from "astro/components/${imageComponentPrefix}Image.astro";
125+
export { default as Picture } from "astro/components/${imageComponentPrefix}Picture.astro";
126+
export { inferRemoteSize } from "astro/assets/utils/inferRemoteSize.js";
127+
128+
export const imageConfig = ${JSON.stringify({ ...settings.config.image, experimentalResponsiveImages: settings.config.experimental.responsiveImages })};
129+
// This is used by the @astrojs/node integration to locate images.
130+
// It's unused on other platforms, but on some platforms like Netlify (and presumably also Vercel)
131+
// new URL("dist/...") is interpreted by the bundler as a signal to include that directory
132+
// in the Lambda bundle, which would bloat the bundle with images.
133+
// To prevent this, we mark the URL construction as pure,
134+
// so that it's tree-shaken away for all platforms that don't need it.
135+
export const outDir = /* #__PURE__ */ new URL(${JSON.stringify(
136+
new URL(
137+
settings.buildOutput === 'server'
138+
? settings.config.build.client
139+
: settings.config.outDir,
140+
),
141+
)});
142+
export const assetsDir = /* #__PURE__ */ new URL(${JSON.stringify(
143+
settings.config.build.assets,
144+
)}, outDir);
145+
export const getImage = async (options) => await getImageInternal(options, imageConfig);
146+
`,
147+
};
146148
}
147149
},
148150
buildStart() {
@@ -151,7 +153,7 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
151153
},
152154
// In build, rewrite paths to ESM imported images in code to their final location
153155
async renderChunk(code) {
154-
const assetUrlRE = /__ASTRO_ASSET_IMAGE__([\w$]{8})__(?:_(.*?)__)?/g;
156+
const assetUrlRE = /__ASTRO_ASSET_IMAGE__([\w$]+)__(?:_(.*?)__)?/g;
155157

156158
let match;
157159
let s;
@@ -205,7 +207,7 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
205207
return;
206208
}
207209

208-
const emitFile = shouldEmitFile ? this.emitFile : undefined;
210+
const emitFile = shouldEmitFile ? this.emitFile.bind(this) : undefined;
209211
const imageMetadata = await emitESMImage(
210212
id,
211213
this.meta.watchMode,
@@ -223,20 +225,24 @@ export default function assets({ settings }: { settings: AstroSettings }): vite.
223225
if (settings.config.experimental.svg && /\.svg$/.test(id)) {
224226
const { contents, ...metadata } = imageMetadata;
225227
// We know that the contents are present, as we only emit this property for SVG files
226-
return makeSvgComponent(metadata, contents!);
228+
return { code: makeSvgComponent(metadata, contents!) };
227229
}
228230

229231
// We can only reliably determine if an image is used on the server, as we need to track its usage throughout the entire build.
230232
// Since you cannot use image optimization on the client anyway, it's safe to assume that if the user imported
231233
// an image on the client, it should be present in the final build.
232234
if (options?.ssr) {
233-
return `export default ${getProxyCode(
234-
imageMetadata,
235-
settings.buildOutput === 'server',
236-
)}`;
235+
return {
236+
code: `export default ${getProxyCode(
237+
imageMetadata,
238+
settings.buildOutput === 'server',
239+
)}`,
240+
};
237241
} else {
238242
globalThis.astroAsset.referencedImages.add(imageMetadata.fsPath);
239-
return `export default ${JSON.stringify(imageMetadata)}`;
243+
return {
244+
code: `export default ${JSON.stringify(imageMetadata)}`,
245+
};
240246
}
241247
}
242248
},

packages/astro/src/content/vite-plugin-content-virtual-mod.ts

+11-9
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ export function astroContentVirtualModPlugin({
141141
}
142142
if (id === RESOLVED_DATA_STORE_VIRTUAL_ID) {
143143
if (!fs.existsSync(dataStoreFile)) {
144-
return 'export default new Map()';
144+
return { code: 'export default new Map()' };
145145
}
146146
const jsonData = await fs.promises.readFile(dataStoreFile, 'utf-8');
147147

@@ -161,18 +161,20 @@ export function astroContentVirtualModPlugin({
161161

162162
if (id === ASSET_IMPORTS_RESOLVED_STUB_ID) {
163163
const assetImportsFile = new URL(ASSET_IMPORTS_FILE, settings.dotAstroDir);
164-
if (!fs.existsSync(assetImportsFile)) {
165-
return 'export default new Map()';
166-
}
167-
return fs.readFileSync(assetImportsFile, 'utf-8');
164+
return {
165+
code: fs.existsSync(assetImportsFile)
166+
? fs.readFileSync(assetImportsFile, 'utf-8')
167+
: 'export default new Map()',
168+
};
168169
}
169170

170171
if (id === MODULES_MJS_VIRTUAL_ID) {
171172
const modules = new URL(MODULES_IMPORTS_FILE, settings.dotAstroDir);
172-
if (!fs.existsSync(modules)) {
173-
return 'export default new Map()';
174-
}
175-
return fs.readFileSync(modules, 'utf-8');
173+
return {
174+
code: fs.existsSync(modules)
175+
? fs.readFileSync(modules, 'utf-8')
176+
: 'export default new Map()',
177+
};
176178
}
177179
},
178180

packages/astro/src/core/build/plugins/plugin-component-entry.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ export function vitePluginComponentEntry(internals: BuildInternals): VitePlugin
6464
const componentId = id.slice(astroEntryPrefix.length);
6565
const exportNames = componentToExportNames.get(componentId);
6666
if (exportNames) {
67-
return `export { ${exportNames.join(', ')} } from ${JSON.stringify(componentId)}`;
67+
return {
68+
code: `export { ${exportNames.join(', ')} } from ${JSON.stringify(componentId)}`,
69+
};
6870
}
6971
}
7072
},

packages/astro/src/core/build/plugins/plugin-manifest.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function vitePluginManifest(options: StaticBuildOptions, internals: BuildInterna
6363
];
6464
const exports = [`export { manifest }`];
6565

66-
return [...imports, ...contents, ...exports].join('\n');
66+
return { code: [...imports, ...contents, ...exports].join('\n') };
6767
}
6868
},
6969

packages/astro/src/core/build/plugins/plugin-pages.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function vitePluginPages(opts: StaticBuildOptions, internals: BuildInternals): V
5050
imports.push(`import { renderers } from "${RENDERERS_MODULE_ID}";`);
5151
exports.push(`export { renderers };`);
5252

53-
return `${imports.join('\n')}${exports.join('\n')}`;
53+
return { code: `${imports.join('\n')}${exports.join('\n')}` };
5454
}
5555
}
5656
}

packages/astro/src/core/build/plugins/plugin-prerender.ts

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ function getNonPrerenderOnlyChunks(bundle: Rollup.OutputBundle, internals: Build
5757

5858
nonPrerenderOnlyEntryChunks.add(chunk);
5959
}
60+
if (chunk.type === 'chunk' && chunk.isDynamicEntry) {
61+
nonPrerenderOnlyEntryChunks.add(chunk);
62+
}
6063
}
6164

6265
// From the `nonPrerenderedEntryChunks`, we crawl all the imports/dynamicImports to find all

packages/astro/src/core/build/plugins/plugin-renderers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ export function vitePluginRenderers(opts: StaticBuildOptions): VitePlugin {
3737

3838
exports.push(`export const renderers = [${rendererItems}];`);
3939

40-
return `${imports.join('\n')}\n${exports.join('\n')}`;
40+
return { code: `${imports.join('\n')}\n${exports.join('\n')}` };
4141
} else {
42-
return `export const renderers = [];`;
42+
return { code: `export const renderers = [];` };
4343
}
4444
}
4545
},

packages/astro/src/core/build/plugins/plugin-ssr.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function vitePluginAdapter(adapter: AstroAdapter): VitePlugin {
3030
},
3131
async load(id) {
3232
if (id === RESOLVED_ADAPTER_VIRTUAL_MODULE_ID) {
33-
return `export * from ${JSON.stringify(adapter.serverEntrypoint)};`;
33+
return { code: `export * from ${JSON.stringify(adapter.serverEntrypoint)};` };
3434
}
3535
},
3636
};
@@ -103,7 +103,7 @@ function vitePluginSSR(
103103
const ssrCode = generateSSRCode(adapter, middleware!.id);
104104
imports.push(...ssrCode.imports);
105105
contents.push(...ssrCode.contents);
106-
return [...imports, ...contents, ...exports].join('\n');
106+
return { code: [...imports, ...contents, ...exports].join('\n') };
107107
}
108108
},
109109
async generateBundle(_opts, bundle) {

packages/astro/src/core/middleware/vite-plugin.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export function vitePluginMiddleware({ settings }: { settings: AstroSettings }):
4444
if (!userMiddlewareIsPresent && settings.config.i18n?.routing === 'manual') {
4545
throw new AstroError(MissingMiddlewareForInternationalization);
4646
}
47-
return 'export const onRequest = (_, next) => next()';
47+
return { code: 'export const onRequest = (_, next) => next()' };
4848
} else if (id === MIDDLEWARE_MODULE_ID) {
4949
if (!userMiddlewareIsPresent && settings.config.i18n?.routing === 'manual') {
5050
throw new AstroError(MissingMiddlewareForInternationalization);
@@ -53,7 +53,7 @@ export function vitePluginMiddleware({ settings }: { settings: AstroSettings }):
5353
const preMiddleware = createMiddlewareImports(settings.middlewares.pre, 'pre');
5454
const postMiddleware = createMiddlewareImports(settings.middlewares.post, 'post');
5555

56-
const source = `
56+
const code = `
5757
${
5858
userMiddlewareIsPresent
5959
? `import { onRequest as userOnRequest } from '${resolvedMiddlewareId}';`
@@ -69,7 +69,7 @@ export const onRequest = sequence(
6969
);
7070
`.trim();
7171

72-
return source;
72+
return { code };
7373
}
7474
},
7575
};

packages/astro/src/core/server-islands/vite-plugin-server-islands.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function vitePluginServerIslands({ settings, logger }: AstroPluginOptions
2727
},
2828
load(id) {
2929
if (id === RESOLVED_VIRTUAL_ISLAND_MAP_ID) {
30-
return `export const serverIslandMap = ${serverIslandPlaceholder};`;
30+
return { code: `export const serverIslandMap = ${serverIslandPlaceholder};` };
3131
}
3232
},
3333
transform(_code, id) {

packages/astro/src/env/vite-plugin-env.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ export function astroEnv({ settings, sync, envLoader }: AstroEnvPluginParams): P
7272
load(id, options) {
7373
if (id === resolveVirtualModuleId(VIRTUAL_MODULES_IDS.client)) {
7474
ensureTemplateAreLoaded();
75-
return templates!.client;
75+
return { code: templates!.client };
7676
}
7777
if (id === resolveVirtualModuleId(VIRTUAL_MODULES_IDS.server)) {
7878
if (options?.ssr) {
7979
ensureTemplateAreLoaded();
80-
return templates!.server;
80+
return { code: templates!.server };
8181
}
8282
throw new AstroError({
8383
...AstroErrorData.ServerOnlyModule,
@@ -86,7 +86,7 @@ export function astroEnv({ settings, sync, envLoader }: AstroEnvPluginParams): P
8686
}
8787
if (id === resolveVirtualModuleId(VIRTUAL_MODULES_IDS.internal)) {
8888
ensureTemplateAreLoaded();
89-
return templates!.internal;
89+
return { code: templates!.internal };
9090
}
9191
},
9292
};

packages/astro/src/manifest/virtual-module.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default function virtualModulePlugin({
4242
});
4343
}
4444
// There's nothing wrong about using `/client` on the server
45-
return `${serializeClientConfig(manifest)};`;
45+
return { code: serializeClientConfig(manifest) };
4646
}
4747
// server
4848
else if (id == RESOLVED_VIRTUAL_SERVER_ID) {
@@ -58,7 +58,7 @@ export default function virtualModulePlugin({
5858
message: AstroErrorData.ServerOnlyModule.message(VIRTUAL_SERVER_ID),
5959
});
6060
}
61-
return `${serializeServerConfig(manifest)};`;
61+
return { code: serializeServerConfig(manifest) };
6262
}
6363
},
6464
};

packages/astro/src/prefetch/vite-plugin-prefetch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default function astroPrefetch({ settings }: { settings: AstroSettings })
4040
load(id) {
4141
if (id === resolvedVirtualModuleId) {
4242
if (!prefetch) throwPrefetchNotEnabledError();
43-
return `export { prefetch } from "astro/virtual-modules/prefetch.js";`;
43+
return { code: `export { prefetch } from "astro/virtual-modules/prefetch.js";` };
4444
}
4545
},
4646
transform(code, id) {

0 commit comments

Comments
 (0)