前回、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を導入してみました。ここまでくれば後はモリモリと写経できそうです!