Skip to content

Create a full and powerful worflow with Ionic (Unit Testing, Environment variables, Automatic documentation, Production App Server, Automatic deployment)

Notifications You must be signed in to change notification settings

ballbrk/ionic-workflow-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ionic-workflow

Create a full and powerful worflow with Ionic

(16 May 2017, Ionic 3.2.1)

Features : Unit Testing, Environment variables, Automatic documentation, Production App Server, Automatic deployment, Dependencies version check

Many code chunks and tutorials are available on the web to configure a Ionic workflow that includes features such as Unit Testing, Environment Variables and others, but most of it are obsolete or depends on specific dependencies, version or configuration that is hard to put together or maintain through time and Ionic core evolution.

There is also tons of starters git repositories but nobody explain how to build their solution from scratch, so that people can understand and implement it in an existing project.

That's why I make this repository. You will find here a step by step guide, where nearly all implementations are versions specific and based on Ionic official repositories, so that this guide will still be consistent 3 months later and can easily be updated with Ionic updates.

====================================================================================

Quickstart

You'll find next a step by step guide, but if you want to make this quick, you can simply clone this repository. It contains the exact code that will be created by following the guide.

git clone https://github.com/RomainFallet/ionic-workflow-guide/

====================================================================================

1. The basics

I'm specifying Git, Node, Npm, Cordova and Ionic-CLI version in case a new version of these packages would break something or add an error/warning in the future. This will ensure that you'll follow this guide in the exact same conditions, but it may work with different versions of these.

1.1 Install Node 7.10.0 and Git 2.13.0

https://nodejs.org/download/release/v7.10.0/

https://git-scm.com/downloads

1.2 Install Npm 4.6.1, Cordova 7.0.1 and Ionic CLI 3.0.0

sudo npm install -g [email protected] [email protected] [email protected]

1.3 Create the project with Ionic 3.2.1 (replace "my-app" by the name you want for your folder)

git clone https://github.com/driftyco/ionic2-app-base ./my-app

cd ./my-app && git reset --hard 49e70da

1.4 Create the file 'src/app/app.module.ts' with this

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';

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

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        IonicModule.forRoot(AppComponent)
    ],
    bootstrap: [IonicApp],
    entryComponents: [
        AppComponent
    ],
    providers: [
        {provide: ErrorHandler, useClass: IonicErrorHandler}
    ]
})
export class AppModule {}

1.5 Create the file 'src/app/app.component.ts' with this

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

@Component({
    templateUrl: 'app.component.html'
})
export class AppComponent {
    rootPage: any;
    
    constructor() {
    }
}

1.6 Create the file 'src/app/app.component.html' with this

<ion-nav [root]="rootPage"></ion-nav>

1.7 Append this to "devDependencies" inside your package.json

"@ionic/cli-plugin-cordova": "1.0.0",
"@ionic/cli-plugin-ionic-angular": "1.0.0"

2. Set up Unit Testing

2.1 Append this to "devDependencies" inside your package.json

"@types/jasmine": "2.5.41",
"@types/node": "7.0.8",
"angular2-template-loader": "0.6.2",
"html-loader": "0.4.5",
"jasmine": "2.5.3",
"jasmine-spec-reporter": "4.1.0",
"karma": "1.5.0",
"karma-chrome-launcher": "2.0.0",
"karma-jasmine": "1.1.0",
"karma-jasmine-html-reporter": "0.2.2",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "2.0.3",
"null-loader": "0.1.1",
"protractor": "5.1.1",
"ts-loader": "2.0.3",
"ts-node": "3.0.2"

2.2 Add Unit Testing conf files (this will add two directories "e2e" and "test-config" in your root folder)

git clone https://github.com/driftyco/ionic-unit-testing-example.git ./tmp

cd ./tmp && git reset --hard 7b1f2a6 && cd ../

cp -r ./tmp/test-config ./

mkdir e2e && cp -r ./tmp/e2e/tsconfig.json ./e2e && rm -rf ./tmp

2.3 Append this to "scripts" inside your "package.json"

"test": "karma start ./test-config/karma.conf.js",
"test-ci": "karma start ./test-config/karma.conf.js --single-run",
"e2e": "webdriver-manager update --standalone false --gecko false; protractor ./test-config/protractor.conf.js"

2.4 Install dependencies

npm install

2.5 Let's add your first test for your AppComponent. Create a new file "src/app.component.spec.ts" and add the following

import { async, TestBed } from '@angular/core/testing';
import { IonicModule } from 'ionic-angular';

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

describe('AppComponent', () => {
    let fixture;
    let component;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [ AppComponent ],
            imports: [
                IonicModule.forRoot(AppComponent)
            ],
            providers: [
            ]
        })
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(AppComponent);
        component = fixture.componentInstance;
    });

    it ('should create a valid instance of AppComponent', () => {
        expect(component instanceof AppComponent).toBe(true);
    });
});

2.6 Run the tests

You can run Unit Tests with :

npm run test

ionic-unit-testing-success

If you need a single run execution, use :

npm run test-ci

To run end to end test (e2e), use :

ionic serve

then :

npm run e2e

2.7 To test a Ionic page, such as "HomePage", use this

import { async, TestBed } from '@angular/core/testing';
import { IonicPageModule, Config } from 'ionic-angular';

import { ConfigMock } from '../../../test-config/mocks-ionic.ts';

import { HomePage } from './home';

describe('HomePage', () => {
    let fixture;
    let component;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [ HomePage ],
            imports: [
                IonicPageModule.forChild(HomePage)
            ],
            providers: [
                { provide: Config, useClass: ConfigMock }
            ]
        })
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(HomePage);
        component = fixture.componentInstance;
    });

    it ('should create a valid instance of HomePage', () => {
        expect(component instanceof HomePage).toBe(true);
    });
});

2.8 To test a custom component, for example "HeaderComponent", use this

import { async, TestBed } from '@angular/core/testing';
import { IonicModule, Config } from 'ionic-angular';

import { ConfigMock } from '../../../test-config/mocks-ionic';

import { HeaderComponent } from './header.component';

describe('HeaderComponent', () => {
    let fixture;
    let component;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [ HeaderComponent ],
            imports: [
                IonicModule
            ],
            providers: [
                { provide: Config, useClass: ConfigMock }
            ]
        })
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(HeaderComponent);
        component = fixture.componentInstance;
    });

    it ('should create a valid instance of HeaderComponent', () => {
        expect(component instanceof HeaderComponent).toBe(true);
    });
});

3. Set up Environment Variables

3.1 Add conf file and Environments Variables json files

git clone https://github.com/RomainFallet/ionic-workflow-guide ./tmp

cp -r ./tmp/{env,webpack.envars.js} ./ && rm -rf ./tmp

3.2 Add this inside your "package.json". This will add your environment variables when you'll use Ionic commands to build or serve your app.

"config": {
  "ionic_webpack": "./webpack.envars.js"
}

3.3 Add this inside your "test-config/karma.conf" to make your environment variables available during your tests.

var envarsConfig = require('../webpack.envars.js');

3.4 To use your ENV global variable, declare it on every file you need it with

declare const ENV: any;

3.5 For example, you can use it that way in your "src/app.component.ts" file (you can add more variables inside your "env/prod.json" and "env/dev.json" files)

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

declare const ENV: any;

@Component({
    templateUrl: 'app.component.html'
})
export class AppComponent {
    rootPage: any;
    
    constructor() {
        console.log('isProduction : ' + ENV.PRODUCTION);
    }
}

If your serve your app now :

ionic serve

You'll see in your browser console :

ionic-envars-serve

3.6 Enable programmatically the Angular production mode by adding this to your "src/app/main.ts"

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
import { enableProdMode } from '@angular/core';
declare const ENV;

if (ENV.PRODUCTION) { enableProdMode(); }

platformBrowserDynamic().bootstrapModule(AppModule);

3.7 Append this to "scripts" inside your "package.json"

"build": "ionic-app-scripts build --prod"

3.8 Then use this to build your app in production :

npm run build

This will create static assets of your app inside your "www" directory. Open your "www/index.html" in your browser and you'll see :

ionic-envars-prod

We have a cordova error but that's OK because we are running our app in browser. Now we see that our app is using our production environment variables and that the angular "enableProdMode" warning is gone.

Our app is fully in production mode !

4. Set up automatic documentation with compodoc

4.1 Append this to "devDependencies" inside your "package.json"

"@compodoc/compodoc": "1.0.0-beta.9"

4.2 Install Compodoc

npm install

4.3 Append this to "scripts" inside your "package.json"

"compodoc": "./node_modules/.bin/compodoc -d ./docs/ -p ./tsconfig.json"

4.4 Generate the docs (docs will be available inside your "docs" folder)

npm run compodoc

Then, open "docs/index.html" in your browser to see your docs.

4.5 Publish docs on Github pages

If you're using Github for your app source control. You can simply publish your docs to Github pages. Go to your project settings and set your page source to your "docs" folder.

ionic-github-publish-docs

I made it for this repo, you can view it here : https://romainfallet.github.io/ionic-workflow-guide/

4.6 Automatically generate docs on push

What you don't want with your docs is that the published version on Github pages does not match the last changes you made. To automatically update your docs when you push somes changes, append this to "scripts" inside your "package.json" :

"git-push": "npm run compodoc && git add ./docs && git commit -m 'Update docs' && git push -u origin master"

Then, use npm run git-push instead of git push to publish your commits. That way, you are sure that your last commits are fully and automatically documented.

5. Set up our Production App Server

We saw in the Environment Variables set up that we can build our app in production mode with :

npm run build

That packages our production ready app inside the "www" folder. Now we want to serve it.

5.1 Append this to "dependencies" inside your "package.json"

"express": "4.15.2",
"compression": "1.6.2"

5.2 Install the server dependencies

npm install

5.3 Create a new "server.js" file in your project root folder and add this to it

const express = require('express');
const compression = require('compression');
const path = require('path');
const app = express();
const port = process.env.PORT || 8080;
const ENV = require(path.join(__dirname + '/env/' + (process.env.NODE_ENV ? process.env.NODE_ENV : 'dev') + '.json'));
const forceSSL = function() {
  return function (req, res, next) {
    if (req.headers['x-forwarded-proto'] !== 'https') {
      return res.redirect(['https://', req.get('Host'), req.url].join(''));
    }
    next();
  }
}

// We force HTTPS and GZIP compression on production
if (ENV.PRODUCTION) {
    app.use(forceSSL());
    app.use(compression());
}

app.use(express.static(__dirname + '/www'));

// We redirect all GET requests to our 'index.html' to let Ionic handle the rooting
app.get('/*', function(req, res) {
    res.sendFile(path.join(__dirname + '/www/index.html'));
});

app.listen(port, function() {
    console.log('Listening on port ' + port + '. isProduction : ' + ENV.PRODUCTION);
});

5.4 Then, append this to "scripts" inside our "package.json"

"start": "NODE_ENV=prod node ./server.js"

5.5 Our production app server can now be started with this command

npm run start

ionic-production-app-server

6. Automatic deployment on Heroku

Now that we have a production ready server. We need to deploy it somewhere in the web !

6.1 Create a free account on Heroku

https://www.heroku.com/

6.2 Create a new app

ionc-heroku-create-app

6.3 Link your app with your Github account

ionic-heroku-deploy

6.4 Enable automatic deploy

ionic-heroku-automatic-deploy

6.5 Move "typescript", "@ionic/app-scripts" and "@ionic/cli-build-ionic-angular" from "devDependencies" to "dependencies" inside your "package.json"

  "dependencies": {
    "@ionic/app-scripts": "1.3.7",
    "typescript": "~2.2.1",
    "@types/jasmine": "2.5.41",

This will make Heroku able to build our app.

6.6 Append this to "scripts" inside your "package.json"

"heroku-postbuild": "npm run build"

With this, Heroku will build our app in production mode as soon as our dependencies will be installed. We use "ionic-app-scripts" (which is now packaged in our dependencies) instead of "ionic" because the Ionic CLI is only installed on our computer locally.

6.7 Add this inside your "package.json"

This will make Heroku use the same environment in which we develop our app.

"engines": {
  "node": "7.10.0",
  "npm": "4.6.1"
}

6.8 Deploy to Heroku

To deploy, you just have to commit some changes. The automatic deploy will do the rest.

git add . && git commit -m 'Add Heroku deployment' && npm run git-push

I made it for this repo, you can view it here :

https://ionic-workflow-guide.herokuapp.com/

7. Set up dependencies version check with npm-check

7.1 Append this to "devDependencies" inside your "package.json"

"npm-check": "5.4.4"

7.2 Install npm-check

npm install

7.3 Append this to "scripts" inside your "package.json"

"check": "node ./node_modules/npm-check/bin/cli.js -u"

4.4 Check your dependencies version and update if needed

npm run check

About

Create a full and powerful worflow with Ionic (Unit Testing, Environment variables, Automatic documentation, Production App Server, Automatic deployment)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published