This article explains how to migrate Ionic Angular to Standalone automatically using the official @ionic/angular-standalone-codemods. For background on Ionic Angular Standalone, see the article below.
https://zenn.dev/rdlabo/articles/8beb8c91e7d337
Recommended preparation
@ionic/angular-standalone-codemods uses ts-morph for code transformation. Every transformed file passes through ts-morph, which can change line breaks and indentation beyond the migration itself, producing large diffs. I recommend running a formatter first so you only see meaningful changes. Here is one example.
% npm install -D prettier
% npx prettier --parser typescript --write "./src/**/*.ts" && prettier --parser angular --write "./src/**/*.html"
If you already use Prettier, skip this step.
What is @ionic/angular-standalone-codemods?
@ionic/angular-standalone-codemods is Ionic's official codemod for migrating Ionic Angular to Standalone. Like Angular CLI's ng update, it automatically applies the code changes needed for Standalone.
https://github.com/ionic-team/ionic-angular-standalone-codemods
Running it is simpleβ from your Ionic Angular project root:
% npx @ionic/angular-standalone-codemods
A prompt appears. First you see:
β² β οΈ This utility is experimental. Always review the changes made before committing them to your project. β οΈ
β
β² For manual migration, see the guide at: https://www.ionicframework.com/docs/angular/build-options#migrating-from-modules-to-standalone
Just a confirmation. The tool creates large diffs, so commit your current work before running it. Next:
β Would you like to run this migration as a dry run? No changes will be written to your project.
β β Yes / β No
β
This asks whether to apply changes or preview only (dry run). Choose Yes to preview. Choose No to run the migration for real.
β Please enter the path to your project (default is the current working directory):
β /Users/sakakibara/dev/winecode/app_
Finally it confirms the project path. The default is the current directory, but you can specify another path. Press Enter to run. It finishes in seconds with:
β Project migration at /Users/sakakibara/dev/winecode/app completed successfully.
β
β We recommend reviewing the changes made by this migration and formatting your code (e.g., with Prettier) before committing.
The Standalone migration codemod is done. I recommend formatting again with Prettier and reviewing the Git diff.
% npx prettier --parser typescript --write "./src/**/*.ts" && prettier --parser angular --write "./src/**/*.html"
What changes are applied
0001-migrate-app-module
The first change replaces IonicModule.forRoot in the root NgModule with provideIonicAngular. This is for apps that have not yet moved Angular itself to Standalone.
import { NgModule } from '@angular/core';
- import { IonicModule } from '@ionic/angular';
-
+ import { provideIonicAngular } from '@ionic/angular/standalone';
+
@NgModule({
- imports: [IonicModule.forRoot({ mode: 'md' })]
+ imports: [],
+ providers: [provideIonicAngular({ mode: 'md' })]
})
- export class AppModule {}
+ export class AppModule { }
0002-import-standalone-componen
The second change imports Ionic Standalone components directly, because IonicModule is no longer used.
import { Component } from "@angular/core";
+ import { IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel } from "@ionic/angular/standalone";
@Component({
selector: 'my-component',
...
</ion-list>
</ion-content>
\`,
- standalone: true
- })
+ standalone: true,
+ imports: [IonHeader, IonToolbar, IonTitle, IonContent, IonList, IonItem, IonLabel]
+ })
export class MyComponent { }
IonIcon also changed: instead of referencing files under assets, it uses icons registered with addIcons.
import { Component } from "@angular/core";
+ import { addIcons } from "ionicons";
+ import { logoIonic } from "ionicons/icons";
+ import { IonIcon } from "@ionic/angular/standalone";
@Component({
selector: 'my-component',
template: '<ion-icon name="logo-ionic"></ion-icon>',
- standalone: true
- })
- export class MyComponent { }
+ standalone: true,
+ imports: [IonIcon]
+ })
+ export class MyComponent {
+ constructor() {
+ addIcons({ logoIonic });
+ }
+ }
Icons not registered with addIcons will not display. However, if they were registered elsewhere (stored on the window objectβ in main.ts, another component, or a service), they can still appear. Registering in the component itself keeps the total bundle smallest.
0003-migrate-bootstrap-application / 0006-migrate-angular-app-config
The third change replaces IonicModule.forRoot loaded via importProvidersFrom in bootstrapApplication with provideIonicAngular. This is for apps already on Angular Standalone.
- import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
+ import { IonicRouteStrategy, provideIonicAngular } from '@ionic/angular/standalone';
...
bootstrapApplication(AppComponent, {
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
- importProvidersFrom(IonicModule.forRoot({ mode: 'ios' })),
provideRouter(routes),
+ provideIonicAngular({ mode: 'ios' })
],
});
0004-migrate-import-statements
The fourth change moves every import from @ionic/angular to @ionic/angular/standalone. After migration, imports from @ionic/angular are not usable. Without loading the module, that is expected.
import { Injectable } from '@angular/core';
- import { ModalController } from '@ionic/angular';
+ import { ModalController } from '@ionic/angular/standalone';
@Injectable()
export class MyService {
0005-migrate-angular-json-assets
The fifth change removes copying node_modules/ionicons/dist/ionicons/svg in angular.json. In Ionic Angular Standalone, IonIcon bundles through addIcons, so the assets entry is no longer needed.
architect: {
build: {
options: {
- assets: [
- "src/favicon.ico",
- "src/assets",
- {
- glob: "**/*.svg",
- input: "node_modules/ionicons/dist/ionicons/svg",
- output: "./svg",
- },
- ],
+ assets: ["src/favicon.ico", "src/assets"],
},
},
},
Summary
Inspired by ng update, the Ionic team ships migration tools for major changes (including Capacitor major releases). These tools make Ionic upgrades easier. Give them a try.