Reactは15ヶ月前に比べて相当様子が違った

17年9月ごろを最後にReact書いてなかったので、15ヶ月ぐらいのブランクでしたが、再び寝たReactを起こしてみました。すると、なんとまあ、相当様子が違うのです。Cliツールで雛形を作るのはView.jsで経験していましたが、そもそもに元祖だったらしいReactのソレ(create-react-app)がいい感じに良く動く。複雑なWebpackの設定とか、ライブラリスタックのバージョン合わせなどを全くしなくてもOK。素敵。TypeScriptもちゃんと対応。

package.json

まずやるのは、scriptsから事故防止のためにejectを削ります。

その後にだいたい使いそうなライブラリを加えたりしてまずは以下の感じ。せっかくcreate-react-appで依存性をシンプルに見せられているのに@typesの連続で汚れる。TypeScriptの機能としてJSライブラリに型定義がなければ自動的に@typesみてくれるようになればいいのにな。

まだアプリケーションのコード一切書いてないのでライブラリは入れ出しするでしょう。material-ui関連ではバージョンがあがりすぎてて見当がつかないのでまずドキュメント読み直すところからです。最近のお気に入りはramda。関数型「風」に書くのが好きなのでlodashとかより適している。GraphQL with AppSyncは初挑戦。

{
    "scripts": {
        "start": "react-scripts-ts start",
        "build": "react-scripts-ts build",
        "test": "react-scripts-ts test --env=jsdom"
    },
    "dependencies": {
        "@material-ui/core": "^3.7.0",
        "@material-ui/icons": "^3.0.1",
        "aws-amplify": "^1.1.17",
        "aws-amplify-react": "^2.2.4",
        "ramda": "^0.26.1",
        "react": "^16.7.0",
        "react-dom": "^16.7.0",
        "react-redux": "^6.0.0",
        "react-router-dom": "^4.3.1",
        "redux": "^4.0.1",
        "redux-actions": "^2.6.4"
    },
    "devDependencies": {
        "@types/enzyme": "^3.1.15",
        "@types/enzyme-adapter-react-16": "^1.0.3",
        "@types/jest": "^23.3.10",
        "@types/nock": "^9.3.0",
        "@types/node": "^10.12.18",
        "@types/ramda": "^0.25.45",
        "@types/react": "^16.7.17",
        "@types/react-dom": "^16.0.11",
        "@types/react-redux": "^6.0.11",
        "@types/react-router-dom": "^4.3.1",
        "@types/redux-actions": "^2.3.1",
        "enzyme": "^3.8.0",
        "enzyme-adapter-react-16": "^1.7.1",
        "nock": "^10.0.4",
        "react-scripts-ts": "3.1.0",
        "tslint-config-airbnb": "^5.11.1",
        "typescript": "^3.2.2"
    }
}

ここで疑問なのは、react-scripts-tsが自動生成されたものではdependensiesに入ってたこと。これってdevDependenciesでいいんじゃないかなと思うので移しておいて様子見ます。

watchman

create-react-appはJestのテスト環境もすぐ作ってくれますが、テスト実行すると立ち上がったままで変更監視を始めます。すると「ファイルが多すぎ」エラーが出てしまいそのままでは動かなかった。調べるとファイル変更を監視するためにwatchmanというのをインストールしないとダメだとのこと。

$ HOMEBREW_PREFIX=$(brew --prefix) brew install watchman

HomeBrewで淹れますが、単に「$ brew install watchman」だと入れたwatchmanがアクセス権の問題で動きませんので、上記のようにPREFIX環境変数を設定します。これは長時間ハマりました。

テスト周辺

import * as React from 'react';
import { configure, shallow } from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';

import App from '../App';

describe('App', () => {
    beforeAll(() => {
        configure({ adapter: new Adapter() });
    });

    test('renders without crashing', () => {
        const wrapper = shallow(<App/>); // mountでもyarn testならOK。IDEからの直接起動はNG
        expect(wrapper.contains(<h1 className="App-title">Welcome to React</h1>)).toBeTruthy();
    });
});

デフォで書き出されてたテストをEnzymeバージョンにして動作確認。Dom不要のshallowはいつでも動くが、mountを使ったテストは単独でGoLand(IDEはWebStormもCLionもやめてGoLandにしました)から実行できない。

f:id:masataka_k:20181223223241p:plain
GoLand(他、JetBrainsのIDE)の個別Jest実行設定画面

こちらのように、Jestのオプション設定で「--env=jsdom」を書いてあげればOK。yarn testの実行時でもreact-scripts-ts testの引数として書かれてます。jestの設定で指定する方法をやってみると以下のエラーで、ejectしろと言ってくるので、とりあえず先のIDE設定で回避します。

Out of the box, Create React App only supports overriding these Jest options:

  • collectCoverageFrom
  • coverageReporters
  • coverageThreshold
  • snapshotSerializers
  • moduleNameMapper.

These options in your package.json Jest configuration are not currently supported by Create React App:

  • testEnvironment

If you wish to override other Jest options, you need to eject from the default setup. You can do so by running npm run eject but remember that this is a one-way operation. You may also file an issue with Create React App to discuss supporting more options out of the box.

しかしEnzymeは前からこんなに簡単に書けたかな?Reactノードを引数にとるのも、containsってのも記憶にない。。。これはView.jsに替えてReactを選ぶ強力な説得材料になるかも。jsx/tsxでテストが書けるのでDom断片を気軽に使える=ユニットテストが楽しい。nock使っての通信のところもフックすると、ユニットテストの延長線上でE2Eに近いことがさほど手数多く無く書けそう。

HMR環境

create-react-appのデフォではHMR環境が組まれてないのですが、まあ、無くてもいいかな。画面見ながら作るよりUIもTDDで書くようにしたら実際に動かす必要は常の事ではないので。トリッキーにアプリのブートストラップコードのところで細工しないといけないのが改善されていないのであればwebpackの設定をこじ開けるなど無理するのも嫌なのでHMRは入れなくていいや。