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.json → server.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
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-angularand@analogjs/vitest-angularinstalled 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:Changes required:
vite.config.tsfor the app build (Analog plugin withssr: false)proxy.conf.json→server.proxyinvite.config.tsfileReplacementsoption orVITE_*env vars@angular/service-worker(ngsw) withvite-plugin-pwa(Workbox-based)styles.css,material.scss) inindex.htmlinstead ofangular.jsonOutcome: 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:
package.jsonto each of the 7 libs (auth,counter,home,login,shared,todo,weather-forecast) so Vite Task can derive ordering from workspace dependenciesvp migrate --no-interactivefrom workspace root — rewrites Vitest imports tovite-plus/test, merges configsnx.json+project.jsonlint/test targets withrun.tasksinvite.config.ts.NETNx executors (tools/builders/dotnet-builder) withvp runtask definitions callingdotnetCLI directlynxViteTsPaths()withvite-tsconfig-pathsplugin (same behaviour, no Nx dependency)@nx/enforce-module-boundariesESLint rule for a convention-only approach (small project; TS path aliases already enforce boundaries)nx affectedwith--filter+ agit diff-based shell scriptToolchain delta:
@angular/build:application@analogjs/platform@nx/*packagesvite-plusnx.json+ 9×project.jsonvite.config.ts@angular/service-workervite-plugin-pwangx-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.mdat runtime viangx-markdown. With@analogjs/content, markdown is processed at build time with frontmatter support and optional syntax highlighting (Prism or Shiki).A page component becomes:
Eliminates the
/assets/home.mdHTTP fetch at runtime and dropsngx-markdownas a dependency.File-based routing
Analog supports
src/app/pages/*.page.tsfilesystem routing — a route per file with noRoutesarray to maintain. Existing lazy-loaded module routes can be migrated incrementally usingwithExtraRoutes()to mix old and new.Route-level meta tags
Frontmatter in content pages maps directly to
<meta>tags viaRouteMetaresolvers — 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
vp dev,vp build,vp testall pass for the Angular app with Analog buildvp run, lint via Oxlint, format via Oxfmt@analogjs/content(build-time) instead ofngx-markdown(runtime fetch)ngx-markdowndependency removed.mdinsrc/content/