igniteで自分専用のボイラープレート環境を作る
この記事は React Native Advent Calendar 2017 16日目です。
こんにちは。Webエンジニアの@DotEarlです。
Togetterという会社で、自社アプリをReactNativeで開発しています。
目次
モチベーション
新しくReactNativeでアプリを作り始める時
最初にお決まりの構成、つまりボイラープレートを毎回作るのは面倒くさいと思います
例えばredux入れてmiddleware入れてデバッグツール組み込んで…など
出来ればinitでプロジェクト作ったら後は書くだけの環境が整って欲しいところ
自分専用のボイラープレート環境を
コマンド一発で生成することが出来るようになります
今回はその作り方を説明したいと思います
igniteとは
簡単に説明すると、react-native init
する感覚でignite new
すると
自分が設定したパッケージ/ディレクトリ構成と、react-native-xxxのようなネイティブモジュールを
入れるか入れないかyes/noで選びながらプロジェクトの初期化が出来るツールです
詳しくは以前に書いたのでこちらを
igniteでプロジェクトを始める時
新しいRNプロジェクトを作成する時は $ ignite new myApp
の用に実行します
何も指定しないと公式自家製の環境がセレクトされますが
他に用意されたボイラープレートを使いたい時は
$ ignite new MyApp -b ir-boilerplate
のように -b
オプションで指定します
指定できるボイラープレート一覧はこちら
ignite/BOILERPLATES.md at master · infinitered/ignite · GitHub
この-bで指定するボイラープレートを今から自作していきます
前置きが長くなりました
自分用のボイラープレートを作る
時間がなくて適当になってしまいましたが
主に redux-saga
と redux-actions
を使った基盤を用意しました
GitHub - rskull/rn_redux_saga_sample
今から $ ignite new myApp
した時にこの構成でプロジェクトが生成されるようにボイラープレートを作っていきます
1. 基盤を生成する
新しいボイラープレートを作る時は以下のようにコマンドを実行します
$ ignite plugin new ignite-sample-biilerplate ? Is this an app boilerplate plugin? -> Yes ? Will your plugin have an example component? -> No ? Will your plugin have a generator command? -> Yes Creating new plugin: ignite-sample-biilerplate $ cd ignite-sample-biilerplate $ npm install $ tree -L 1 ├── README.md ├── boilerplate/ ├── boilerplate.js ├── commands/ ├── ignite.json ├── node_modules/ ├── package-lock.json ├── package.json ├── plugin.js ├── templates/ └── test
まずはboilerplate/
の中に入ってるignite/
フォルダ以外を全て削除します
次に、用意したRNの環境からボイラープレートなJS部分を boilerplate/
フォルダにコピーします
このあたりは人によって構成が違うと思いますが、とりあえず上で貼ったRNのサンプルを元に説明します
ルートにあった index.js
は index.js.ejs
に変更してboilerplate/
にコピー
続いてそのファイルを開き、アプリ名が直書きされてる部分を書き換えます
// index.js.ejs import { AppRegistry } from 'react-native'; import App from './src/App'; // $ ignite new myApp ← // 生成した時のアプリ名が渡ってくるので、差し替わるようにする AppRegistry.registerComponent('<%= props.name %>', () => App);
package.json
もpackage.json.ejs
に名前を変更して、差し替わる部分があれば
同じように <%= props.name %>
に書き換えます
今回はこれだけですが、他に.eslintや.flowconfigなどがあったら同じルールでコピーすればOKです
2. boilerplate.jsを書き換える
次はルートにあるboilerplate.js
を書き換えます
このファイルは、newした時に実行されるタスクの手順が書かれています
// boilerplate.js // ... // 単純に何をコピーするか指定するだけ // 自分の環境にパスを合わせる filesystem.copy(`${PLUGIN_PATH}/boilerplate/src`, `${APP_PATH}/src`, { overwrite: true }) spinner.stop() // ... // 自分の環境に合わせて必要な設定を追加 const templates = [ { template: 'index.js.ejs', target: 'index.js' }, { template: 'package.json.ejs', target: 'package.json' }, { template: 'ignite/ignite.json', target: 'ignite/ignite.json' } ] await ignite.copyBatch(context, templates, { name: name }, { quiet: true, directory: `${PLUGIN_PATH}/boilerplate` }) spinner.stop() // ... // 最初から入ってて不要なものがあれば消す filesystem.remove('__tests__') filesystem.remove('App.js') // run npm install spinner.text = '▸ installing ignite dependencies'
3. plugin.jsを書き換える
このファイルはreact-native-xxxx
のようなnpmモジュールを適用させる設定を書きます
今回は追加してないので特に設定はありませんが、サンプルコードが書かれてるで不要な部分を消します
async function add (context) { // await screenExamples.add(context) } async function remove (context) { // await screenExamples.remove(context) } module.exports = { add, remove }
機会があればこのあたり深掘りする記事も書きたいと思います
4. 使ってみる
ひとまずこれで完成です!
このボラープレートを使ってプロジェクトを生成してみます!
適当なワークスペースに移動したら-bオプションで今作ったフォルダを指定して実行
$ ignite new myApp -b ./ignite-sample-biilerplate
これで用意した環境が適用されたプロジェクトが生成されたと思います
いつも通りreact-native run-ios
などして正常に動いていれば成功です
これで煩わしい環境構築を忘れて素早く開発がスタートできますね!!
ちなみに作成したボイラープレートはnpmに登録すると簡単に利用出来るようになります
ルールとしてパッケージ名はignite-
のプリフィックスを付ける決まりです
指定するときはignite-
を省略できます
今回はサンプルなので登録はしませんでしたが、もし登録してたら
どこにいても $ ignite new myApp -b sample-biilerplate
で生成可能になります
今回つくったボイラープレートのリポジトリ ↓
その他の機能
今回ふれなかった機能の紹介
igniteにはgenerateオプションがあります
例えば$ ignite generate reducer user
の用に実行すると
reducer/フォルダにuser.jsテンプレートを作ってくれるなど
自分でコマンドをカスタマイズすることが出来ます
このエントリーでいじらなかったフォルダはこのあたりの設定を入れるやつです
templates/
-> generateで生成する元となるテンプレートファイル群を入れる
commands/
-> generateで何をどこにコピーするかなどの設定を入れる
詳しくは公式のボイラープレートのリポジトリを眺めてみて下さい
この辺りもいずれ書きたいと思います
感想
自分専用のボイラープレートを作って生成するところまでやってみました
generateオプションでファイルを自動生成するようにすればもっと開発効率上がりそう?
用意さえしてしまえば後々楽ができそうですね
以上で終わります
Happy boilerplating!
参考URL
ReactNativeにStorybookを導入するまで
storybookはコンポーネント単位でサンドボックス開発できる開発環境
どんなコンポーネントが存在するか、どんな種類があるか、使い方は?など
ドキュメントとしても機能するのであると便利
最近Webの方でよく使われてるようで、ReactNativeでも使える
導入
まずはstorybookをグローバルにインストールする
$ npm i -g @storybook/cli
RNのプロジェクトに移動してgetstorybook
を実行
$ getstorybook
あとは勝手に設定されて
storybook
というフォルダが作成される
最初からいくつかサンプルコードが入っているので実行して確認してみる
実行
ReactNativeの場合、コンポーネントの動作はシュミレーター上で確認するので
既にアプリが起動してる場合は、いつも動かしてる8081のサーバーは落としておく必要がある
まずはstorybookのサーバーを起動
$ yarn run storybook
localhost:7007
にアクセスすると専用のページが表示される
この時点では、リストに何も表示されてなくてサンプルを確認出来ない
RNのアプリを立ち上げると、さっき起動したstorybookのサーバーに繋がって
アプリ側にも専用の画面が表示される
するとWebの画面にも用意したコンポーネントのリストが表示されるようになり
見たい項目をクリックすると、連動してシュミレーター上でも画面が切り替わる
これでやっと確認出来るようになった
※ 左の画面がiOSシュミレーター
最初からあるサンプルを参考に自分のアプリのコンポーネントも追加していけば
これでチーム開発も捗るのではないだろうか
今回動かしたのサンプル:GitHub - rskull/rn_storybook
でもシュミレーター上で確認しないといけないのはちょっと面倒くさいかも…
以上です
ミドルウェアを使わないreduxをちゃんと理解するための個人メモ
仕事でいきなりredux/redux-saga
さらに redux-actions
の環境を触ってきて
ミドルウェアを使わないシンプルな構成のreduxの理解が浅かったのでちゃんと覚えようと思った
環境構築
お手軽 create-react-app
$ create-react-app react-redux-example
次にreduxを使うのに必要なnpmモジュールをインストールする
$ yarn add redux react-redux
react-redux
は react
で redux
を扱うために必要
これだけで環境は整った
処理の流れ
ActionType
ただの変数
イベントの名前を付けてく
const ADD_ITEM = 'ADD_ITEM' const DELETE_ITEM = 'DELETE_ITEM'
Action
オブジェクトを返すだけのピュアな関数
typeを設定するのはお約束
// typeにActionTypeを設定 export const addItem = item => ({ type: ADD_ITEM, item }) export const deleteItem = id => ({ type: DELETE_ITEM, id }) // addItem('hello') // -> { type: 'ADD_ITEM', item: 'hello' }
Reducer
storeの構造はここで決まる
import { combineReducers } from 'redux' // 初期値 const initialState = [ { item: 'hello' } ] const todos = (state = initialState, action) => { switch (action.type) { // アイテムを追加 case ADD_ITEM: return [...state, { item: action.item }] // アイテムを削除 case DELETE_ITEM: return state.filter((v, k) => k !== action.id) default: return state } } // 分割されたreducerを合成 // これがstore全体の構造になる const reducer = combineReducers({ todos })
Storeを生成
import { createStore } from 'redux' // 前述のReducersで生成した値が入る const store = createStore(reducer)
ミドルウェアがある場合はcreateStoreの第2引数に設定を渡すが
今回は素のredux構成なので省略
描画する
index.js
を編集
import { Provider } from 'react-redux' // ... ReactDOM.render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) // ...
ここでやっとreact-redux
が登場
storeの値やActionが使えるようになる
App.js
container
となるものは全てこの形式で書かれる
import { connect } from 'react-redux' class App extends Component<{}> { render() { const { todos, actions } = this.props return ( <div> <button onClick={() => actions.addItem('world')}>ADD</button> <ul> {todos.map((v, k) => <li onClick={() => actions.deleteItem(k)}>{v.item}</li>)} </ul> </div> ) } } // stateにstoreの値が入ってる // this.props.todosで使えるようになる const mapStateToProps = state => ({ todos: state.todos }) // Actionsで定義した関数が使えるようになる // this.props.actions.addItem('hello') const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(Actions, dispatch) }) // Appコンポーネントに各値を接続 export default connect(mapStateToProps, mapDispatchToProps)(App)
まとめ
処理の流れが分かってスッキリした
今回のソース
わかりやすいように出来るだけ1ファイルに納めて書いてる
次はミドルウェア
を導入してどう変わっていくかを確かめる
※追記
タイトル変えました
以上
igniteでモダンなReactNative環境を楽々セットアップ
react-native init app
でアプリを始めても最初はredux
やmiddleware
など
いつも決まって使うような環境は入っていない
とりあえず試したいけど面倒くさいよ!って時はignite
コマンドを使うと
定番の環境、いわゆるボイラープレートをいい感じに構築してくれる
そうでない人も、個人的にフォルダ構成や書き方は参考になった
準備
react-native
まずはReactNativeを動かせる環境を作る
Getting Started - React Native
$ brew install node $ brew install watchman $ npm install -g react-native-cli
ignite
ignite
をインストール
$ npm install -g ignite-cli
ignite
コマンドを使うと
対話形式で定番のライブラリを導入するか聞かれていき
最後に全て設定が整ったプロジェクトが生成される
この生成されるボイラープレートには種類があり
下のリンクで配布されている中から -b
で指定出来る
ignite/BOILERPLATES.md at master · infinitered/ignite · GitHub
また、自分でボイラープレートを作成することも出来る
ignite/creating-boilerplates.md at master · infinitered/ignite · GitHub
$ ignite new MyNewAppName -b ir-boilerplate
何もなも指定しないと、デフォルトで redux/redux-saga
がメインの構成になる
試す
$ ignite new igniteApp
実行した後、いくつか質問されます
- Would you like Ignite Development Screens?
- 動いてるサンプルが見たい場合は
yes
- 動いてるサンプルが見たい場合は
- What vector icon library will you use?
- 用意された様々なiconを表示出来るツールが使いたい場合は
yes
- 用意された様々なiconを表示出来るツールが使いたい場合は
- What internationalization library will you use?
- 多言語対応したい場合は
yes
- 多言語対応したい場合は
- What animation library will you use?
- 便利なアニメーション ライブラリが使いたい場合は
yes
- 便利なアニメーション ライブラリが使いたい場合は
とりあえず全部yes
にする
すると以下のようなフォルダが生成される
├── App │ ├── Components │ ├── Config │ ├── Containers │ ├── Fixtures │ ├── I18n │ ├── Images │ ├── Lib │ ├── Navigation │ ├── Redux │ ├── Sagas │ ├── Services │ ├── Themes │ └── Transforms │ ├── README.md ├── Tests ├── android ├── app.json ├── ignite ├── index.js ├── ios ├── node_modules ├── package.json ├── storybook └── yarn.lock
storybookもデフォルトで設定されてて嬉しい
起動
$ react-native run-ios
コンポーネント・API・テーマ・画面遷移など、サンプルコードが一式確認出来るので
とりあえずコードを眺めたりいじったりしてみると良いのではないでしょうか
時間があったら自分用のボイラープレート作ってみる予定
以上