Announcing Ionic Framework 2 Beta | The Official Ionic Blogionic2が無事ベータリリースになったようなので、チュートリアルを体験してみました。が、英語なのとionic1やAngularが分かっていないと戸惑う部分が多いように思われました。そこでチュートリアルの流れを日本語で解説し、本家で触れられていない点についていくつか補足します。なおハイブリットアプリをWindowsで作る人はそういないと思いますのでMacが前提です。
kawauchiyasuo-no-MacBook-Pro:project2 yasuo$ ionic _ _ (_) (_) _ ___ _ __ _ ___ | |/ _ \| '_ \| |/ __| | | (_) | | | | | (__ |_|\___/|_| |_|_|\___| CLI v2.0.0-beta.17Usage: ionic task args=======================Available tasks: (use --help or -h for more info) start .......... Starts a new Ionic project in the specified PATH serve .......... Start a local development server for app dev/testing platform ....... Add platform target for building an Ionic app run ............ Run an Ionic project on a connected device emulate ........ Emulate an Ionic project on a simulator or emulator build .......... Build (prepare + compile) an Ionic project for a given platform. plugin ......... Add a Cordova plugin resources ...... Automatically create icon and splash screen resources (beta)"
Pageデコレーターはインポート元であるnode_modules/ionic-framework/decorators/page.jsに実装されています。ここはフレームワーク部分ですからユーザーが触ることはありません。Page – Function in module – Ionic FrameworkPageデコレーターが付けられると、Angularのビューとして構成されるので、セレクタを使わなくても動的に内容が変更できるページになります。PageはNavControllerによりナビゲーションをさせることができます。
Hello I test
Welcome to your first Ionic app!
This starter project is our way of helping you get a functional app running in record time.
Follow along on the tutorial section of the Ionic docs!
この中の「*navbar」は現状効能が不明です。削除してもサンプルはそのまま動作しました。buttonにmenuToggleというキーワードが入っています。これはionicが備えているディレクティブで、ボタンにメニューをトグルする機能を持たせることができます。MenuToggle – Class in module – Ionic Frameworkion-contentが本文部分ですが、この中のbuttonもmenuToggleが記述されているのでメニューをトグルします。
NavController
サイドメニューでMy First Listをタップするとpagesのcomponentで指定されているListPageに遷移します。ListPageは./pages/list/listからインポートされていますので./pages/list/list.jsのクラスです。
import {Page, NavController, NavParams} from 'ionic/ionic';import {ItemDetailsPage} from '../item-details/item-details';@Page({ templateUrl: 'build/pages/list/list.html'})export class ListPage { constructor(nav: NavController, navParams: NavParams) { this.nav = nav; // If we navigated to this page, we will have an item available as a nav param this.selectedItem = navParams.get('item'); this.icons = ['flask', 'wifi', 'beer', 'football', 'basketball', 'paper-plane', 'american-football', 'boat', 'bluetooth', 'build']; this.items = []; for(let i = 1; i < 11; i++) { this.items.push({ title: 'Item ' + i, note: 'This is item #' + i, icon: this.icons[Math.floor(Math.random() * this.icons.length)] }); } } itemTapped(event, item ,index) { this.nav.push(ItemDetailsPage, { item: item }); }}
import {Page, NavController, NavParams} from 'ionic/ionic';@Page({ templateUrl: 'build/pages/item-details/item-details.html'})export class ItemDetailsPage { constructor(nav: NavController, navParams: NavParams) { this.nav = nav; // If we navigated to this page, we will have an item available as a nav param this.selectedItem = navParams.get('item'); }}
ここでのポイントはNavParamsです。NavParamsはデータを保持できるオブジェクトです。NavParams – Class in module – Ionic Framework一つ前のlist.jsのitemTapped関数内のpushでitemという引数を渡しています。pushはページを移動するだけで無く移動先のページに対して、パラメーターを渡すことができます。NavController – Class in module – Ionic Frameworkこの場合でいくとlist.js内のitemをitemというラベルを付けて、次のページに渡すということです。そして次のページではNavParamsを使って、navParams.get(‘item’)と指定することで渡されたデータを取得できます。this.nav = nav;は無意味な記載でコメントアウトしてもちゃんと動作します。
ハイブリッドアプリでシステム開発:JSでボタンへのイベント登録はloadの後じゃ無いとだめ | 法務ネット:弁護士 川内康雄先日Monacaも軽く触っていたのですが、感想はデバッガが良くできているなというところでした。そこでIonicとMonacaの開発の私的なサクサク感を比較してみたいと思います。ちなみに比較対象のMonacaはフリー版です。CLIが使えるGold以上だとまた印象が変わってくるのかも知れません。ionicもMonacaも、「HTML5+JavaScriptハイブリッドアプリ」という点では同じですので、ブラウザで開発中のアプリの実行結果を確認できます。Monacaの場合はクラウドIDEですのでクラウド環境での実行、ionicはionic serveコマンドでサーバーを作ってローカルで実行という違いはあります。が、レスポンスに特段の差は無く、デバッグのサクサク感はそれほど変わらないと思いました。ChromeのJavaScriptコンソールによるデバッグ情報の表示も、どちらの環境も同じように行えます。強いて言うとバグやconsole.logの実行行の特定が、ionicの方が若干楽という程度でしょうか。app.bundle.jsがエディタ上で簡単に見えるので、対象行の発見が楽です。が、Monacaにしてもchromeからソースを追えば発見可能です。一方、実機上でデバッグを行う場合には、両者の使用感には差があります。 Monacaの場合は、クラウドIDEでの開発内容をMonacaアプリにダウンロードして実行します。もともとIDEがクラウド上にありますから、ビルドする度にアップロードをするという手間がかかりません。またビルドも自動的に実行されるので、コードを保存したらすぐにMonacaアプリで結果を確認できます。そしてconsole.logの内容は、アプリのフローティングメニューからたどれる表示画面で内容を確認できます。更にネットワーク経由で送信されているようで、少し遅れますがクラウドIDEに情報が表示されます。ionic viewはmonnacaデバッガーにぱっと見は似ていますが、・コードを変える都度ビルドしてアップロードするという手間をかけないと変更が反映されない・これ自体にデバッグ出力を持っていないのでconsole.logを確認できないという制限があります。そのためがんがんコードを書き換えながら実機で確認するという用途には余り向いていません。How to debug on Ionic View [not the question, here’s the answer!]この方法でconsole.logを確認することもできそうですが、出自の分からないサービスだと継続性やセキュリティの問題がありますので、簡単に頼ることもできないと思います。ただしionicにはライブプレビューという機能があります。これは、母艦にAndroidを有線で接続している場合には、ionic runを-lオプション付きで起動すると、ソースを変更する度に自動的にAndroid実機に反映されるという仕組みです。-cオプションを付けている場合には、ionic runを起動したコンソールにログが出力されます。そんなわけでデバッグ環境の充実度、使いやすさはionicよりもMonacaが一歩リードしていると感じました。次は実際にコードを書いてみて、開発しやすさを比較してみたいと思います。”””
ionicのローカルテスト環境はブラウザ上で動いているので、ブラウザのCORS制限に引っかかります。別にプロキシをインストールする方法もあるようですが、ionic CLI自体にプロキシ機能が備わっているようなので、これを使うことに。How to fix CORS issues, revisitedHandling CORS issues in Ionicが、ここらへんに書かれている設定をいじってもウンともスンとも反応しません。404になるだけです。 というか、ionic.projectを消してしまってもブラウザ環境でプログラムが走ります。この設定ファイルってそもそも関係無いのではと悩んでいて、フォーラムに質問を投げたら回答をしてくれる人がいました。Proxy Problems with Ionic 2設定を記述する場所がionic2で変わったようで、ionic.projectではなくてionic.config.jsに記述するとのこと。 早速実行してみると、ブラウザからローカルのプロキシのポートにアクセスしても、ちゃんと目標の所に転送(というか代わって取得)してくれました。スクリプトからもOKです。こういう人柱的なところがあるのはベータ版を使う際の悩みですね。”””
Raspberry PiでIoTなシステム開発: Raspberry Pi にバイナリでNode.jsをインストールしばらく前に公式サイトからnodeのARM用バイナリが提供されなくなり、ネットでバイナリを探してインスト−ルをしていました。が、遂に公式でのARM用バイナリの配布が再開されたようです。それもv6/v7/v8も、4系も5系もとう大盤振る舞い。Download | Node.jsせっかくなのでこれを使ってインストールできるか試してみることにします。公式でのディレクションはcurlで直接nodeをインストールしていますが、まだ4系、5系のどちらを使うか決めていないので、nvmを使ってインストールして、後からバージョンを切り替えられるようにします。Jessieだとcurlはあえてインストールしなくても最初から使えました。
pi@raspberrypi:~ $ curlcurl: try 'curl --help' or 'curl --manual' for more informationpi@raspberrypi:~ $ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed100 7766 100 7766 0 0 3738 0 0:00:02 0:00:02 --:--:-- 3740=> Downloading nvm from git to '/home/pi/.nvm'=> Cloning into '/home/pi/.nvm'...remote: Counting objects: 4402, done.remote: Compressing objects: 100% (3/3), done.remote: Total 4402 (delta 0), reused 0 (delta 0), pack-reused 4399Receiving objects: 100% (4402/4402), 1.10 MiB | 562.00 KiB/s, done.Resolving deltas: 100% (2582/2582), done.Checking connectivity... done.* (detached from v0.31.0) master=> Appending source string to /home/pi/.bashrc=> Close and reopen your terminal to start using nvmpi@raspberrypi:~ $ nvm-bash: nvm: command not found
pi@raspberrypi:~ $ nvmNode Version ManagerNote: refers to any version-like string nvm understands. This includes: - full or partial version numbers, starting with an optional ""v"" (0.10, v0.1.2, v1) - default (built-in) aliases: node, stable, unstable, iojs, system - custom aliases you define with `nvm alias foo`Usage: nvm help Show this message nvm --version Print out the latest released version of nvm nvm install [-s] Download and install a , [-s] from source. Uses .nvmrc if available --reinstall-packages-from= When installing, reinstall packages installed in <node|iojs|node version="" number=""> nvm uninstall Uninstall a version nvm use [--silent] Modify PATH to use . Uses .nvmrc if available nvm exec [--silent] [] Run on . Uses .nvmrc if available nvm run [--silent] [] Run `node` on with as arguments. Uses .nvmrc if available nvm current Display currently activated version nvm ls List installed versions nvm ls List versions matching a given description nvm ls-remote List remote versions available for install nvm version Resolve the given description to a single local version nvm version-remote Resolve the given description to a single remote version nvm deactivate Undo effects of `nvm` on current shell nvm alias [] Show all aliases beginning with nvm alias Set an alias named pointing to nvm unalias Deletes the alias named nvm reinstall-packages Reinstall global `npm` packages contained in to current version nvm unload Unload `nvm` from shell nvm which [] Display path to installed node version. Uses .nvmrc if availableExample: nvm install v0.10.32 Install a specific version number nvm use 0.10 Use the latest available 0.10.x release nvm run 0.10.32 app.js Run app.js using node v0.10.32 nvm exec 0.10.32 node app.js Run `node app.js` with the PATH pointing to node v0.10.32 nvm alias default 0.10.32 Set default node version on a shellNote: to remove, delete, or uninstall nvm - just remove the `$NVM_DIR` folder (usually `~/.nvm`)pi@raspberrypi:~ $ nvm --version0.31.0</node|iojs|node>
pi@raspberrypi:~ $ wget -qO- https://raw.githubusercontent.com/xtuple/nvm/master/install.sh | sudo bashCloning into '/usr/local/nvm'...remote: Counting objects: 826, done.remote: Total 826 (delta 0), reused 0 (delta 0), pack-reused 826Receiving objects: 100% (826/826), 141.80 KiB | 26.00 KiB/s, done.Resolving deltas: 100% (387/387), done.Checking connectivity... done.NVM installedpi@raspberrypi:~ $ sudo nvmNode Version ManagerUsage: nvm help Show this message nvm install [-s] Download and install a nvm uninstall Uninstall a version nvm use Modify PATH to use nvm run [] Run with as arguments nvm ls List installed versions nvm ls List versions matching a given description nvm ls-remote List remote versions available for install nvm deactivate Undo effects of NVM on current shell nvm alias [] Show all aliases beginning with nvm alias Set an alias named pointing to nvm unalias Deletes the alias named nvm copy-packages Install global NPM packages contained in to current versionExample: nvm install v0.4.12 Install a specific version number nvm use 0.2 Use the latest available 0.2.x release nvm run 0.4.12 myApp.js Run myApp.js using node v0.4.12 nvm alias default 0.4 Auto use the latest installed v0.4.x version
早速これを使ってインストール。sudoでnode呼べました。
pi@raspberrypi:~ $ sudo nvm install v5######################################################################## 100.0%Checksums emptyNow using node v5.7.1pi@raspberrypi:~ $ lsinit-functions kt node_modules ts wiringPipi@raspberrypi:~ $ ls -laFtotal 100drwxr-xr-x 8 pi pi 4096 Mar 5 09:10 ./drwxr-xr-x 3 root root 4096 Feb 2 20:52 ../-rw------- 1 pi pi 20462 Mar 5 09:05 .bash_history-rw-r--r-- 1 pi pi 220 Mar 4 17:42 .bash_logout-rw-r--r-- 1 pi pi 3610 Mar 4 17:42 .bashrcdrwx------ 3 pi pi 4096 Mar 5 08:43 .config/-rw-r--r-- 1 pi pi 6148 Mar 5 07:19 .DS_Store-rw-r--r-- 1 pi pi 362 Mar 4 17:42 .ftpconfig-rwxr-xr-x 1 pi pi 11506 Mar 4 17:44 init-functions*drwxr-xr-x 3 pi pi 4096 Feb 11 22:54 kt/drwxr-xr-x 2 pi pi 4096 Mar 5 08:38 node_modules/-rw-r--r-- 1 pi pi 27 Mar 4 17:42 .node_repl_historydrwxr-xr-x 253 pi pi 12288 Mar 5 08:42 .npm/-rw-r--r-- 1 pi pi 675 Mar 4 17:44 .profiledrwxr-xr-x 4 pi pi 4096 Mar 5 08:46 ts/drwxr-xr-x 10 pi pi 4096 Feb 11 11:43 wiringPi/pi@raspberrypi:~ $ node -vv5.7.1pi@raspberrypi:~ $ sudo node -vv5.7.1
pi@raspberrypi:~ $ sudo visudopi@raspberrypi:~ $ sudo sh -c 'echo $PATH'/usr/local/nvm/v5.7.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binpi@raspberrypi:~ $ sudo typingsUsage: typings Commands: bundle, i, in, init, install, la, list, ll, ls, r, remove, rm, search, uninstalltypings -h Get help for typings --no-insight Disable insights for typings --version Print the CLI versiontypings --cache Print the path to the cache directorytypings@0.6.9 /usr/local/nvm/v5.7.1/lib/node_modules/typings
visudoではsecure_pathのところにパスを追記しています。
## This file MUST be edited with the 'visudo' command as root.## Please consider adding local content in /etc/sudoers.d/ instead of# directly modifying this file.## See the man page for details on how to write a sudoers file.#Defaults env_resetDefaults mail_badpassDefaults secure_path=""/usr/local/nvm/v5.7.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin""
pi@raspberrypi:~/ts $ tsc --nolib --diagnostics st.tserror TS2318: Cannot find global type 'Array'.error TS2318: Cannot find global type 'Boolean'.error TS2318: Cannot find global type 'Function'.error TS2318: Cannot find global type 'IArguments'.error TS2318: Cannot find global type 'Number'.error TS2318: Cannot find global type 'Object'.error TS2318: Cannot find global type 'RegExp'.error TS2318: Cannot find global type 'String'.Files: 1Lines: 10Nodes: 32Identifiers: 9Symbols: 7Types: 15Memory used: 9694KI/O read: 0.00sI/O write: 0.00sParse time: 0.12sBind time: 0.04sCheck time: 0.14sEmit time: 0.23sTotal time: 0.53s
で、これではお話にならないので対策を考えることにします。rpi2に入れたnodeで動かしたいので最初からちゃんとリモートで動く環境を作りたいんです。そもそもライブラリをチェックしたりコンパイルする必要も無いのだから、プリコンパイルしてリンクの時だけくっつけたらいいのでは無いかと思い検索したら同じ事を考えている人がいました。How to use compiler API to hold lib.d.ts in precompiled form · Issue #2030 · Microsoft/TypeScript · GitHubが、この方法だとソースの中身をいじる必要がありそうなのでパス。自分はそもそも今からTypeScriptを覚えようとしている段階なので、覚える前にソースをいじらないといけないというのでは順序が逆なので。次に考えたのが、atom-typescriptにはtsの保存と同時にjsを生成する機能があるので、それを使えばいいというソリューション。自分はRemote-FTPパッケージを使っているので、もともとリモートファイルをローカルファイルの様に編集できているので、リモートのtsを編集して保存すると同時にjsができれば簡単です。が、Remote-FTPがリモートのファイルを更新してくれるのは、エディタ画面上で保存ボタンを押したときのみで、atom-typescriptが自動生成するファイルをリモートに保存してくれる訳ではありませんでした。この延長線上で考えたのがRemote-FTPにはローカルとリモートを同期させる機能があるので、これを使うという手。しかしファイルを更新する都度syncを実行するのは面倒です。それをやっている間に3.94秒経ちそう。でもって次に考えたのがローカルのファイル変更を検出して自動的にリモートにアップロードするという方法。調べてみるとOSXならOS標準の機能だけで実行できそうです。OSXのLaunchAgentでホストOSのファイル監視してリモートサーバーにrsyncして同期する方法 – Qiitaが、設定ファイルを見て気が重くなったのと、ファイル変更を検知するプロセスが常駐するというのはマシンの負荷が増えそうなのが気になります。この設定をした直後はいいんですが、開発が終わったらこの設定をしたことを忘れてしまって、OSを再インストールするまで常駐しそう。で、結局採用したのが、リモートのフォルダをそのままマウントする方法。一番ありきたりな手段に落ち着きました。SSHFS (SSH Filesystem) – Raspberry Pi Documentation使い方はなんてことはなくてこの通り実行するだけ。最初リモートでsshfsというサーバーが稼働するのかと思い、piの方でapt-getを実行してしまいました。これはクライアントサイドでsshをラップしてリモートをマウントしているように見せるためのものですね。マウントするとローカルのマウントポイントの名前とアイコンが変わりました。マウントしてローカルのatomでtsファイルを更新したら(5行目のgreeterを康雄にしました)、リモートのjsが更新されています。マルチバイト文字でも問題なし。とりあえずこれでTypeScriptの学習を進めます。”””