Skip to content

[AnalogJS v3] RFC: Nitro-style Vite plugin interop hooks for Analog compilation #2254

Description

@benpsnyder

Summary

The stylesheet pipeline work exposed a broader architectural question: how should Analog let external Vite plugins participate in framework compilation without turning @analogjs/vite-plugin-angular into the owner of Analog-specific policy or a broad new plugin surface?

Based on review feedback, the direction should be:

  • keep @analogjs/vite-plugin-angular very thin and focused on Angular compilation/resource integration
  • avoid new packages for this work
  • avoid introducing a broad public API that makes this feel like a custom Analog plugin system
  • prefer a model closer to Nitro v3, where ordinary Vite plugins can expose a framework-specific setup hook that the framework picks up and wires into compilation

Research reference:

Problem

Right now, features like stylesheet preprocessing need a seam that plain Vite plugins cannot fully reach on their own because part of the work happens inside Angular compilation/resource loading.

At the same time, we do not want to solve that by:

  • growing @analogjs/vite-plugin-angular into a general Analog extension host
  • introducing new shared packages for one feature
  • inventing a parallel "Analog plugin" ecosystem when normal Vite plugins should remain the primary authoring model

We need a way for Analog compilation to be interoperable with Vite plugins while keeping framework ownership and compiler ownership separated.

Proposed Direction

Use a Nitro-like model:

  • contrib authors still write normal Vite plugins
  • a Vite plugin can optionally expose an analog setup hook
  • Analog discovers those plugins during setup and calls that hook with a narrow framework integration context
  • @analogjs/vite-plugin-angular only consumes the registrations/integration points it needs for Angular compilation

High-level sketch:

import type { Plugin } from 'vite';

export interface AnalogPluginContext {
  registerStylePreprocessor(preprocessor: StylePreprocessor): void;
}

export type AnalogInteropPlugin = Plugin & {
  analog?: {
    setup?(ctx: AnalogPluginContext): void | Promise<void>;
  };
};

The important part is not the exact shape of the API. The important part is the boundary:

  • Vite plugin remains the public extension unit
  • Analog owns only the minimal setup context needed for framework interop
  • Angular compilation stays behind a thin seam in @analogjs/vite-plugin-angular

Initial Scope

The first implementation should stay narrow and solve the current stylesheet case only.

That likely means:

  • @analogjs/platform owns discovery of plugin.analog?.setup(...)
  • @analogjs/platform owns the broader style-pipeline authoring/config surface
  • @analogjs/vite-plugin-angular keeps only:
    • stylesheet preprocessor integration into Angular compilation
    • registry/compiler-host integration
    • minimal wiring needed to apply registered transforms
  • no new packages
  • no generic helper surface exported from @analogjs/vite-plugin-angular

Why This Direction

This keeps the package boundaries aligned with maintainer feedback:

  • Analog policy stays out of @analogjs/vite-plugin-angular
  • contrib authors can integrate through normal Vite plugins instead of a bespoke Analog plugin format
  • framework-specific seams still exist where Vite alone cannot reach Angular compilation internals

It also gives us a path for other future integrations, but without committing to a generalized plugin framework up front.

Open Questions

  • Where should plugin discovery live: entirely in @analogjs/platform, or split between platform and lower-level integrations?
  • What is the smallest useful analog.setup context for the stylesheet case?
  • How should setup ordering interact with normal Vite plugin ordering?
  • How should this behave in dev/HMR when Angular compilation paths do not always provide full stylesheet context?
  • What is the right compatibility story for Vite 6-8?
  • Which future use cases actually justify expanding the setup context beyond styles?

Acceptance Criteria

  • document a Nitro-inspired interop model that uses normal Vite plugins as the extension unit
  • identify the minimal framework-owned setup context needed for stylesheet preprocessing
  • define a package boundary where @analogjs/vite-plugin-angular remains compiler-focused and thin
  • avoid new packages as part of this direction
  • identify what work should stay in the current PR versus what should land as follow-up

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions