Migrate to the new engine
Move a site from the legacy builders to the new engine. The new engine generates the same pages, with a persistent cache, faster rebuilds and diagnostic codes. A new application that you set up with ng add already uses it (ng update keeps your project on the legacy builders, and a schematic moves it when you are ready. You can roll it back.
Prerequisites
- NgDoc 22.0 with the legacy builders (
Upgrade to 22.0 ). - A clean working tree, so you can review and undo the changes. The schematic warns when it isn't.
- Node.js
>=24.15.0 <25.
1. Preview the migration
The migrate-to-vite schematic moves a project to the new engine in the Vite host, and keeps ng build and ng serve working. Run it with --dry-run first: it prints the files it would change and its report, and writes nothing.
ng g @ng-doc/builder:migrate-to-vite --project <project-name> --dry-runIn an Nx workspace, run nx g @ng-doc/builder:migrate-to-vite with the same options. You can leave out --project when only one project uses the legacy builders.
2. Run the schematic
ng g @ng-doc/builder:migrate-to-vite --project <project-name>It changes the workspace like this:
- Targets:
buildandserverun@ng-doc/builder:vite-applicationand@ng-doc/builder:vite-dev-server(Builders, plugin and CLI [Vite builders] ). The original targets stay asbuild-legacyandserve-legacy. Each build configuration, such asproduction, selects the Vite mode with the same name; without adefaultConfiguration, the target runs the plain options as thedefaultmode.prerender: falsestays off. Angular builders that read the build options, such asextract-i18nandunit-test, now point atbuild-legacy. vite.config.mjs: a new file in the project folder. When the folder already has avite.config.*, for example for Vitest, the file is vite.ng-doc.config.mjs instead, so Vite and Vitest run directly keep loading yours; thebuildandservetargets name NgDoc's file inconfigFile, and the report says so.--vite-configsets another name. The file holds the application of the build target (browser,server,polyfills,styles,assets), the Analog Angular plugin (tsConfig,inlineStyleLanguage,fileReplacements) and the engine settings (Vite host ). Options that differ between configurations, such asfileReplacementsorsourceMap, are selected by the Vite mode.- Server entry: with a
serverentry, the default export ofmain.server.tsis wrapped with, so a page is prerendered once its content is ready.withNgDocContentReady - Dependencies:
vite,@analogjs/vite-plugin-angular,@angular/compilerand@angular/compiler-cliare added with the ranges inBuilders, plugin and CLI [Supported versions] (^8.3.0,^2.8.0,^22.0.0), unlesspackage.jsonalready lists them. Nothing is pinned: npm installs the newest matching releases. Pass--skip-installto install them yourself. A listed package whose installed version (or, before an install, whose range) lies outside the engine's range is kept, and the report says so. Forviteit also tells you to update it withnpm i -D vite@^8.3.0: the Vite engine doesn't start with Vite 7 or earlier (Troubleshooting [NGDOC_VITE_VERSION] ). Any Angular 22 works: the engine uses the project's own@angular/build. - Files:
/.cache/ng-docis added to.gitignore. The legacy generated folder,ng-doc/<project-name>, is deleted once, because the new engine refuses to overwrite files it didn't write (OUTPUT_UNOWNED_COLLISION). The@ng-doc/generatedpath intsconfig.jsonstays as it is. - Legacy targets:
build-legacyandserve-legacyget a generated folder of their own,ng-doc-legacy/ng-doc/<project-name>, which is added to.gitignore. They load ng-doc.config.legacy.ts, which setsoutDir: 'ng-doc-legacy'over your configuration, and compile with tsconfig.app.legacy.json (one pertsConfigof the build target), which maps@ng-doc/generatedthere; their generated assets entry points there too. So both engines can run in turn without touching each other's files. When the schematic can't remap@ng-doc/generated, it leaves the folder shared and the report says how to separate it.
The schematic writes a report to .ng-doc-migration/<project-name>/report.md and prints it. The report lists every option: migrated, dropped because it has no effect under Vite, or left for you to change by hand. Options that need a manual change include scripts, deployUrl, proxyConfig and ssl. An ssr.entry server, such as server.ts, isn't built: the Vite build prerenders every route instead, so deploy the browser folder as a static site.
The schematic changes nothing when it can't migrate the project, and the report says why:
- the build target uses another builder, such as a custom esbuild builder;
- the build target localizes the application (
localize); - the index file isn't named
index.html, orindexisfalse; - the root component can't be found from the browser entry. Pass it with
--root-component src/app/app.ts; - the server entry,
main.server.ts, exports an NgModule (NGDOC_MIGRATE_SERVER_NGMODULE). The Vite build prerenders with a bootstrap function, so export one instead:(context) =>;bootstrapApplication (App,config , context) - the Vite configuration file it would create already exists, such as a vite.ng-doc.config.mjs or the file you named with
--vite-config. Pass another file name with--vite-config; - a target with the name the legacy target would get, such as
build-legacy, already exists.
Running the schematic again is safe: it adds only what is missing, and keeps your edits to the files it created. If the .ng-doc-migration/<project-name> folder is gone, it finds the build-legacy target next to the Vite target and changes nothing.
3. Build and check
Install the dependencies, if you passed
--skip-install.Start the development server with
ng serve, then run a production build withng build. With aserverentry,ng buildalso prerenders every route (Production builds and prerendering ).Compare the pages with the legacy build,
ng run <project-name>:build-legacy. If a build fails, the error starts with a diagnostic code: look it up inTroubleshooting .The Vite targets write
ng-doc/<project-name>and the-legacytargetsng-doc-legacy/ng-doc/<project-name>, so you can switch between them without deleting anything.Delete
node_modules/.cache/ng-docif it exists. The new engine doesn't use it.
To set up the Vite host by hand instead, follow
After migrating
Go through this list before you commit the migration:
- Manual items: open
.ng-doc-migration/<project-name>/report.mdand handle each entry under “Needs a manual change”. The schematic didn't migrate them, so the site can behave differently until you do. - Output folder: the Vite build writes the application to
<outputPath>/browser, whateveroutputPath.browserwas, and with aserverentry the server bundle to<outputPath>/server. Update deploy scripts and CI artifact paths that read the old folder. - Server rendering: with
outputMode: 'server', the Angular server that renders on request isn't built. The build prerenders every route intobrowser/: deploy it as a static site, or keep thebuild-legacytarget for the server. - Vite version: keep
viteon Vite 8 (^8.3.0); updates within Vite 8 are fine. The Vite engine doesn't start with Vite 7 or earlier (Troubleshooting [NGDOC_VITE_VERSION] ). - Legacy targets: keep
ng-doc.config.legacy.tsand thetsconfig.*.legacy.jsonfiles as long as you keepbuild-legacyandserve-legacy, and commit them with the migration;ng-doc-legacy/is generated and ignored. If the report says the legacy targets still shareng-doc/<project-name>, delete that folder before you switch engines (Troubleshooting [OUTPUT_UNOWNED_COLLISION] ). - Vite configuration: if the project folder already had a
vite.config.*, NgDoc's configuration is vite.ng-doc.config.mjs. Run NgDoc throughng serveandng build(or pass--configto Vite);viteandvitestrun directly keep using your own file. - The diff:
ng gformats every file a schematic changed with the workspace's Prettier, so a file can show more changed lines than the schematic's edit. Inmain.server.tsthe schematic adds one import and wraps the default export.
What changes
| Behaviour | Legacy builders | New engine |
|---|---|---|
| Cache | Off unless cache: true | On unless cache: false |
| Cache folder | node_modules/.cache/ng-doc | .cache/ng-doc/<project-name> |
| Generated folder | ng-doc/<project-name> | The same, owned by the new engine |
| Generated assets | An asset entry in the build target | Added by the builder or the Vite plugin |
| Configuration file names | ng-doc.config.ts, .js | Also .mjs and .cjs |
| Configuration search | Starts in the folder of the browser entry file, usually src | Starts in the parent of that folder. Move src/ng-doc.config.ts to the project folder, or set its path explicitly. |
| Errors | Messages | Messages with a diagnostic code ( |
| Progress output | – |
Roll back
ng g @ng-doc/builder:migrate-to-vite --project <project-name> --revertThe revert restores the original build and serve targets and the files the schematic changed, and deletes the files it created, both generated folders and the new engine's cache folder, so the legacy builders start clean in ng-doc/<project-name> again. A file you edited after the migration is kept, and the revert says so; reformatting doesn't count as an edit. It also reports a Vite target you edited, then restores the original. The added dependencies stay. When a -legacy target is missing, the revert stops and changes nothing: restore the target first. It needs the .ng-doc-migration/<project-name> folder: commit it with the migration if you want to keep the revert available. Your version control remains the primary way back.
Known limitations
vite build --watchisn't supported. Use the development server.- Supported platforms: Linux, macOS and Windows, all tested in CI.
Next: