FN-6085: avoid dashboard CSS import in plugin entry
Prevent the Compound Engineering plugin from pulling dashboard CSS into Node-side plugin loading. - remove the dashboard view re-export from the Compound Engineering plugin server entry - document the CSS-import failure mode caused by server-side index re-exports of dashboard views - update bundled plugin registration guidance to keep dashboard view loading client-only Files changed: docs/solutions/integration-issues/bundled-plugin-registration-drift.md | 4 ++-- docs/solutions/integration-issues/bundled-plugin-vite-alias-missing.md | 13 ++++++++++++- plugins/fusion-plugin-compound-engineering/src/index.ts | 1 - 3 files changed, 14 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-6085 Fusion-Task-Lineage: 38e6d4de-18ff-4f7b-9ea4-39b0653b4cce
This commit is contained in:
@@ -29,7 +29,7 @@ The four registration points:
|
||||
3. **CLI startup** — `BUNDLED_PLUGIN_IDS` in `packages/cli/src/plugins/bundled-plugin-install.ts` (auto-install/upgrade of bundled plugins)
|
||||
4. **Build staging** — `packages/cli/tsup.config.ts` (`bundlePluginEntry` or a copy block staging the plugin into `dist/plugins/<id>/` so packaged installs have a copy at all)
|
||||
|
||||
A plugin with a dashboard view additionally needs client-side view registration in `packages/dashboard/app/plugins/registerBundledPluginViews.ts`.
|
||||
A plugin with a dashboard view additionally needs client-side view registration in `packages/dashboard/app/plugins/registerBundledPluginViews.ts`. Its dashboard view component must **not** be re-exported from the plugin's server-side `src/index.ts`; keep only the `dashboardViews` manifest metadata there so Node-side plugin loading does not chase React/CSS imports.
|
||||
|
||||
## Symptoms
|
||||
|
||||
@@ -78,7 +78,7 @@ The Settings card sends a relative `./plugins/<id>` path. The server resolves it
|
||||
|
||||
## Prevention
|
||||
|
||||
- **When adding a bundled plugin, grep for an existing one** (e.g. `rg -l "fusion-plugin-roadmap" packages/` ) and mirror every hit — that surfaces all four lists plus view registration.
|
||||
- **When adding a bundled plugin, grep for an existing one** (e.g. `rg -l "fusion-plugin-roadmap" packages/` ) and mirror every hit — that surfaces all four lists plus view registration. If the plugin has a dashboard view, keep the view load path client-only and do not re-export the view component from the server entry.
|
||||
- Route tests must force the fallback: mock fs so the cwd-relative path **misses** and only `dist/plugins/<id>` exists (see "installs bundled compound engineering plugin when relative path misses cwd" in `packages/dashboard/src/__tests__/plugin-routes.test.ts`). A mock that matches any path containing the plugin id tests nothing.
|
||||
- **Pin assertions to the exact contract, not substring containment.** `stringContaining(pluginId)` passed for both the correct entry-file path and the buggy directory path — when a mock or matcher can satisfy both the correct and the buggy value, the test proves nothing. Route tests now assert the registered path ends in an entry-file suffix, cover the `dist/index.js` and `src/index.ts` fallbacks, and the 400 no-entry branch.
|
||||
- When duplicating a helper is forced by test infrastructure (fs mocks vs externalized deps), add a real-fs drift-guard test that runs every copy against the same on-disk fixtures and asserts identical output.
|
||||
|
||||
@@ -76,12 +76,23 @@ const mod = await import(/* @vite-ignore */ moduleId);
|
||||
|
||||
Vite's static analysis cannot trace these imports, so it relies on `resolve.alias` to map the module ID to a filesystem path. Without the alias, Vite falls through to default resolution, which fails because the plugin package is in a sibling `plugins/` directory outside the dashboard's root. The error surfaces through the CSS loader because Vite's fallback resolution path misattributes the failure.
|
||||
|
||||
## Related root cause: CSS import via index re-export
|
||||
|
||||
The same `Unknown file extension ".css"` symptom can also happen when a plugin's **server-side entry** (`src/index.ts` / `dist/index.js`) re-exports its dashboard view component:
|
||||
|
||||
```ts
|
||||
export { SomeDashboardView } from "./dashboard-view.js";
|
||||
```
|
||||
|
||||
Server-side plugin loading uses Node.js `import()` against the plugin entry. If that entry re-exports a React dashboard view, Node follows the chain into the view and any imported `.css` files before Vite is involved, then crashes because the Node ESM loader does not handle CSS. The fix is to keep dashboard view components out of the server entry: preserve the `dashboardViews` manifest metadata (`componentPath: "./dashboard-view"`) and load the view client-side through `registerBundledPluginViews.ts` plus the Vite alias.
|
||||
|
||||
## Prevention
|
||||
|
||||
- **When adding a bundled plugin with a dashboard view, grep for an existing plugin alias** in `packages/dashboard/vite.config.ts` and mirror the pattern for the new plugin
|
||||
- **Do not re-export dashboard view components from the plugin's server-side `index.ts`** — the server entry must stay free of React/CSS view imports; `dashboardViews` metadata is enough for registration
|
||||
- **Verify the alias in both dev and production builds** — the alias must resolve correctly for Vite's dev server and its production bundler
|
||||
- **Consider a consistency test** that asserts every plugin registered in `registerBundledPluginViews.ts` has a corresponding Vite alias (similar to the existing `lazy-loaded-views-docs.test.ts` that keeps the AGENTS.md view inventory in sync)
|
||||
- **Watch for the misleading `.css` error** — when Vite reports an unknown file extension for a file that clearly exists, suspect module resolution failure before investigating loaders
|
||||
- **Watch for the misleading `.css` error** — when Vite reports an unknown file extension for a file that clearly exists, suspect module resolution failure before investigating loaders; when Node reports it while enabling a plugin, suspect a server-entry re-export of the dashboard view
|
||||
|
||||
## Related Issues
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import { reconcileCePipelines } from "./sync/reconciler.js";
|
||||
import { settingsSchema } from "./settings.js";
|
||||
import { getReconcileOnHooks } from "./settings.js";
|
||||
|
||||
export { CompoundEngineeringDashboardView } from "./dashboard-view.js";
|
||||
export { COMPOUND_ENGINEERING_SKILLS } from "./skills.js";
|
||||
export {
|
||||
installBundledCeSkills,
|
||||
|
||||
Reference in New Issue
Block a user