This post is a collection of things that I had to do/learn to convert an Ionic 3 - Angular 5 app from 2018 to Ionic 5 - Angular 10 in 2020 to solve increasing technical debt going forward as it was the best option versus upgrading version by version. I’m by no means an expert in Angular but I got 5+ years of experience with Ionic and I’ve just gone through the process so if you want to hire me to do it to your app I’m always open to new opportunities
First, make sure you have the latest Cordova and Ionic:
npm i -g ionic
npm i -g cordova
P.S. Check my article on interesting node global packages you should be using
Then, start a new project/app: ionic start [NAME] blank --cordova
Now copy page by page to your new project.
I generated them first using ionic generate page [NAME]
and then copied the class contents to the new class.
By doing this you will notice a few differences like:
[NAME].ts
changed to[NAME].page.ts
[NAME].html
changed to[NAME].page.html
[NAME].scss
changed to[NAME].page.scss
[NAME]-routing.module.ts
is new and contains the route declarations.
- As I just mentioned now there’s an additional
[NAME]-routing.module.ts
file per page which can have additional routes. I opted for keeping all my routes inapp-routing.module.ts
for consistency and ease of use (seeing all app routes at once). - If you had styles in 1 component that another one used but now is not getting them you should move them to
global.scss
file or as a last resort add the.scss
file to thestyleUrls
array of the second component. - Component or pages now specify
styleUrls
each time, unlike before that it would just “magically find it” I guess. 🤔 - Each class
implments OnInit
which is a typescript way to basically declare the shape of your component/page class. I’m pretty confident you can remove those 2 words without causing problems. import { [NAME] } from "ionic-angular";
changed toimport { [NAME] } from "@ionic/angular";
- Decorators/types like
Slides
andContent
“changed location” as well as name. For example:
import { Content, Slides } from "ionic-angular";
// changed to:
import { IonContent, IonSlides } from "@ionic/angular";
@ViewChild(Slides) slides: Slides;
@ViewChild(Content) content: Content;
// changed to:
@ViewChild(IonSlides) slides: IonSlides;
@ViewChild(IonContent) content: IonContent;
- Providers are no longer a thing, they are all called “services” now. A service is something you use to share code or state between components/pages, I for example use a utils service as well as a data-sharing service. If you had a provider you should generate a service using
ionic g service [NAME]
and copy code over to it. ionViewDidLoad
doesn’t exist anymore, you probably want to useionViewWillEnter
instead, more here: https://ionicframework.com/docs/angular/lifecycle or one of the angular lifecycle methods: https://angular.io/guide/lifecycle-hooks- Here are some useful new commands to get a sense of what the new “things are”:
ionic g page [NAME]
ionic g service [NAME]
ionic g component [NAME]
- If you previously used
NavController
to navigate between pages:this.navCtrl.push(XPage, data)
you will have to create your routes first and use the angular router properly and do something likethis.router.navigate(["vocabulary"], { relativeTo: this.route });
, this is the same as the previous:this.navCtrl.push(VocabularyPage, data);
but now you will have to savedata
first using a service and get it back on the other page. Previously was as simple as:navParams.get("cat");
- Pages don’t have the
@IonicPage()
decorator anymore. [centeredSlides]="false"
is not a thing anymore, you can leave it but it will give your warnings. You probably want toion-slide
doesn’t have adiv.slide-zoom
inside and then your content inside it anymore. It’sion-slide
and then your content directly andion-slide
isdisplay: flex;
that means that if you had elements directly inside they will change position, I just wrapped them in a div. The div isdisplay: block
and elements inside will probably go back to the previous place..content { color: $appGrey; }
doesnt work anymore since you have to use the CSS 3? 4? variables, I did it like so:.content { color: $appGrey; --color: none; }
- The same goes for backgrounds and paddings of ion-content:
#menu-page {
background: $appYellow;
font-size: 0;
// https://ionicframework.com/docs/api/content/#css-custom-properties
--background: none;
--padding-top: 16px;
--padding-end: 16px;
--padding-bottom: 16px;
--padding-start: 16px;
}
If you inspect the shadow dom it has a div just for the background, this code sets its background to none
so that it becomes transparent and then sets the outer div background.
- Robot font isn’t as easily available as before:
@import "roboto";
and* { font-family: "Roboto"; }
Now you have to download if from Google Fonts and configure it like so:
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 500;
font-display: swap;
src: local("Roboto Medium"), local("Roboto-Medium"),
url("./assets/fonts/Roboto-Medium.ttf") format("woff2");
}
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 400;
font-display: swap;
src: local("Roboto Regular"), local("Roboto-Regular"),
url("./assets/fonts/Roboto-Regular.ttf") format("woff2");
}
@font-face {
font-family: "Roboto";
font-style: normal;
font-weight: 700;
font-display: swap;
src: local("Roboto Bold"), local("Roboto-Bold"),
url("./assets/fonts/Roboto-Bold.ttf") format("woff2");
}
* {
font-family: "Roboto";
}
- SASS variables aren’t “magically” available to your sass pages/components like before you will need to import them at the top of your SASS like so:
@import "../../theme/variables.scss";
… - If you were using REM or EM sizes for font or paddings, etc your layout changed quite a bit because of that. To fix it set the font size back to 10px, aka 62.5% and ion.app to…
body, html {
// compensate for whatever they changed and the root font isnt 62.5% as before (10px)
font-size: 10px;
font-size: 62.5%;
}
ion-app .md, ion-app .ios {
font-size: 1.4rem;
}
- Paths in SASS files changed:
background-image: url("../assets/imgs/wrong_icon.png");
// to
background-image: url("../../../assets/imgs/wrong_icon.png");
If you have them wrong you will get the following error:
./src/app/games/matching/matching.page.scss
Module Error (from ./node_modules/postcss-loader/src/index.js):
(Emitted value instead of an instance of Error) CssSyntaxError: /home/unknown/git/temp_delete/aviation2/aviation-english/matching.page.scss:58:2: Can't resolve '../assets/imgs/plane.png' in '/home/unknown/git/temp_delete/aviation2/aviation-english/src/app/games/matching'
[navPush]="page"
isnt a thing anymore, instead dorouterLink="/page"
or make a click function and use the Angular router like so:this.router.navigate(["page"], { relativeTo: this.route.parent });
whereprivate router: Router, private route: ActivatedRoute
fromimport { ActivatedRoute, Router } from "@angular/router";
- If you get a similar error message:
NullInjectorError: R3InjectorError(TestPageModule)[Keyboard -> Keyboard -> Keyboard -> Keyboard]: NullInjectorError: No provider for Keyboard!
just go to your app.module.ts and import the given classimport { Keyboard } from "@ionic-native/keyboard/ngx";
and pass it to theproviders
array:providers: [Keyboard]
AlertController
changed fromthis.alertController.create({...}).present();
tothis.alertController.create({...}).then((result) => { result.present(); });
Don’t forget to:
- Add the icon and splash screen into the new project and regenerate the new assets with
cordova-res
orionic cordova resources
. - Copy your signing key, package name and version to generate the same app…
- Copy configuration files like
.editorconfig
,.gitignore
,.prettierrc
,README.md
, etc.
Optional:
- I recommend you remove and re-add the default plugins that come with the new project to update them to the latest version and new way of working with them. (plugins are now stored in
package.json
)
ionic cordova plugin rm cordova-plugin-ionic-webview && ionic cordova plugin add cordova-plugin-ionic-webview
Pro tips:
- Add
--prod
to your release builds to save tuns of space!
ionic cordova build android --release --prod
(My .apk
went from 29MiB to 23MiB!)
- If you are on Linux compress your PNGs using
pngquant
:
find . -name '*.png' -exec pngquant --ext .png --force {} \;
Conclusion:
It’s quite easy to make the necessary changes and took me about 5+ afternoons to “convert” 3 components, 3 services, 13 pages. Performance improved slightly, about 5%. The app size got reduced to 2/3.