ある程度Babelとか知ってる人向きです。
要約
- Class Property DeclarationsでReactのPropTypes指定が捗る
- ESLintそのままではClass Property Declarationsに対応してない
- babel-eslintパーサ使えば解決(ただしestraverse-fbは手動で入れろ)
以上。estraverse-fb周りはそのうち修正されそう。
Class Property DeclarationsでReactのPropTypes指定が捗る
ES.nextのClass Property Declarationsでクラスにプロパティ生やせるよう提案されている。
それを使えばReactのpropTypes指定が捗るようになる。やったぜ。
import React from 'react';
export default class MyButton extends React.Component {
static propTypes = {
onClick: React.PropTypes.func.isRequired
};
handleClick(){
this.props.onClick();
}
render(){
return (
<button onClick={::this.handleClick}>ClickMe!</button>
);
}
}
使うにはBabelのstage-2stage-1以上の指定が必要。
(イベントハンドラってbindする必要あったんだっけ…?)
ESLintそのままではClass Property Declarationsに対応してない
ESLintは2.3.0からES7に対応したらしい。
ES7(ES2016)で新たに入るのは以下の二つのみ。
- Array.prototype.includes
- Exponentiation Operator(
**
)
仕様は以下から見られる。
ES7が固まった以上、昔ES7 async/awaitなんて言ってたりしたのはもはや誤用なのだが、
Class Property Declarationsが入ると勘違いして試してコケた。
誤用については以下のリンクも参考になる。
※指摘をいただいたので上記を修正
{
"parserOptions": {
"ecmaVersion": 7
},
"env": {
"browser": true,
"es6": true
},
"ecmaFeatures": {
"classes": true,
"jsx": true
},
"plugins": [
"react"
],
"rules": {
//...
}
}
$ eslint MyButton.jsx
/src/MyButton.jsx
4:20 error Parsing error: Unexpected token =
/(^o^)\
babel-eslintパーサ使えば解決
というわけで、babel-eslintを入れよう。
babelパーサならES.nextの仕様のコードでも読んでくれる。
パーサ自体がbabel用なためか、いろいろオプション抜いても平気で動く。
$ npm i -D babel-eslint
{
"parser": "babel-eslint",
"env": {
"browser": true
},
"plugins": [
"react"
],
"rules": {
//...
}
}
ここで、estraverse-fbが存在しないと怒られたら手動で入れる。
$ npm i -D estraverse-fb
estraverse-fbは2.3.0から利用しなくなったESLintの依存モジュールらしい。
babel-eslintがESLintのためにそれを読んでるとかなんとか。
上のリンクでそのうちbabel-eslintが対応すると思うので-D
は付けてないよ、ってコメントあるけど、
めんどいので-D
つけたよ。お好みで。
ビルド環境
実際はeslint直接ぶっ叩いてるわけじゃなくてwebpackのpreLoaderとして使ってる。
現状の趣味プロジェクトのビルド環境晒しとく。多分そのうち変わる。
しかし最近のjs環境って本当にカオスですよねー
みんなHaxe使えばいいのに
const path = require('path');
module.exports = [{
entry: {
bundle: './src/entry.jsx'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
preLoaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'eslint-loader'
}
],
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.jade$/,
loader: 'jade-react-loader'
}
]
}
}];
{
"parser": "babel-eslint",
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"env": {
"browser": true
},
"plugins": [
"react"
],
"rules": {
"indent": [
"error",
2
],
"quotes": [
"error",
"single"
],
"linebreak-style": [
"error",
"unix"
],
"semi": "error",
"no-unused-vars": "warn",
"no-console": "warn"
}
}
{
"presets": ["es2015", "stage-0", "react"]
}