Using Ionic 2 with the Angular CLI

The easiest way to create and work on an Ionic project is to use the Ionic CLI.

However Ionic 2 is based on Angular 2, so we could say that an Ionic project is basically an Angular project with the Ionic framework added to it. You don’t have to use the Ionic CLI.

Ionic “the framework” is one thing, and the Ionic CLI is another thing. This is an important distinction that people just starting with Ionic frequently seem to miss.

The Ionic framework is a basically a JavaScript library, available as the ionic-angular npm package, that we can include into our project just like other third party libraries. Well, it’s not just JavaScript, it also contains CSS files and other assets. But it’s not too different from integrating say the Bootstrap framework.

The Ionic CLI on the other hand can be installed as the ionic npm package. It provides the ionic command line tool that can generate, build, and run Ionic projects. It’s a very convenient tool, but again it’s not strictly a requirement for working with Ionic.

In this article I’ll show you how to add the Ionic framework to a “regular” Angular project generated using the Angular CLI. The same instructions should also apply if you want to use one of the many Angular starter projects available on Github, like qdouble/angular-webpack2-starter.

Adding Ionic to your own project structure could be especially useful if you’re working on an application that will not be distributed as a mobile app but only as a mobile website, maybe sharing code with a desktop web app. This scenario also includes Progressive Web Apps, which seem the latest hot topic.

Let’s get started with an example. Assuming you have the Angular CLI installed already, you can generate a new project with

ng new myapp --style=scss

Note that Ionic uses Sass scss files for styles, so we want to enable that option instead of the default css.

At this point we can go into the newly created folder and install the ionic-angular package that – as mentioned – contains the Ionic 2 framework. We also want the ionicons package to be able to use its nifty icons.

cd myapp
npm install --save ionic-angular ionicons

You may get a few warnings such as

npm WARN ionic-angular@2.0.0-rc.2 requires a peer of @angular/common@2.1.1 but none was installed.
npm WARN ionic-angular@2.0.0-rc.2 requires a peer of @angular/compiler@2.1.1 but none was installed.
...

That’s because the ionic-angular package expects specific versions of the Angular packages, that may be different from the latest version installed by ng new. Chances are things would still work even with slightly different versions, but if you (like me) prefer getting rid of all those warnings you can check what peerDependencies are declared by ionic-angular with:

npm view ionic-angular peerDependencies 

and update the versions in package.json accordingly. For example with ionic-angular 2.0.0-rc.2 that means changing all the @angular/* packages to 2.1.1, adding @angular/compiler-cli and @angular/platform-server, and changing zone.js to 0.6.21. Then update the installed versions by running

npm install

You could also remove @angular/router since Ionic provides its own navigation mechanism.

npm uninstall --save @angular/router

Note: you can also see all the changes detailed here as commit diffs in this repository: mirkonasato/ionic2-with-angular-cli.

At this point all the npm warnings should be gone, and you can start the app with

ng serve

The next step to use Ionic in your project is to change src/app/app.module.ts to import the IonicModule instead of Angular’s BrowserModule, and bootstrap IonicApp:

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';

import { AppComponent } from './app.component';

@NgModule({
  imports: [ IonicModule.forRoot(AppComponent) ],
  declarations: [ AppComponent ],
  bootstrap: [ IonicApp ]
})
export class AppModule { }

The IonicApp component has ion-app as its selector, so you also need to modify src/index.html replacing <app-root> with <ion-app>.

At this point the app should still work – as in, display a page showing what’s in src/app/app.component.html – but there will be no visible difference showing that we’re using Ionic.

To benefit from Ionic styles we need to import all the Ionic scss files. This proved to be quite a tricky step to figure out because there isn’t a single file to import, there are dozens of them. I had to look at the ionic-app-scripts source code to see how all those file can be discovered, and wrote a script to generate all the necessary imports. I’ll make your life easier by giving you the generated file.

To keep the project structure somewhat similar to what the Ionic CLI generates, create a src/theme folder, then download and put into that folder these two files: ionic.scss and variables.scss.

Finally include them in build process by editing angular-cli.json to load variables.scss first in the styles inside app:

  "styles": [
    "theme/variables.scss",
    "styles.scss"
  ],

Note that you’ll have to restart ng serve for this change to take effect.

You should now see the page displayed in a different style. variables.scss is where you can customise the Ionic theme by overriding Sass variables.

The final step for having a basic Ionic app is to create a page component, and load it in AppComponent using ion-nav.

To do that create a src/pages folder with a home.page.ts file containing e.g.

import { Component } from '@angular/core';

@Component({
  selector: 'page-home',
  templateUrl: 'home.page.html'
})
export class HomePage {

  message = 'Welcome!';

}

and the corresponding template in home.page.html with a basic Ionic page, including header and content:

<ion-header>
  <ion-navbar>
    <ion-title>Ionic App</ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
  {{ message }}
</ion-content>

Next you can declare your new page in app.module.ts

//...
import { AppComponent } from './app.component';
import { HomePage } from '../pages/home.page';

@NgModule({
  imports: [ IonicModule.forRoot(AppComponent) ],
  declarations: [ AppComponent, HomePage ],
  entryComponents: [ HomePage ],
  bootstrap: [ IonicApp ]
})
export class AppModule { }

Note that all page components need to be added not just to the declarations array like all Angular components, but also as entryComponents. That’s because pages are inserted dynamically into an ion-nav.

To display that page modify app.component.ts to:

import { Component } from '@angular/core';
import { HomePage } from '../pages/home.page';

@Component({
  template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class AppComponent {

  rootPage = HomePage;

}

As you can see it has a simple inline template with an ion-nav with its root set to rootPage, that in turn is set to HomePage. Save that file and voila! You should see a simple Ionic page with a header bar.

You can delete app.component.html and app.compoent.scss since they’re no longer used. If you want page-specific styles you could add a home.page.scss file and reference it in home.page.ts:

@Component({
  selector: 'page-home',
  templateUrl: 'home.page.html',
  styleUrls: [ 'home.page.scss' ]
})
export class HomePage { /*...*/ }

So now you have an initial Ionic app with a single page, and you can add more pages and functionality as needed, working on it just like any other Angular project.


Did you find this article helpful? I’m also preparing a full course on Ionic 2. If you’re interested please Pre-Register Here.

6 thoughts on “Using Ionic 2 with the Angular CLI

  1. Roope Hakulinen says:

    Thank you for this article. I’ve been thinking about the possibility to use Angular CLI for Ionic apps too. What are the up and downsides of using Angular CLI with Ionic. I mean the ionic-app-scripts does provide quite a few things for serving and building Ionic applications. On the other hand Angular CLI seems to be much further on stability and performance. Any thoughts on this matter? Bundle size? Build times? Development experience (debugging for example?)?

    While we are on the topic, I’ll share the thoughts about this in general too. I do think that it would be extremely nice to have Ionic support somehow baked into the CLI along with support for Electron. What I would like to see is the possibility to like really easily use one codebase as a basis for all platforms. So far with the usage of Ionic CLI exclusively for Ionic apps it hasn’t been that well possible. Also last time I checked the status of component-scoped CSS on Ionic, it was told that they will retain as they now are, so no support for styleUrls which doesn’t seem like a good idea to me. This I haven’t checked for a while now, though.

    Anyway, thank you again for this post, and hope to hear some of your further thoughts on the subject. 🙂

    Like

    • mirkonasato says:

      In general if you want to create a typical Ionic app I think the Ionic CLI is the best option.

      Recent versions of the ionic-app-scripts use Webpack 2 by default, just like the Angular CLI, so I don’t think there’s much difference in terms of build size and time.

      Component-scoped styles using styleUrls is indeed one advantage of the approach proposed in this article. The Ionic approach is that e.g. HomePage has selector “page-home” and all rules in home.scss are nested inside “page-home”, so effectively you get component-scoped styles that way. But I’m not sure why they opted for that approach.

      Something that’s still not clear with the Ionic CLI at present is what’s the best way to package a mobile website / PWA, so that’s where using the Angular CLI may make sense.

      (With the Ionic CLI you can do “npm run ionic:build” and take what’s generated in “www”, or you can add the Cordova “browser” platform and do “ionic build browser”. Seems like the “browser” platform will be the preferred approach, but they’re still working on this: https://twitter.com/maxlynch/status/799651661681725440)

      My main motivation for this post was actually just to point out that the Ionic CLI is not the only option, that you can add Ionic to an Angular project (almost) like any other third party libraries. And that applies not just to projects generated with the Angular CLI, but also those based on starter repositories or custom set ups.

      I can think of cases where you may want to have full control over your project structure and build process, and that way also be isolated from breaking changes in tools like the Ionic CLI or indeed the Angular CLI.

      It’s basically a trade-off: want an easy set up for typical use cases? Use the CLI. Have some special requirements that don’t fit into the standard workflow? You can set up your own custom project.

      Like

  2. Roope Hakulinen says:

    Thank you for your thoughtful answer.

    Although the both use Webpack 2, there has still been quite some difference in loaders etc. used, and those could potentially have a great effect on the performance from these viewpoints.

    About the PWAs, I’d really hope that Ionic team would clearly tell what is the intended flow for distributing those. But I do feel this has been a more general problem with the Ionic, that it is really hard to figure out this kind of things like what should be used for what problem and why. It has, though, gotten better as Ionic has matured, as one could expect. So looking really much forward for the future of the project.

    Also I do think that it would be nice from the Ionic team to produce some kind of documentation of what ever kind to support the usage with Angular CLI as it is after all the preferred way to do Angular 2 development.

    Anyway, good to hear that other people are also seeing the things the same way as I regarding the Ionic development 🙂

    Like

  3. Lados says:

    Thank you very much for this article!
    I want to use Ionic to develop a PWA which will be mostly run in a browser. So I dont need the mobile cordova stuff that brings the ionic-cli with. (also the angular-cli comes with some nice pre-created testing scripts)
    So I have done all the things you’ve described in this article.
    I can compile my project and start it – and ionic is working, so its fine.
    But after compilation It get the following error two times:
    “WARNING in ./~/ionic-angular/util/ng-module-loader.js
    54:11-36 Critical dependency: the request of a dependency is an expression”

    Do you know why and how I can solve this? I’ve searched for this but I’ve only found solutions where I have to modify the webpack config. But because of I am using angular-cli I don’t have the webpack config.

    Thanks in advance!

    Like

  4. Tobias Kraus says:

    Thank you for your helpful post, but I ran into some problems because they are not correct in your post, or some things changed:

    You wrote:
    > change src/app/app.module.ts to import the IonicModule instead of Angular’s BrowserModule, and bootstrap IonicApp.

    When leaving out BrowserModule from imports, angular-cli will not be able to compile. As in Ionic starter template blank –type=ionic-angular, you need both:

    imports: [
    BrowserModule,
    IonicModule.forRoot(MyApp)
    ],

    And in your [git repository](https://github.com/mirkonasato/ionic2-with-angular-cli) you have a wrong closing tag in src/index.html:

    ion-app gets closed with app-root

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s