Skip to content
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1befb90
feat: plugin hook filters
florian-lefebvre Dec 10, 2025
c383f54
wip
florian-lefebvre Dec 10, 2025
3feb29f
wip
florian-lefebvre Dec 10, 2025
5a5acbb
wip
florian-lefebvre Dec 10, 2025
c37813a
wip
florian-lefebvre Dec 10, 2025
3901a73
wip
florian-lefebvre Dec 10, 2025
fb6e01d
wip
florian-lefebvre Dec 10, 2025
e87df8d
wip
florian-lefebvre Dec 10, 2025
93c8cb2
wip
florian-lefebvre Dec 10, 2025
a3da79c
wip
florian-lefebvre Dec 10, 2025
e95e37e
wip
florian-lefebvre Dec 10, 2025
8f72ee4
wip
florian-lefebvre Dec 10, 2025
db456d0
wip
florian-lefebvre Dec 10, 2025
c76daa3
todos
florian-lefebvre Dec 10, 2025
e5a0b19
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 10, 2025
bf3a9ed
fix
florian-lefebvre Dec 10, 2025
8750f02
fix: vite plugin config alias
florian-lefebvre Dec 10, 2025
8b23c66
feat: load
florian-lefebvre Dec 10, 2025
ecbb025
fix: misc
florian-lefebvre Dec 10, 2025
46e78fc
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 10, 2025
e95d8e0
fix: regex
florian-lefebvre Dec 10, 2025
a358b76
fix: regex
florian-lefebvre Dec 10, 2025
da1cacd
fix: regex
florian-lefebvre Dec 10, 2025
6e5f017
fix: regex
florian-lefebvre Dec 11, 2025
4fa4903
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 11, 2025
477d1ab
fix: regex
florian-lefebvre Dec 11, 2025
863606e
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 11, 2025
5870997
fix: regex
florian-lefebvre Dec 11, 2025
3dc7098
improve regex
florian-lefebvre Dec 11, 2025
71a0b26
fix: unsufficient regex
florian-lefebvre Dec 11, 2025
fa7a8db
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 11, 2025
e362a45
chore: format
florian-lefebvre Dec 12, 2025
d0cae56
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 12, 2025
69bcb45
chore: format
florian-lefebvre Dec 12, 2025
dacba07
wip
florian-lefebvre Dec 12, 2025
547f756
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 15, 2025
4c44b63
feat: plugin hook filters (part 2) (#15000)
florian-lefebvre Dec 15, 2025
4c5f2f3
Merge branch 'next' into feat/plugin-hook-filters
florian-lefebvre Dec 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@ const VIRTUAL_MODULE_ID = "virtual:dynamic.css";
const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;

export default {
name: VIRTUAL_MODULE_ID,
resolveId(source) {
if (!source.startsWith(VIRTUAL_MODULE_ID)) return;

return RESOLVED_VIRTUAL_MODULE_ID;
},
load(id) {
if (!id.startsWith(RESOLVED_VIRTUAL_MODULE_ID)) return;

return "body { background: red; }";
},
name: VIRTUAL_MODULE_ID,
resolveId: {
filter: {
id: new RegExp(`^${VIRTUAL_MODULE_ID}$`),
},
handler() {
return RESOLVED_VIRTUAL_MODULE_ID;
},
},
load: {
filter: {
id: new RegExp(`^${RESOLVED_VIRTUAL_MODULE_ID}$`),
},
handler() {
return "body { background: red; }";
},
},
} satisfies Plugin;
88 changes: 49 additions & 39 deletions packages/astro/src/actions/vite-plugin-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,27 +63,30 @@ export function vitePluginActions({
return {
name: VIRTUAL_MODULE_ID,
enforce: 'pre',
async resolveId(id) {
if (id === VIRTUAL_MODULE_ID) {
return RESOLVED_VIRTUAL_MODULE_ID;
}

if (id === OPTIONS_VIRTUAL_MODULE_ID) {
return RESOLVED_OPTIONS_VIRTUAL_MODULE_ID;
}

if (id === ACTIONS_ENTRYPOINT_VIRTUAL_MODULE_ID) {
const resolvedModule = await this.resolve(
`${decodeURI(new URL('actions', settings.config.srcDir).pathname)}`,
);

if (!resolvedModule) {
return RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID;
resolveId: {
filter: {
id: new RegExp(
`^(${VIRTUAL_MODULE_ID}|${OPTIONS_VIRTUAL_MODULE_ID}|${ACTIONS_ENTRYPOINT_VIRTUAL_MODULE_ID})$`,
),
},
async handler(id) {
if (id === VIRTUAL_MODULE_ID) {
return RESOLVED_VIRTUAL_MODULE_ID;
}

resolvedActionsId = resolvedModule.id;
return ACTIONS_RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID;
}
if (id === OPTIONS_VIRTUAL_MODULE_ID) {
return RESOLVED_OPTIONS_VIRTUAL_MODULE_ID;
}
if (id === ACTIONS_ENTRYPOINT_VIRTUAL_MODULE_ID) {
const resolvedModule = await this.resolve(
`${decodeURI(new URL('actions', settings.config.srcDir).pathname)}`,
);
if (!resolvedModule) {
return RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID;
}
resolvedActionsId = resolvedModule.id;
return ACTIONS_RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID;
}
},
},
async configureServer(server) {
const filePresentOnStartup = await isActionsFilePresent(fs, settings.config.srcDir);
Expand All @@ -97,35 +100,42 @@ export function vitePluginActions({
server.watcher.on('add', watcherCallback);
server.watcher.on('change', watcherCallback);
},
async load(id) {
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
if (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
load: {
filter: {
id: new RegExp(
`^(${RESOLVED_VIRTUAL_MODULE_ID}|${RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID}|${ACTIONS_RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID}|${RESOLVED_OPTIONS_VIRTUAL_MODULE_ID})$`,
),
},
async handler(id) {
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
if (this.environment.name === ASTRO_VITE_ENVIRONMENT_NAMES.client) {
return {
code: `export * from 'astro/actions/runtime/entrypoints/client.js';`,
};
}
return {
code: `export * from 'astro/actions/runtime/entrypoints/client.js';`,
code: `export * from 'astro/actions/runtime/entrypoints/server.js';`,
};
}
return {
code: `export * from 'astro/actions/runtime/entrypoints/server.js';`,
};
}

if (id === RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID) {
return { code: 'export const server = {}' };
}
if (id === RESOLVED_NOOP_ENTRYPOINT_VIRTUAL_MODULE_ID) {
return { code: 'export const server = {}' };
}

if (id === ACTIONS_RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID) {
return { code: `export { server } from ${JSON.stringify(resolvedActionsId)};` };
}
if (id === ACTIONS_RESOLVED_ENTRYPOINT_VIRTUAL_MODULE_ID) {
return { code: `export { server } from ${JSON.stringify(resolvedActionsId)};` };
}

if (id === RESOLVED_OPTIONS_VIRTUAL_MODULE_ID) {
return {
code: `
if (id === RESOLVED_OPTIONS_VIRTUAL_MODULE_ID) {
return {
code: `
export const shouldAppendTrailingSlash = ${JSON.stringify(
shouldAppendForwardSlash(settings.config.trailingSlash, settings.config.build.format),
)};
`,
};
}
};
}
},
},
};
}
1 change: 1 addition & 0 deletions packages/astro/src/assets/consts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const VIRTUAL_MODULE_ID = 'astro:assets';
export const RESOLVED_VIRTUAL_MODULE_ID = '\0' + VIRTUAL_MODULE_ID;
export const VIRTUAL_SERVICE_ID = 'virtual:image-service';
export const VALID_INPUT_FORMATS = [
'jpeg',
Expand Down
18 changes: 12 additions & 6 deletions packages/astro/src/assets/fonts/vite-plugin-fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,20 +296,26 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
}
});
},
resolveId(id) {
if (id === VIRTUAL_MODULE_ID) {
resolveId: {
filter: {
id: new RegExp(`^(${VIRTUAL_MODULE_ID})$`),
},
handler() {
return RESOLVED_VIRTUAL_MODULE_ID;
}
},
},
load(id) {
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
load: {
filter: {
id: new RegExp(`^(${RESOLVED_VIRTUAL_MODULE_ID})$`),
},
handler() {
return {
code: `
export const internalConsumableMap = new Map(${JSON.stringify(Array.from(internalConsumableMap?.entries() ?? []))});
export const consumableMap = new Map(${JSON.stringify(Array.from(consumableMap?.entries() ?? []))});
`,
};
}
},
},
async buildEnd() {
if (sync || settings.config.experimental.fonts!.length === 0) {
Expand Down
52 changes: 33 additions & 19 deletions packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ import {
removeQueryString,
} from '../core/path.js';
import { normalizePath } from '../core/viteUtils.js';
import { isAstroServerEnvironment } from '../environments.js';
import type { AstroSettings } from '../types/astro.js';
import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from './consts.js';
import {
RESOLVED_VIRTUAL_MODULE_ID,
VALID_INPUT_FORMATS,
VIRTUAL_MODULE_ID,
VIRTUAL_SERVICE_ID,
} from './consts.js';
import { fontsPlugin } from './fonts/vite-plugin-fonts.js';
import type { ImageTransform } from './types.js';
import { getAssetsPrefix } from './utils/getAssetsPrefix.js';
Expand All @@ -22,9 +28,6 @@ import { emitImageMetadata, hashTransform, propsToFilename } from './utils/node.
import { getProxyCode } from './utils/proxy.js';
import { makeSvgComponent } from './utils/svg.js';
import { createPlaceholderURL, stringifyPlaceholderURL } from './utils/url.js';
import { isAstroServerEnvironment } from '../environments.js';

const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;

const assetRegex = new RegExp(`\\.(${VALID_INPUT_FORMATS.join('|')})`, 'i');
const assetRegexEnds = new RegExp(`\\.(${VALID_INPUT_FORMATS.join('|')})$`, 'i');
Expand Down Expand Up @@ -127,19 +130,27 @@ export default function assets({ fs, settings, sync, logger }: Options): vite.Pl
config(_, env) {
isBuild = env.command === 'build';
},
async resolveId(id, _importer) {
if (id === VIRTUAL_SERVICE_ID) {
if (isAstroServerEnvironment(this.environment)) {
return await this.resolve(settings.config.image.service.entrypoint);
resolveId: {
filter: {
id: new RegExp(`^(${VIRTUAL_SERVICE_ID}|${VIRTUAL_MODULE_ID})$`),
},
async handler(id) {
if (id === VIRTUAL_SERVICE_ID) {
if (isAstroServerEnvironment(this.environment)) {
return await this.resolve(settings.config.image.service.entrypoint);
}
return await this.resolve('astro/assets/services/noop');
}
return await this.resolve('astro/assets/services/noop');
}
if (id === VIRTUAL_MODULE_ID) {
return resolvedVirtualModuleId;
}
if (id === VIRTUAL_MODULE_ID) {
return RESOLVED_VIRTUAL_MODULE_ID;
}
},
},
load(id) {
if (id === resolvedVirtualModuleId) {
load: {
filter: {
id: new RegExp(`^(${RESOLVED_VIRTUAL_MODULE_ID})$`),
},
handler() {
return {
code: `
export { getConfiguredImageService, isLocalService } from "astro/assets";
Expand Down Expand Up @@ -186,7 +197,7 @@ export default function assets({ fs, settings, sync, logger }: Options): vite.Pl
export const getFontData = createGetFontData(fontsMod);
`,
};
}
},
},
buildStart() {
if (!isBuild) return;
Expand Down Expand Up @@ -231,8 +242,11 @@ export default function assets({ fs, settings, sync, logger }: Options): vite.Pl
configResolved(viteConfig) {
resolvedConfig = viteConfig;
},
async load(id) {
if (assetRegex.test(id)) {
load: {
filter: {
id: assetRegex,
},
async handler(id) {
if (!globalThis.astroAsset.referencedImages)
globalThis.astroAsset.referencedImages = new Set();

Expand Down Expand Up @@ -283,7 +297,7 @@ export default function assets({ fs, settings, sync, logger }: Options): vite.Pl
code: `export default ${JSON.stringify(imageMetadata)}`,
};
}
}
},
},
},
fontsPlugin({ settings, sync, logger }),
Expand Down
13 changes: 8 additions & 5 deletions packages/astro/src/container/vite-plugin-container.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type * as vite from 'vite';

const virtualModuleId = 'astro:container';
const VIRTUAL_MODULE_ID = 'astro:container';

export default function astroContainer(): vite.Plugin {
return {
name: 'astro:container',
name: VIRTUAL_MODULE_ID,
enforce: 'pre',
resolveId(id) {
if (id === virtualModuleId) {
resolveId: {
filter: {
id: new RegExp(`^(${VIRTUAL_MODULE_ID})$`),
},
handler() {
return this.resolve('astro/virtual-modules/container.js');
}
},
},
};
}
61 changes: 33 additions & 28 deletions packages/astro/src/content/vite-plugin-content-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,40 +31,45 @@ export function astroContentAssetPropagationPlugin({
return {
name: 'astro:content-asset-propagation',
enforce: 'pre',
async resolveId(id, importer, opts) {
if (hasContentFlag(id, CONTENT_IMAGE_FLAG)) {
const [base, query] = id.split('?');
const params = new URLSearchParams(query);
const importerParam = params.get('importer');
resolveId: {
filter: {
id: new RegExp(`(?:\\?|&)(?:${CONTENT_IMAGE_FLAG}|${CONTENT_RENDER_FLAG})(?:&|=|$)`),
},
async handler(id, importer, opts) {
if (hasContentFlag(id, CONTENT_IMAGE_FLAG)) {
const [base, query] = id.split('?');
const params = new URLSearchParams(query);
const importerParam = params.get('importer');

const importerPath = importerParam
? fileURLToPath(new URL(importerParam, settings.config.root))
: importer;
const importerPath = importerParam
? fileURLToPath(new URL(importerParam, settings.config.root))
: importer;

const resolved = await this.resolve(base, importerPath, { skipSelf: true, ...opts });
if (!resolved) {
throw new AstroError({
...AstroErrorData.ImageNotFound,
message: AstroErrorData.ImageNotFound.message(base),
});
const resolved = await this.resolve(base, importerPath, { skipSelf: true, ...opts });
if (!resolved) {
throw new AstroError({
...AstroErrorData.ImageNotFound,
message: AstroErrorData.ImageNotFound.message(base),
});
}
return resolved;
}
return resolved;
}
if (hasContentFlag(id, CONTENT_RENDER_FLAG)) {
const base = id.split('?')[0];
if (hasContentFlag(id, CONTENT_RENDER_FLAG)) {
const base = id.split('?')[0];

for (const { extensions, handlePropagation = true } of settings.contentEntryTypes) {
if (handlePropagation && extensions.includes(extname(base))) {
return this.resolve(`${base}?${PROPAGATED_ASSET_FLAG}`, importer, {
skipSelf: true,
...opts,
});
for (const { extensions, handlePropagation = true } of settings.contentEntryTypes) {
if (handlePropagation && extensions.includes(extname(base))) {
return this.resolve(`${base}?${PROPAGATED_ASSET_FLAG}`, importer, {
skipSelf: true,
...opts,
});
}
}
// Resolve to the base id (no content flags)
// if Astro doesn't need to handle propagation.
return this.resolve(base, importer, { skipSelf: true, ...opts });
}
// Resolve to the base id (no content flags)
// if Astro doesn't need to handle propagation.
return this.resolve(base, importer, { skipSelf: true, ...opts });
}
},
},
configureServer(server) {
if (!isRunnableDevEnvironment(server.environments[ASTRO_VITE_ENVIRONMENT_NAMES.ssr])) {
Expand Down
Loading
Loading