Lets port a new angular project to Cordova without using Ionic or NativeScript. Why? Because those frameworks can sometimes be too opinionated and constraining. By the end of this article, you'll have a functioning angular/cordova project which will be as loosely coupled with Cordova as possible. You'll be able to conform to the angular style conventions, and install whatever plugins, frameworks, or libraries you desire. (e.g. bootstrap, ng-bootstrap, pug, etc.)
First, I'd like to give credit to this post as it's what got me heading in the right direction however I found it to be a little incomplete.
You can find the demo source code here
Ok. Lets Get Started.
First we're going to create a vanilla angular 6 project called hello-cordova
with the following command: ng new hello-cordova
.
Some things you may want to do at this point would be to install and configure things like bootstrap
& ng-bootstrap
or any other angular library's you're interested in working with.
Now that we have a basic angular app running with npm start
we're going to create some basic scaffolding to setup our cordova build.
First let's make sure we have the cordova cli installed: npm install -g cordova
.
Now let's create a basic cordova app. We're going to create the cordova app in a cordova
subdirectory and give it an id of com.hellocordova.www
and a name of Hello Cordova
.
cordova create cordova com.hellocordova.www "Hello Cordova"
Now let's add some git tracking files to ignore some build files and keep directories:
touch cordova/.gitignore
touch cordova/www/.gitkeep
And add the following to cordova/.gitignore
:
node_modules
www/*
!www/.gitkeep
platforms
plugins
Finally, let's add the iOS platform. To add platforms (and plugins) we'll want to make sure we're in the cordova
directory and then run the following:
cordova platform add ios
In the root directory of our project (not the one in the cordova
folder), lets add some basic scripts to the package.json
to automate a few things:
"clean": "rm -rf dist cordova/www/* && touch cordova/www/.gitkeep",
"build:cordova": "npm run clean && ng build --base-href=. --output-path=cordova/www",
"cordova:prepare": "cd cordova && rm -rf platforms plugins node_modules && npm ci && cordova prepare && cd ..",
"cordova:build:ios": "npm run build:cordova && cd cordova && cordova build ios && cd ..",
"cordova:emulate:ios": "npm run cordova:build:ios && cd cordova && cordova emulate ios && cd ..",
"open:xcode": "open $(find ./cordova/platforms/ios -name '*.xcworkspace')"
We're also going to modify the build
script to be the following:
"build": "ng build --base-href=/"
This will give you the following utilities:
npm run cordova:prepare
- Other devs should be able to run this script to initialize the Cordova app in their environment.npm run open:xcode
- Run this to easily open the project in Xcodenpm run cordova:build:ios
- Run this to rebuild the iOS projectnpm run cordova:emulate:ios
- Run this to run an iOS emulator of the projectYes. Now let's remove the infamous 400ms delay that iOS defaults on webview clicks. We're going to add FastClick.js to our angular app.
$ npm i fastclick
Add the following to the top of your src/main.ts
:
import * as FastClick from 'fastclick';
// attach FastClick.js
FastClick.attach(document.body);
Note: this should be added to main.ts as close to the top as possible so it executes immediately.
Now if you want to install other plugins you'll need to configure them. This can be done in the ngOnInit()
of your app.component.ts
:
// src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { CordovaService } from './service/cordova.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
constructor(protected _cordovaService: CordovaService) {}
public ngOnInit(): void {
this._cordovaService.initialize();
}
}
// src/app/service/cordova.service.ts
import { Injectable } from '@angular/core';
@Injectable()
export class CordovaService {
protected hasBegunInitialization: boolean = false;
constructor() {}
public initialize(): void {
// listen for 'deviceready' event in case it hasn't
// already been fired during application bootstrap
document.addEventListener('deviceready', () => {
window['isDeviceReady'] = true;
this.init();
console.log('deviceready fired after bootstrap finish');
}, false);
// check if 'deviceready' has already fired during
// application bootstrap.
if (window['isDeviceReady'] === true) {
this.init();
console.log('deviceready fired before bootstrap finish');
}
}
protected init(): void {
// lock initialization
if (this.hasBegunInitialization) {
return;
}
this.hasBegunInitialization = true;
// do init stuff here
}
}
Make sure you add a provider for the CordovaService
class.
Error: Cannot read property 'replace' of undefined
run cd platforms/ios/cordova && npm install ios-sim
Whitescreen of death?
<base href="/"></base>
, instead use <base href="."></base>
for your cordova distributions. This typically isn't what you want for your web distribution however as it can mess with your routing.--base-href
flags.