Files
fusion/docs/solutions/integration-issues/bundled-plugin-vite-alias-missing.md
gsxdsm 7cfc2168a2 FN-6111: alias bundled plugin views to source entries
Keep bundled plugin dashboard views loading from source so Compound Engineering no longer falls back to the unavailable placeholder.

- switch bundled dependency graph, roadmap, and compound engineering dashboard view loaders to static literal imports
- add vitest aliases for dependency graph and compound engineering dashboard view source entrypoints and cover the alias contract with regression tests
- document the missing-alias failure mode and the static-import requirement for bundled dashboard views

Files changed:
 .../bundled-plugin-vite-alias-missing.md            | 20 +++++++++++---------
 .../__tests__/registerBundledPluginViews.test.tsx   | 10 +++++++--
 .../app/plugins/registerBundledPluginViews.ts       | 19 +++++-------------
 .../runtime-plugin-alias-regression.test.ts         | 21 ++++++++++++++------
 packages/dashboard/vitest.config.ts                 |  8 ++++++++
 5 files changed, 49 insertions(+), 29 deletions(-)

Fusion-Task-Id: FN-6111

Fusion-Task-Lineage: a41b893c-4c14-4a2d-b0c9-47e1dbd0e1ef
2026-06-09 12:51:20 -07:00

6.6 KiB

title, date, category, module, problem_type, component, symptoms, root_cause, resolution_type, severity, tags
title date category module problem_type component symptoms root_cause resolution_type severity tags
Bundled plugin dashboard views fail to load when Vite alias is missing 2026-06-06 integration-issues plugins integration_issue tooling
Plugin fails to enable with: Unknown file extension ".css" for /path/to/PluginView.css
Dynamic import of bundled plugin view returns 404 or module not found
Bundled plugin view unavailable: @fusion-plugin-examples/compound-engineering/dashboard-view#CompoundEngineeringDashboardView
Plugin works in its own package build but fails when loaded by the dashboard
incomplete_setup config_change medium
plugins
bundled-plugins
vite
alias
dashboard-view
registration-drift
css-loader

Bundled plugin dashboard views fail to load when Vite alias is missing

Problem

When a bundled plugin exports a dashboard view, the dashboard lazy-loads it via registerBundledPluginViews.ts. For this to work, the dashboard's Vite and Vitest configurations must include resolve.alias entries that map the plugin's package name to its source directory, and the loader's import() call must use a static string literal so Vite can emit a bundled lazy chunk. Without the alias or static import, Vite cannot resolve or bundle the view module, and the plugin view fails to load.

The error message can be misleading: Vite may report Unknown file extension ".css" because module resolution fails and the error bubbles up through an unrelated loader path. In production, a /* @vite-ignore */ dynamic import can instead surface as the dashboard placeholder: Bundled plugin view unavailable: <module>#<export>.

Symptoms

  • The Compound Engineering plugin (or any bundled plugin with a dashboard view) fails to enable
  • Console shows: Failed to enable Compound Engineering: Unknown file extension ".css" for /path/to/PluginView.css
  • The plugin's own package builds successfully — the issue only manifests when the dashboard tries to load it
  • Other bundled plugins (e.g., dependency-graph) load correctly — they have aliases and static literal import() loaders

What Didn't Work

  • Investigating CSS loader configuration — the .css error is a red herring; the real issue is module resolution
  • Checking the plugin's package.json exports — they were correct ("./dashboard-view" → "./src/dashboard-view.tsx")
  • Verifying the plugin's CSS file exists and is valid — it was fine

Solution

Add the missing resolve.alias entries to both packages/dashboard/vite.config.ts and packages/dashboard/vitest.config.ts:

// packages/dashboard/vite.config.ts
export default defineConfig({
  // ...
  resolve: {
    alias: {
      // ... existing aliases ...
      "@fusion-plugin-examples/compound-engineering/dashboard-view": resolve(
        __dirname,
        "../../plugins/fusion-plugin-compound-engineering/src/dashboard-view.tsx",
      ),
      "@fusion-plugin-examples/compound-engineering": resolve(
        __dirname,
        "../../plugins/fusion-plugin-compound-engineering/src/index.ts",
      ),
      // ... other plugin aliases ...
    },
  },
});

Both aliases are needed:

  • The /dashboard-view alias resolves the view component import
  • The package root alias resolves any internal imports the view makes to the plugin's index

Why This Works

The dashboard should use statically analyzable literal imports for bundled plugin views:

// packages/dashboard/app/plugins/registerBundledPluginViews.ts
const mod = await import("@fusion-plugin-examples/compound-engineering/dashboard-view");

Vite can trace a literal import() through resolve.alias, include the aliased source file in the build graph, and emit a code-split chunk for the lazy view. A /* @vite-ignore */ import using a dynamic module ID prevents this analysis; production browsers then try to resolve the bare package specifier at runtime and the dashboard falls back to the "Bundled plugin view unavailable" placeholder. 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. Some failures surface through the CSS loader because Vite's fallback resolution path misattributes the failure.

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:

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 packages/dashboard/vitest.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
  • Use a static string literal import() in registerBundledPluginViews.ts for bundled dashboard views that should be code-split by Vite; avoid /* @vite-ignore */ unless the task explicitly requires runtime-only resolution
  • Verify the alias in dev, production builds, and Vitest — the alias must resolve correctly for Vite's dev server, production bundler, and test runner
  • 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; when Node reports it while enabling a plugin, suspect a server-entry re-export of the dashboard view
  • docs/solutions/integration-issues/bundled-plugin-registration-drift.md — the broader registration-drift problem (4 independent lists for bundled plugins); this doc covers a fifth implicit registration point (Vite aliases)
  • PR #1464 — the fix for the Compound Engineering alias