From 451cbe0b7b029bd56750123a61d8551fbaef7af3 Mon Sep 17 00:00:00 2001 From: Janis Jansen Date: Sat, 3 Oct 2026 14:44:49 +0200 Subject: [PATCH] fioxafix: vite plugin builds --- packages/docs/src/pages/docs/guides/vite.mdx | 3 ++- packages/vite-plugin-surimi/src/plugin.ts | 20 ++++++++++++++--- packages/vite-plugin-surimi/src/runner.ts | 23 ++++++++++++++++++-- packages/vite-plugin-surimi/src/types.ts | 5 +++-- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/docs/src/pages/docs/guides/vite.mdx b/packages/docs/src/pages/docs/guides/vite.mdx index 9de43d5..bf065ac 100644 --- a/packages/docs/src/pages/docs/guides/vite.mdx +++ b/packages/docs/src/pages/docs/guides/vite.mdx @@ -58,7 +58,8 @@ export default defineConfig({ * Decide which of your other Vite plugins run inside surimi's internal * evaluation server. By default every plugin (except surimi's own) is * included, so aliases and custom resolvers keep working inside `.css.ts` - * files. Drop plugins that misbehave in a secondary, websocket-less server. + * files. Only their `resolveId`, `load` and `transform` hooks run there. + * Drop plugins whose transforms misbehave in a secondary server. * default: */ pluginFilter: undefined, diff --git a/packages/vite-plugin-surimi/src/plugin.ts b/packages/vite-plugin-surimi/src/plugin.ts index 5229a1d..3e44c1f 100644 --- a/packages/vite-plugin-surimi/src/plugin.ts +++ b/packages/vite-plugin-surimi/src/plugin.ts @@ -1,6 +1,6 @@ import path from 'node:path'; import type { CompileResult } from '@surimi/compiler'; -import type { EnvironmentModuleGraph, EnvironmentModuleNode, Plugin } from 'vite'; +import type { EnvironmentModuleGraph, EnvironmentModuleNode, Plugin, PluginOption } from 'vite'; import { createFilter } from 'vite'; import { VIRTUAL_CSS_REGEX, VIRTUAL_CSS_SUFFIX, VIRTUAL_SURIMI_PATH_REGEX } from './constants.js'; @@ -41,6 +41,8 @@ export default function surimiPlugin(options: SurimiOptions = {}): Plugin[] { }; const filesWatched = new Set(); + /** Plugins registered by the host (user or framework), as opposed to ones Vite adds internally. */ + let hostPlugins = new Set(); const normalizeDependencyId = (dependencyId: string, ownerId: string): string => { const cleanId = dependencyId.split('?')[0] ?? dependencyId; @@ -69,7 +71,7 @@ export default function surimiPlugin(options: SurimiOptions = {}): Plugin[] { include, exclude, resolvedConfig: ctx.resolvedConfig, - userPlugins: ctx.resolvedConfig.plugins.flat(), + userPlugins: ctx.resolvedConfig.plugins.filter(plugin => hostPlugins.has(plugin)), ...(options.pluginFilter ? { pluginFilter: options.pluginFilter } : {}), }); } @@ -169,7 +171,9 @@ export default function surimiPlugin(options: SurimiOptions = {}): Plugin[] { const corePlugin: Plugin = { name: 'vite-plugin-surimi', - config(config) { + async config(config) { + hostPlugins = await collectPlugins(config.plugins); + if (config.build?.ssr) { return { build: { @@ -347,6 +351,16 @@ export default function surimiPlugin(options: SurimiOptions = {}): Plugin[] { return [corePlugin, createVuePlugin(ctx)]; } +async function collectPlugins(option: PluginOption, into = new Set()): Promise> { + const resolved = await option; + if (Array.isArray(resolved)) { + for (const nested of resolved) await collectPlugins(nested, into); + } else if (resolved) { + into.add(resolved); + } + return into; +} + function collectModulesForInvalidation( fileId: string, moduleGraph: EnvironmentModuleGraph, diff --git a/packages/vite-plugin-surimi/src/runner.ts b/packages/vite-plugin-surimi/src/runner.ts index 34601c5..facd9a8 100644 --- a/packages/vite-plugin-surimi/src/runner.ts +++ b/packages/vite-plugin-surimi/src/runner.ts @@ -44,8 +44,27 @@ function isDevelopmentSurimiFile(id: string): boolean { return DEV_SURIMI_PACKAGES.some(pkgPath => id.includes(pkgPath)); } +const MODULE_PIPELINE_HOOKS = ['resolveId', 'load', 'transform'] as const; + +/** + * Host plugin instances are already configured by the host. Only their module pipeline hooks may run + * here: re-running lifecycle hooks (`config`, `configResolved`, `buildStart`, ...) with this server's + * serve-mode config clobbers their shared state, e.g. Astro's content store flips to its dev path. + */ +function isolateHostPlugin(plugin: Plugin): Plugin { + const isolated: Plugin = { name: plugin.name }; + if (plugin.enforce) isolated.enforce = plugin.enforce; + for (const hook of MODULE_PIPELINE_HOOKS) { + if (plugin[hook]) Object.assign(isolated, { [hook]: plugin[hook] }); + } + return isolated; +} + function filterUserPlugins(plugins: Plugin[], pluginFilter: (plugin: Plugin) => boolean): Plugin[] { - return plugins.flat().filter((plugin): plugin is Plugin => pluginFilter(plugin)); + return plugins + .flat() + .filter((plugin): plugin is Plugin => pluginFilter(plugin)) + .map(isolateHostPlugin); } function createPrefixAliasPlugin(prefixAliases: Record): Plugin { @@ -205,7 +224,7 @@ export class SurimiEvaluator { const hostConfig = this.options.resolvedConfig; const prefixAliases = this.options.prefixAliases; const plugins: Plugin[] = [ - ...filterUserPlugins(this.options.userPlugins ?? hostConfig?.plugins.flat() ?? [], this.pluginFilter), + ...filterUserPlugins(this.options.userPlugins ?? [], this.pluginFilter), ...(prefixAliases && Object.keys(prefixAliases).length > 0 ? [createPrefixAliasPlugin(prefixAliases)] : []), createSurimiCssTsResolvePlugin(), createVirtualSourcesPlugin(this.virtualSources), diff --git a/packages/vite-plugin-surimi/src/types.ts b/packages/vite-plugin-surimi/src/types.ts index 88aff06..a0e5c0b 100644 --- a/packages/vite-plugin-surimi/src/types.ts +++ b/packages/vite-plugin-surimi/src/types.ts @@ -41,8 +41,9 @@ export interface SurimiOptions { /** * Decide which host plugins are seeded into surimi's owned evaluation server. - * The default keeps every plugin except surimi's own. Use this to drop plugins that misbehave - * inside a secondary, websocket-less server (middleware/websocket-dependent plugins, etc.). + * The default keeps every plugin registered by you or your framework except surimi's own (Vite's + * internal plugins are never seeded). Seeded plugins only contribute their `resolveId`, `load` + * and `transform` hooks. Use this to drop plugins whose transforms misbehave there. */ pluginFilter?: (plugin: Plugin) => boolean; }