Skip to content

Spike: migrate from Nx to Vite+ via Analog.js #147

@chrisjwalk

Description

@chrisjwalk

Overview

Investigate and plan a two-phase migration away from Nx toward a fully Vite-native stack using Analog.js (Angular meta-framework) and Vite+ (unified CLI toolchain).

The project already has @analogjs/vite-plugin-angular and @analogjs/vitest-angular installed for testing — this spike would extend that to the full build pipeline.


Phase 1 — Migrate app build to Analog.js

Replace @angular/build:application (esbuild) with @analogjs/platform (Vite-native). This can be done while still on Nx using the built-in migration generator:

pnpm add -D @analogjs/platform
npx nx generate @analogjs/platform:migrate --project web-app

Changes required:

  • Wire up vite.config.ts for the app build (Analog plugin with ssr: false)
  • Move proxy.conf.jsonserver.proxy in vite.config.ts
  • Migrate environment file replacements (preview config) → Analog fileReplacements option or VITE_* env vars
  • Replace @angular/service-worker (ngsw) with vite-plugin-pwa (Workbox-based)
  • Reference global styles (styles.css, material.scss) in index.html instead of angular.json

Outcome: dev server, build, and tests all run via Vite. Proper HMR for Angular components.


Phase 2 — Migrate off Nx to Vite+

Replace Nx task orchestration, ESLint, and Prettier with Vite+ tooling.

Changes required:

  • Add package.json to each of the 7 libs (auth, counter, home, login, shared, todo, weather-forecast) so Vite Task can derive ordering from workspace dependencies
  • Run vp migrate --no-interactive from workspace root — rewrites Vitest imports to vite-plus/test, merges configs
  • Replace nx.json + project.json lint/test targets with run.tasks in vite.config.ts
  • Replace custom .NET Nx executors (tools/builders/dotnet-builder) with vp run task definitions calling dotnet CLI directly
  • Replace nxViteTsPaths() with vite-tsconfig-paths plugin (same behaviour, no Nx dependency)
  • Swap @nx/enforce-module-boundaries ESLint rule for a convention-only approach (small project; TS path aliases already enforce boundaries)
  • Replace CI's nx affected with --filter + a git diff-based shell script

Toolchain delta:

Removed Replaced by
@angular/build:application @analogjs/platform
All @nx/* packages vite-plus
ESLint + Prettier Oxlint + Oxfmt (Rust-based, ~50–100× faster)
nx.json + 9× project.json single vite.config.ts
@angular/service-worker vite-plugin-pwa
ngx-markdown @analogjs/content (see below)

Analog.js feature opportunities

Beyond the build migration, Analog unlocks several features worth evaluating:

Content pages via markdown (replaces ngx-markdown)

The home page already loads /assets/home.md at runtime via ngx-markdown. With @analogjs/content, markdown is processed at build time with frontmatter support and optional syntax highlighting (Prism or Shiki).

src/
└── content/
    ├── home.md          ← current /assets/home.md moves here
    └── pages/
        └── about.md     ← new static content pages

A page component becomes:

// src/app/pages/(home).page.ts
@Component({
  imports: [MarkdownComponent],  // from @analogjs/content
  template: `
    @if (content$ | async; as page) {
      <analog-markdown [content]="page.content" />
    }
  `,
})
export default class HomePageComponent {
  readonly content$ = injectContent({ customFilename: 'home' });
}

Eliminates the /assets/home.md HTTP fetch at runtime and drops ngx-markdown as a dependency.

File-based routing

Analog supports src/app/pages/*.page.ts filesystem routing — a route per file with no Routes array to maintain. Existing lazy-loaded module routes can be migrated incrementally using withExtraRoutes() to mix old and new.

Route-level meta tags

Frontmatter in content pages maps directly to <meta> tags via RouteMeta resolvers — useful for the home and any future static content pages.

API routes (optional / future)

Analog supports src/server/routes/ API route handlers running on Node/Nitro. Since this project has a .NET API, this is low priority, but worth noting as an option for lightweight server endpoints that don't need .NET.


Acceptance criteria for the spike

  • Phase 1 proven: vp dev, vp build, vp test all pass for the Angular app with Analog build
  • Phase 2 proven: Nx packages removed, all tasks run via vp run, lint via Oxlint, format via Oxfmt
  • Home page markdown served via @analogjs/content (build-time) instead of ngx-markdown (runtime fetch)
  • ngx-markdown dependency removed
  • At least one additional content page added as .md in src/content/
  • CI updated (affected detection, task commands)
  • All existing tests pass

Metadata

Metadata

Assignees

No one assigned

    Labels

    spikeResearch and investigation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions