TypeScript
Angular
ionic
IonicCLI

Ionic CLIのソースコードを追ってみよう

三連休初日に、日本中で1人ぐらいにニーズがあるかもしれない記事を書こうと思いたち、せっかくIonic CLIのコントリビューションしてるので(ionic-team/ionic-cli Contributors)、Ionic CLIのコードの簡単な解説をしてみます。

$ npm i -g ionic

でインストールして、それ以降、ionic コマンドを使えるあいつです。Ionic Teamはソースコードを

https://github.com/ionic-team/ionic-cli

で公開しており、CLIの中身をここで確認することができます。


Ionic CLIを手元でコンパイルする

GitHubからcloneしたファイルを使って、Ionic CLIを動かすことができます。試してみる場合は、以下の手順を実行してください。



  1. https://github.com/ionic-team/ionic-cli をローカルにcloneする


  2. npm i で依存パッケージをインストール


  3. npm run bootstrap で、packages/以下のモノレポ毎の依存パッケージをインストールして、それぞれをリンクさせる


  4. npm run link で、グローバルにパスを通します

これで、あなたのionicコマンドは、cloneしたパッケージから実行されるようになりました。ちなみに、ソースコードの変更を行う時は npm run watch を実行すると即時反映されます(参考


CLIの中身

では、CLIの中身についてみていきましょう。


ionic start

ionic start --type=angular というコマンドを例に、簡単に処理を追っていきます。

このコマンドが実行されると、 packages/ionic/src/commands/start.tsが呼び出されます。オプションである--type=angularについてはL96-L100で定義されています。


packages/ionic/src/commands/start.ts

{

name: 'type',
summary: `Type of project to start (e.g. ${lodash.uniq(starterTemplates.map(t => t.type)).map(type => chalk.green(type)).join(', ')})`,
type: String,
},

ちなみに、ここを削除したら、typeオプションが使えなくなります。オプションを増やす時は、まずここにオプションを定義します。

処理をおおざっぱに説明します。まず、typeオプションがある場合はその文字列を、ない場合はデフォルト値としてionic-angularが変数projectTypeに代入され、this.validateProjectTypeで、「入力された文字列が正しいか」の検証を受けます。L202-203行目です。


packages/ionic/src/commands/start.ts

const projectType = options['type'] ? String(options['type']) : 'ionic-angular'; await this.validateProjectType(projectType); 


現在Ionicのtypeは、Ionic v1を意味する ionic1、 Ionic v2-3の ionic-angular、 Ionic v4の angular の3通りがあり、それ以外はエラーがでます。ここで、CLIではじめるIonicのバージョンを決定しています。

次に、プロジェクト名とスターターテンプレートについて入力済みかどうかの判定があったあと(入力がなかった場合は、入力を求める)、ファイルの生成を行います。L403-408です。


packages/ionic/src/commands/start.ts

if (this.schema.cloned) {

await this.env.shell.run('git', ['clone', this.schema.url, projectDir, '--progress'], { stdio: 'inherit' });
} else {
const starterTemplate = await this.findStarterTemplate(this.schema.template, this.schema.type, tag);
await this.downloadStarterTemplate(projectDir, starterTemplate);
}

スターターテンプレートがURL指定だった場合は、そこをgit cloneすることを試みます。文字列の場合は、公式のstertar templateで存在確認をしたあと、git cloneします。

ですので

$ ionic start projectName https://github.com/rdlabo/ionic-wpcom

とか入力すると、ネット上で公開されているパッケージを使ってそのままionic startすることができるわけです。ハンズオンに役立つ豆知識です。


ionic serveをみてみる

続いて、ionic serveについてです。

実行されると、packages/ionic/src/commands/serve.tsが呼び出されるのですが、ここに記述されている処理はあまりなく、packages/@ionic/cli-utils/src/lib/serve.tsにあるserveメソッドを呼び出しています。


packages/@ionic/cli-utils/src/lib/serve.ts

async run(inputs: CommandLineInputs, options: CommandLineOptions): Promise<void> {

if (!this.project) {
throw new FatalException(`Cannot run ${chalk.green('ionic serve')} outside a project directory.`);
}

// TODO: use runner directly
await serve({ flags: this.env.flags, config: this.env.config, log: this.env.log, prompt: this.env.prompt, shell: this.env.shell, project: this.project }, inputs, options);
await sleepForever();
}


このserveメソッドに受け渡されているproject: this.projectが重要で、これはpackages/@ionic/cli-utils/src/index.tsgetProjectメソッドで取得してきている「そのプロジェクトのIonicのバージョン」が格納されています。


packages/@ionic/cli-utils/src/index.ts

projectFile = await readJsonFile(projectFilePath);


具体的には、プロジェクト直下のionic.config.json


ionic.config.json

{

"type": "ionic-angular"
}

の値を見に行っています。

そして、そのIonicのバージョンに従って、@ionic/cli-utils/src/lib/project/以下のファイルを呼び出して実行します。

例えば、Ionic v3(=ionic-angular)を使っている場合はpackages/@ionic/cli-utils/src/lib/project/ionic-angular/serve.tsが呼び出されますし、v4(=angular)を使っている場合はpackages/@ionic/cli-utils/src/lib/project/angular/serve.tsが呼び出されます。

内部サーバ立ち上げたり、IPアドレスで起動確認したりあたりはソースコード読んでいただけますと幸いです。


パッケージの簡単な説明

packages/@ionic/をみると、様々なパッケージがあって混乱すると思うので、私がさわったことあるパッケージのみですが、軽く解説しておきます。

パッケージ名
概要

cli-framework
CLIフレームワークです。ヘルプを呼び出すとか、ログに色つけるとか、そういうCLIっぽいメイン処理をします。

cli-utils
CLIのコマンド毎のライブラリ、ヘルパーみたいなもの。Ionicのバージョンによって異なる処理を行う場合はここにメイン処理を書く感じになる。

discover
さわったことないです

lab

ionic serve --labでIonic Labを立ち上げる時に使う処理が書いてある。どういう機能かは「ionic serve --lab」で、エミュレーターっぽく動かす参照。

ng-toolkit
Ionic v4では、Angular CLIをラップしてIonic CLIを動かすために必要なファイル群。「Angular CLIでビルドしたあとに、Cordova CLIを実行する」みたいな処理が書かれてたはず。

schematics-angular
Ionic v4で、ionic gコマンドを実行するためのもの。ng gコマンドをラップするのに必要なファイル。

utils-fs

fsのラッパー。TypeScriptで書きやすく、かつちゃんとPromiseで返してくれるようになってます。voidやcallbackはもうやめよう。

utils-network

ionic serve の時のPortまわりとか。DevAppsの疎通とか。

v1-toolkit
Ionic v1まわり


まとめ

駆け足でしたが、Ionic CLIの中身に興味をもつきっかけになりましたら幸いです。それでは、また。