前回、React Routerを使ったルーティング、サーバーとのデータ通信までできました。しかし、これまでECMAScript 5 (ES5) でJavaScriptを書いてきましたが、grails-react-boilerplateではECMAScript 2015 (ES2015) でJavaScriptが書かれています。
今回はBabelを使って、ES2015に対応できるようにしてみます。
引き続き、以下の記事とリポジトリを参考に進めます。
Babel
以前は6to5と呼ばれていたトランスパイラ。JSXも標準でサポート。本稿ではwebpackのローダの一つとして使用
Babelの説明はこう書かれてます。トランスパイラとはコード変換ツールのようなものっていう理解でいいのでしょうか。Babelを使うとES2015のコードをES5に変換できます。ES2015だけでなく、JSXも変換してくれます。
Babelはプラグインを組み合わせて動作させるようです。そして、複数のプラグインをセットにしたものをpresetと呼ぶようです。
今回使いたいpresetは、es2015とreactです。
WebpackからBabelを使えるようにしましょう。Webpackのloaderとして、babel-loaderが使えます。
GitHub - babel/babel-loader: Webpack plugin for Babel
Babelのオプションで使用するpresetを選べます。webpack.config.jsにloader: 'babel?presets[]=react,presets[]=es2015'
というように書いてもいいですが、.babelrcというファイルに書くこともできます。.babelrcを作成しましょう。
// .babelrc { "presets": ["es2015", "react"] }
npmでモジュールをインストールします。
$ npm install babel-core babel-preset-es2015 babel-preset-react babel-loader --save-dev
webpack.config.jsでloaderの設定をjsx
からbabel
へ変更します。
// react-app/hot.webpack.config.js loaders: ['react-hot', 'babel'],
これで設定ができました!
ES2015の文法はWebで調べるとして、ReactでES2015を使う場合、React.createClass
メソッドを使わずにclassとしてReactコンポーネントを定義できます。
BookIndexPageコンポーネントをES2015で書き換えてみます。
// react-app/src/components/BookIndexPage.js import React, {Component} from 'react'; import {BootstrapTable, TableHeaderColumn} from 'react-bootstrap-table'; import {Button} from 'react-bootstrap'; import 'react-bootstrap-table/css/react-bootstrap-table-all.min.css'; import * as ajax from '../ajax'; import BookNewDialog from './BookNewDialog'; export default class BookIndexPage extends Component { constructor(props) { super(props); this.state = {booklist: []}; } createBook(creatingBook) { this.setState({showNewDialog: false}); ajax.createBook(creatingBook, (_) => { this.reloadData(); }, (err) => { console.log("error"); }); } reloadData() { ajax.getBooks((data) => { this.setState({ booklist: data }); }); } showNewDialog() { this.setState({showNewDialog: true}); } hideNewDialog() { this.setState({showNewDialog: false}); } componentDidMount() { ajax.getBooks((data) => { this.setState({ booklist: data }); }); } render() { return ( <div> <h1>Books</h1> <Button onClick={this.showNewDialog.bind(this)}>New</Button> <BootstrapTable data={this.state.booklist} hover condensed pagination deleteRow selectRow={{ mode: 'checkbox', bgColor: "rgb(238, 193, 213)", }} > <TableHeaderColumn dataField="id" dataSort={true} isKey={true} >ID</TableHeaderColumn> <TableHeaderColumn dataField="title" dataSort={true}>Title</TableHeaderColumn> <TableHeaderColumn dataField="price" dataSort={true}>Price</TableHeaderColumn> </BootstrapTable> <BookNewDialog show={this.state.showNewDialog} closeAction={this.hideNewDialog.bind(this)} submitButtonAction={this.createBook.bind(this)} /> </div> ); } }
webpack-dev-serverを起動してアクセスすると、無事表示されます。
grails-react-boilerplateでは、stage-0
というpresetも使っています。これは何でしょうか?
調べてみると、ECMAScriptでは新機能が仕様として認められるかどうかの確度を5段階のStageで表記するようです。
Stage0の段階の機能も使いたい場合は、Stage0のpresetも使えるように設定しておく必要があります。
$ npm install babel-preset-stage-0 --save-dev
// react-app/.babelrc { "presets": ["es2015", "stage-0", "react"] }
ESLint
ESLintはJavaScriptの静的コード解析ツール。早速インストールしてみます。
$ npm install eslint --save-dev
package.jsonにeslintを実行するscriptを追加。
// react-app/package.js "scripts": { ・・・ "lint": "eslint src" },
これで実行できます。
$ npm run-script lint
たくさんエラーが出ました!ES2015で記述してるので、ESLintにES2015を使ってることを教えてあげないといけないです。ESLintの設定ファイルは .eslintrc です。
ecmaFeatures
でES2015の文法を個別に有効にすることができるようです。env
で"es6": true
を設定するとmodules以外が有効になるようです(ECMAScript 2015は以前はECMAScript 6という名称で呼ばれてました)。modulesについては個別にecmaFeatures
で"modules": true
を追加します。JSXも使っているので"jsx": true
も追加。
追記 2016/2/21
ESLintのバージョンが2.xになってから ecmaFeatures
の記述を paserOptions
に書くようになったみたいです。
"parserOptions": { "ecmaFeatures": { "jsx": true, "modules": true } },
追記ここまで。
Documentation - ESLint - Pluggable JavaScript linter
// react-app/.eslintrc { "env": { "es6": true }, "ecmaFeatures": { "jsx": true, "modules": true }, "rules": { } }
これでnpm run-script lint
するとエラーなく実行されます。
.eslintrcにルールを追加していくと色々チェックできるようになります。例えば、セミコロンの省略をチェックするようにするには"semi": 2
を追加します。2
という数値を指定するとチェックに引っかかった場合にエラーとします。1
を指定すると警告です。
List of available rules - ESLint - Pluggable JavaScript linter
// react-app/.eslintrc "rules": { "semi": 2 }
おしまい
今回は、BabelとESLintを導入してみました。ここまでくれば後はモリモリと写経できそうです!