The Ionic team has been busy working behind the scenes to finish the release of Ionic 4.x, which we should hopefully see an alpha release of before too long. We’ve talked about the benefits of Ionic 4 in the past. In this article, I want to focus on how the release of Ionic 4 will impact the actual work you need to do in order to keep building applications with Ionic, or upgrade existing ones.
Ionic 4 has not been officially released yet, so please keep in mind that this is not intended to be an upgrade guide and may not be entirely accurate. I am operating off of incomplete information as there is no official documentation yet, and am just piecing together what I know (or at least, what I think I know).
We are going to look at the Ionic 4 release from three different perspectives:
- What options will there be for building Ionic applications moving forward?
- Basic breaking changes that will be introduced in Ionic 4 (e.g. syntax changes like
<button ion-button>
to<ion-button>
) - Broader architectural changes to Ionic/Angular applications (e.g. Navigation, Lazy Loading)
The main goal of this article is to give you the feel of the kinds of changes you can expect. After Ionic 4 is released, I will be updating my Ionic book with a lot more information – anybody who has already purchased the book, or does so at any point before the release, will get the upgrade for free. You can also expect to see some more in-depth blog posts after the release.
Options for Building Applications with Ionic 4.x
The key change in Ionic 4 is that all of Ionic’s components are now web components. This means that rather than being tied specifically to the Angular framework, Ionic can now be used with any framework, or none at all. There has also been the introduction of Ionic’s web component compiler called Stencil. The Ionic team use Stencil to build the Ionic web components, but you can also use Stencil to build your own web components (if you want), and so you could build your entire application through a combination of Ionic web components, and your own web components built with Stencil (removing the need for a framework library completely).
There is a whole lot more we can do with Ionic now. The question then is: do we stick with what we have always been doing to build Ionic applications (Ionic/Angular)? Or do we switch to one of these new options? Is any particular approach better?
I’ve summarised my thoughts on that in this article, but in brief, my opinion is that:
- Ionic/Angular is a good default. Since people have been building Ionic/Angular applications for years, this option has a lot of community support and tooling support. Operating within the Angular framework will help create a well-structured application, and Angular is optimised for mobile.
- Ionic/Stencil may make development a little more difficult, and requires learning new syntax, but is a good option for people looking to really push performance (since no framework libraries need to be included/loaded).
- Ionic/(Any Other Framework) is a good option for people who already have a preference for a framework like React or Vue, but you do miss out on the little bonuses that the
ionic-angular
package provides, and there won’t be as much community support (not yet, at least).
So, for most people, when Ionic 4 is released just keep doing what you are doing. Not much will change. If you’re interested in exploring another approach, go for it!
Basic Syntax Changes
The transition to web components has led to some necessary syntax changes, but these are mostly pretty straight-forward. You can find a list of some example changes here, but keep in mind that this is not a final or official list. For now, just use this as a way to get a sense of the kind of changes you can expect to see. I would not recommend beginning to update any of your applications based on this information.
I am not going to list all of the changes from that document here, but I will give some examples for those of you who don’t intend to read the document. The main point here is that these changes are mostly quite minor.
Buttons
Previously, we would use the ion-button
attribute to turn either an anchor element or a button element into a stylised Ionic button:
<button ion-button (click)="doSomething()">Default Button</button>
<a ion-button href="#"> Default Anchor </a>
In Ionic 4.x, we would do this instead:
<ion-button (click)="doSomething()"> Default Button </ion-button>
<ion-button href="#"> Default Anchor </ion-button>
Attributes
Many attributes have been renamed, but again, these are minor changes. Instead of using icon-right
we would use slot="end"
, instead of just using a large
attribute would use size="large"
, and instead of using full
to make a button full width we would use expand="full"
. These are not all of the attribute changes, but this should illustrate the point.
Color Changes
The default colours have been changed, and some new default colours have also been added:
primary: #3880ff
secondary: #0cd1e8
tertiary: #7044ff
success: #10dc60
warning: #ffce00
danger: #f04141
light: #f4f5f8
medium: #989aa2
dark: #222428
Tappable Items
Previously, we would use a <button>
for list items that we wanted to be tappable, but now we will just add the tappable
attribute to an <ion-item>
:
<ion-item tappable (click)="doSomething()"> Button Item </ion-item>
There are many more changes that I have not mentioned here, but most of them are of a similar nature to the examples I have mentioned.
Architectural Changes
Aside from the simple syntax changes you can expect, there are also some broader architectural changes to the application. Since Ionic and Angular were previously so tightly coupled, there is naturally going to be a bit of turmoil as the two lovers are separated. They are still friends and will continue to work together, but Ionic has gained its independence now and can come and go as it pleases (and it can even get with other frameworks).
What we will have is a more generic way for Ionic to integrate with Angular, rather than having just “Ionic/Angular”. The vast majority of the things we discuss here will just be included by default, so it may not be super important to understand, but it should help to understand these concepts if you do intend to migrate an existing application.
A great way to see what a typical Ionic 4 application might look like, is to take a look at the core-update branch for the Ionic conference application. I will be using some examples from there.
ionic-angular
We will still have the ionic-angular
package that we have been using for a long time, but it plays less of a role now that most of Ionic is just web components. It will now also be called @ionic/angular
. The @ionic/angular
package will still be responsible for providing the following APIs:
- Action Sheet Controller
- Alert Controller
- App
- Events
- Loading Controller
- Menu Controller
- Modal Controller
- Nav Controller
- Platform
- Popover Controller
- Toast Controller
Root Module Changes
The app.module.ts file contains the root module for the application, and in Ionic 4.x there are just a couple of changes:
@NgModule({
imports: [
BrowserModule,
AppRoutingModule,
HttpModule,
IonicAngularModule.forRoot(),
IonicStorageModule.forRoot()
],
declarations: [
AppComponent
],
providers: [
ConferenceData,
InAppBrowser,
SplashScreen,
UserData
],
bootstrap: [AppComponent]
})
The IonicAngularModule is new, but it essentially fills the role of what IonicModule did previously – this is what is responsible for importing the functionality we need from the ionic-angular
package.
The AppRoutingModule is important for the new style of routing available in Ionic 4.x, but we are going to discuss the role of that in the next section.
Angular Routing in Ionic
Ionic 4.x will support Angular routing and lazy loading, which is why the example root module above included an AppRoutingModule
. This is perhaps the only “big” change you will need to make to your Ionic/Angular applications. Although you are not required to use Angular routing (you can continue to use push/pop navigation in Ionic 4.x), you will need to use Angular routing if you want to support lazy loading (as the @IonicPage
decorator will no longer be available). Angular routing will also become the new default, so it would make sense to switch at some point.
The AppRoutingModule
will define routes for the application and it sets up the Angular router module. It might look something like this:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
const routes: Routes = [
{ path: '', redirectTo: '/tutorial', pathMatch: 'full' },
{
path: 'account',
loadChildren: './pages/account/account.module#AccountModule',
},
{
path: 'support',
loadChildren: './pages/support/support.module#SupportModule',
},
{ path: 'login', loadChildren: './pages/login/login.module#LoginModule' },
{ path: 'signup', loadChildren: './pages/signup/signup.module#SignUpModule' },
{
path: 'app',
loadChildren: './pages/tabs-page/tabs-page.module#TabsModule',
},
{
path: 'tutorial',
loadChildren: './pages/tutorial/tutorial.module#TutorialModule',
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
For people who have used Angular by itself in the past, there shouldn’t be anything too surprising here. However, if you have only used Ionic/Angular then you may not be used to this style of navigation. Although it is not clear to me yet, I believe that the traditional push/pop style of navigation will still be available in Ionic 4.x, but you will also now have the option to navigate by routes (I may very well be wrong about this, though).
When using Angular routing, rather than relying on a push/pop style navigation, the URL is used to define “routes”. For example, if the user were to hit:
http://localhost:8100/about
Then the application would look through the defined routes for one that has a path of ‘about’, once the route is found it will then use that to load the appropriate page. There is a little more to it than that, and we are going to get into that in the next section.
Lazy Loading
When setting up the routes, each route has a loadChildren
property that looks like this:
loadChildren: './pages/account/account.module#AccountModule';
Victor Savkin has an excellent article on Angular Router Declarative Lazy Loading that is well worth a read, but the basic idea of loadChildren
is that it enables lazy loading by only loading the necessary components when the route is hit (not before).
As you may notice, each page in the application has its own module file defined (which you would be familiar with if you have used lazy loading in the past), and that module file is then responsible for including the pages own routing module, which would look like this:
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccountPage } from './account';
const routes: Routes = [{ path: '', component: AccountPage }];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class AccountPageRoutingModule {}
The process for loading our account
route goes something like this:
- Find a route that matches the path
account
- Load the specified module on the
loadChildren
property - The module imports the appropriate routing module for that page
- The routing module defines the components required for the page, and supplies it to the Angular router
This is a little bit more complex than the examples we have looked at so far. However, most people will just be following the default configuration, so there won’t be too much work to do as most of it will just be there by default.
For more information on setting up Angular routing, you should take a look at the following tutorials:
- Using Angular Routing with Ionic 4
- Implementing a Master Detail Pattern in Ionic 4 with Angular Routing
- Creating a Tabs Layout with Angular Routing and Ionic 4
- Prevent Access to Pages in Ionic with Angular Route Guards
Page Component Changes
The components for your pages will look pretty much the same as they always have, except for some small changes in the @Component
decorator. Let’s take a look at another example from the Ionic conference application:
@Component({
selector: 'page-account',
templateUrl: 'account.html',
styleUrls: ['./account.scss'],
encapsulation: ViewEncapsulation.None
})
The decorator now includes a property for styleUrls
, which will now be required to link to the appropriate .scss
file that defines the styles for that component. We will also now be able to easily scope the styles for a particular component to just that component. Previously, even though we had a separate .scss
file for each component, we would wrap the styles for the component inside of its own selector:
page-home {
// styles in here
}
This was to ensure that the styles would only impact the component that we were working on. If we didn’t do this, the styles would be applied globally. However, now we would be able to just do this:
p {
color: red;
}
Which will only cause the paragraph tags within that specific component to have this style applied. Another important new concept here is View Encapsulation. For an in-depth explanation of this concept I would recommend reading Shadow DOM strategies in Angular, but again, we will briefly go over the concept now.
The encapsulation
property determines the components use of the Shadow DOM. The Shadow DOM is basically a way to give elements in an application their own private DOM trees that aren’t exposed to the document as a whole, which creates a kind of “black box” for that element. The benefit to this is that you don’t need to worry about these custom elements interfering with the rest of the application. This is one of the basic ideas behind web components in general – creating a custom element that has its own private “workspace”.
We can set the encapsulation
property to one of the following three values:
- ViewEncapsulation.None – Shadow DOM is not used, and styles will not be scoped to just that component
- ViewEncapsulation.Emulated – Shadow DOM is not used, but styles will be scoped to just that component
- ViewEncapsulation.Native – Shadow DOM is used
Summary
This is not intended in any way to be an all-encompassing upgrade guide for Ionic 4, the intent is just to make you familiar with some of the changes that could expect when Ionic 4 is released (which shouldn’t be too far away). Although there may be a few new concepts, some of which may be confusing, the actual changes required are very minimal, and I don’t expect it would take too much effort even to migrate a large application from Ionic 3.x to Ionic 4.x.
For very little effort, we are going to get the performance and other improvements from the massive amount of effort that has been poured into Ionic 4 behind the scenes.