ReactとOnsen UIとCordovaでストップウォッチアプリを作ってみた

UEQareer Advent Calendar 2016の19日目のエントリーです。

皆さん、こんにちは!
レッドインパルスのたかけんです。

今回は、技術系の記事です。よろしくお願いします!

作ったもの

ストップウォッチアプリです。
ソースコードは、こちら
機能はスタート・ストップ・リセットのみの単純な仕様です。

注目すべき点

僕は、Webアプリの開発経験がメインで、スマートフォンアプリを作った経験はほとんどありません。しかし、今回使用するOnsen UIやCordovaといったツールを駆使することで、Web技術のみでスマートフォンアプリを作ることができます。

環境

  • Mac OSX
  • Node.js v7.2.0
  • npm 3.10.9

ストップウォッチアプリの実装

ベースになるプロジェクトの作成

今回は、Reactを使って実装します。ReactはシンプルなViewライブラリです。フルスタックのフレームワークのようにアプリケーションの雛形を生成する機能はありません。
そこでweb上に公開されている雛形プロジェクト(ボイラープレートと呼ばれる)をベースに実装していきます。

今回は、react-simple-boilerplateを使用します。

[bash gutter=”false”] git clone git@github.com:nolotz/react-simple-boilerplate.git
cd react-simple-boilerplate
tree .
├── LICENSE
├── README.md
├── build
├── index.html
├── package.json
├── server.js
├── src
│   ├── App.jsx
│   └── index.jsx
├── styles
│   ├── application.scss
│   └── home.scss
└── webpack.config.js
[/bash]

このような構成になっています。ブラウザ上で、実行してみましょう。

[bash gutter=”false”] npm install
npm start
[/bash]

ローカルサーバが立ち上がり、雛形アプリがブラウザから確認できました。ここから、色々と手を加えていきましょう。

Onsen UIの導入

スマートフォンアプリ用のUIライブラリ「Onsen UI」をインストールします。Reactで使いたいので、以下、2つのライブラリをnpmからインストールします。

[bash gutter=”false”] npm install –save onsenui react-onsenui

react-simple-boilerplate@1.0.0 /xxx/react-simple-boilerplate
├── onsenui@2.0.5
├── UNMET PEER DEPENDENCY react@15.2.1
├── UNMET PEER DEPENDENCY react-dom@15.2.1
└── react-onsenui@1.1.0

npm WARN react-onsenui@1.1.0 requires a peer of react@^15.3.2 but none was installed.
npm WARN react-onsenui@1.1.0 requires a peer of react-dom@^15.3.2 but none was installed.
[/bash]

ボイラープレートのreactのバージョンが古いようで、アラートがでました。package.json内のバージョンを修正し、再度インストールします。

[bash gutter=”false”] npm install –save onsenui react-onsenui
npm install –save-dev file-loader
[/bash]

webpackでファイルの読み込みに必要なfile-loaderも合わせてインストールしました。

webpack.config.jsの修正

詳細は今回作成したアプリが公開されているGitHubのリポジトリ確認してください。Onsen UIや独自に作成したスタイルをインポートできるように設定します。

コンポーネントの作成

src/App.jsxを編集していきましょう。

[js gutter=”false”] import React, {Component} from ‘react’;
import {Page, Toolbar, ToolbarButton, Icon} from ‘react-onsenui’;
import ‘./../node_modules/onsenui/css/onsen-css-components.css’;
import ‘./../node_modules/onsenui/css/onsenui.css’;
import ‘./style.scss’;
[/js]

使用するライブラリ、CSS、SASSをインポートします。
style.scssはの中身は割愛しますが、ボタンやフォント等をカスタマイズ用のスタイルです。

[js gutter=”false”] const formattedSeconds = (sec) =>
Math.floor(sec / 60) +
‘:’ +
(‘0’ + (sec % 60).toFixed(2)).slice(-5)
[/js]

秒をストップウォッチに表示する文字列に変換するオブジェクトを作成します。

[js] class App extends Component {
constructor(props) {
super(props);
this.state = {
secondsElapsed: 0,
};
this.incrementer = null;
this.isCounting = false;
}

handleStartClick() {
if (!this.isCounting) {
this.incrementer = setInterval( () =>
this.setState({
secondsElapsed: this.state.secondsElapsed + 0.01
})
, 10);
this.isCounting = true;
}
}

handleStopClick() {
clearInterval(this.incrementer);
this.isCounting = false;
}

handleResetClick() {
clearInterval(this.incrementer);
this.setState({
secondsElapsed: 0,
});
this.isCounting = false;
}

render() {
return (
<Page contentStyle={{backgroundColor: ‘#efeff5′}}>
<Toolbar>
<div className=’center’>ストップウォッチ</div>
<div className=’right’>
<ToolbarButton>
<Icon icon=’ion-navicon, material:md-menu’></Icon>
</ToolbarButton>
</div>
</Toolbar>
<div style={{marginTop: ‘50%’, textAlign: ‘center’}}>
<h1 className=’stopwatch-timer’>{formattedSeconds(this.state.secondsElapsed)}</h1>
</div>
<div className=’stopwatch’>
<Button className=’start-btn’ onClick={this.handleStartClick.bind(this)}>start</Button>
<Button className=’stop-btn’ onClick={this.handleStopClick.bind(this)}>stop</Button>
<Button onClick={this.handleResetClick.bind(this)}>reset</Button>
</div>
</Page>
);
}
}
[/js]

ここがコンポーネントの作成になります。コンストラクタに必要なプロパティを新たに追加しています。incrementerは、時間を図るオブジェクトの代入先です。isCountingは、計測状態を論理値で保持します。
その下に、各ボタンのクリック時に実行されるメソッドをそれぞれ定義しています。renderメソッドは、Onsen UIに従ってpageコンポーネントの中に、toolber・時間表示・ボタンのコンポーネントを定義しています。

[js gutter=”false”] const Button = (props) =>
<button type=’button’ {…props} className={‘btn ‘ + props.className } />;
[/js]

ボタンのコンポーネントは、汎用的になるように別途、定義しました。

Cordovaでアプリ化

Cordovaは、webアプリをスマホのアプリにラッピングするツールです。
HTML・CSS・JSだけで、JavaやSwiftを使わずiOSやAndroidアプリを作成できます。

[bash gutter=”false”] npm install -g cordova
cordova create cordova-stopwatch
cd cordova-stopwatch
tree .
.
├── config.xml
├── hooks
│   └── README.md
├── platforms
├── plugins
└── www
├── css
│   └── index.css
├── img
│   └── logo.png
├── index.html
└── js
└── index.js
[/bash]

wwwの中は、自動生成されたファイルが入っています。
今の中身は削除して、先ほど作ったアプリのファイルを追加します。

編集したボイラープレートの直下でwebpackコマンドを使います。

[bash gutter=”false”] webpack
Hash: 12bdad5d6ae1efd8d742
Version: webpack 1.14.0
Time: 5891ms
Asset Size Chunks Chunk Names
assets/ionicons.dd4781d1acc57ba4c4808d1b44301201.ttf 189 kB [emitted] assets/fontawesome-webfont.25a32416abee198dd821b0b17a198a8f.eot 76.5 kB [emitted] assets/fontawesome-webfont.c8ddf1e5e5bf3682bc7bebf30f394148.woff 90.4 kB [emitted] assets/fontawesome-webfont.1dc35d25e61d819a9c357074014867ab.ttf 153 kB [emitted] assets/fontawesome-webfont.d7c639084f684d66a1bc66855d193ed8.svg 392 kB [emitted] assets/ionicons.19e65b89cee273a249fba4c09b951b74.eot 121 kB [emitted] assets/fontawesome-webfont.e6cf7c6ec7c2d6f670ae9d762604cb0b.woff2 71.9 kB [emitted] assets/ionicons.2c159d0d05473040b53ec79df8797d32.woff 67.9 kB [emitted] assets/ionicons.aff28a207631f39ee0272d5cdde43ee7.svg 334 kB [emitted] assets/Material-Design-Iconic-Font.a4d31128b633bc0b1cc1f18a34fb3851.woff2 38.4 kB [emitted] assets/Material-Design-Iconic-Font.d2a55d331bdd1a7ea97a8a1fbb3c569c.woff 50.3 kB [emitted] assets/Material-Design-Iconic-Font.b351bd62abcd96e924d9f44a3da169a7.ttf 99.2 kB [emitted] bundle.js 3.81 MB 0 [emitted] main
[0] multi main 40 bytes {0} [built] + 280 hidden modules

tree bundle
bundle
├── assets
│   ├── Material-Design-Iconic-Font.a4d31128b633bc0b1cc1f18a34fb3851.woff2
│   ├── Material-Design-Iconic-Font.b351bd62abcd96e924d9f44a3da169a7.ttf
│   ├── Material-Design-Iconic-Font.d2a55d331bdd1a7ea97a8a1fbb3c569c.woff
│   ├── fontawesome-webfont.1dc35d25e61d819a9c357074014867ab.ttf
│   ├── fontawesome-webfont.25a32416abee198dd821b0b17a198a8f.eot
│   ├── fontawesome-webfont.c8ddf1e5e5bf3682bc7bebf30f394148.woff
│   ├── fontawesome-webfont.d7c639084f684d66a1bc66855d193ed8.svg
│   ├── fontawesome-webfont.e6cf7c6ec7c2d6f670ae9d762604cb0b.woff2
│   ├── ionicons.19e65b89cee273a249fba4c09b951b74.eot
│   ├── ionicons.2c159d0d05473040b53ec79df8797d32.woff
│   ├── ionicons.aff28a207631f39ee0272d5cdde43ee7.svg
│   └── ionicons.dd4781d1acc57ba4c4808d1b44301201.ttf
└── bundle.js
[/bash]

必要なファイルが出力されます。
bundleフォルダの中身とindex.htmlをまるごとcordovaプロジェクトのwww直下にコピーします。

[bash gutter=”false”] cordova platform add android
cordova run android
[/bash]

今回は、Androidアプリにラッピングします。
実機を接続していれば実機に、無い場合はエミュレータにアプリがインストールされます。


ストップウォッチアプリができました!!

まとめ

web技術を使って、JavaやSwiftを使うことなく、スマホアプリが作れました。Cordova以外にも、スマートフォンアプリ開発においては、XamarinやReact Nativeなどのクロスプラットフォームのツールが現れて、技術的にも盛り上がっています。
それぞれメリット・デメリットがあるので、作りたいアプリの要求条件や自分のスキルを考慮して、適切なツールを選択することが重要ですね。今後も、こういった技術系の記事もドンドン発信していこうと思いますので、よろしくお願いします!

参考サイト