React、TypeScript 環境構築 その1

環境

  • mac
  • node v10.9.0

まず雛形を作成

  • Facebook の提供している、React.js アプリを素早く作成するコマンドラインツール、create-react-app を使う。まずインストール
npm install -g create-react-app
  • create-react-app には TypeScript のボイラープレートもあってそれを使ってプロジェクトを生成
create-react-app react-ts-app --scripts-version=react-scripts-ts

とりあえずアプリを実行

  • yarn start http://localhost:3000 の URL でブラウザが立ち上がる
  • yarn test Jest による単体テスト
  • yarn build 本番ビルドが ‘./build’ に生成
  • React 雛形画面が表示された

create-react-app を削除

  • create-react-app は非常に便利なのだが、なにをやってるか中身がよくわからないので、yarn ejectを実行して create-react-app に頼らないプロジェクトにしよう。
  • yarn ejectを実行すると? Are you sure you want to eject? This action is permanent.と聞かれるので Yにしておく。
  • package.json のtsConfigFileが絶対パスになってるので、相対パスに変更する
"globals": {
  "ts-jest": {
-    "tsConfigFile": "/Users/ユーザー名/workspace/react-ts-app/tsconfig.test.json"
+    "tsConfigFile": "./tsconfig.test.json"
  }
}

tslint.json の修正

  • tslint の設定を latest に修正
"extends": [
   "tslint:latest",

tsconfig.json の修正

  • 型定義ファイルの場所 rootDirrootDirs へ変更して typings を追加する(typingsには css の型定義を格納する予定)
"rootDirs": ["src", "typings"],
  • configディレクトリを除外する
 "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts",
+   "config"
  ]

Prettier

  • Prettier の追加
yarn add -D prettier tslint-plugin-prettier tslint-config-prettier
  • tslint.json へtslint-config-prettierを追加する。もしかして勝手に追加されているかも
{
  "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
  "linterOptions": {
    "exclude": [
      "config/**/*.js",
      "node_modules/**/*.ts",
      "coverage/lcov-report/*.js"
    ]
  }
}

CSS Modules with TypeScript

  • CSSにも型定義をするやつです。違和感あったが、使ったほうがよさそうです。
yarn add -D typed-css-modules typed-css-modules-loader
  • package.json の script にtcmの実行を追加して、preのscriptを追加する。
  • prestartは、startの前に実行される。prebuildはbuildの前に実行される。これ最近しった。。。
/react-ts-app/package.json

"scripts": {
        "tcm": "tcm ./src -c -o ./typings",
        "prestart": "yarn run tcm",
        "start": "node scripts/start.js",
        "prebuild": "yarn run tcm",
        "build": "node scripts/build.js",
        "pretest": "yarn run tcm",
        "test": "node scripts/test.js --env=jsdom"
},
  • Webpackの設定を修正
/react-ts-app/config/webpack.config.dev.js

            use: [
              require.resolve("style-loader"),
              {
                loader: require.resolve("css-loader"),
                options: {
-                 importLoaders: 1,
+                 importLoaders: 2,
+                 modules: true,
+                 localIdentName: "[name]__[local]___[hash:base64:5]",
+                 sourceMap: true
                }
              },
+             {
+               loader: require.resolve("typed-css-modules-loader"),
+               options: {
+                 camelCase: true,
+                 searchDir: "./src",
+                 outDir: "./typings"
+               }
+             },
              {
                loader: require.resolve("postcss-loader"),
  • 本番も一部追加
/react-ts-app/config/webpack.config.prod.js

{
  loader: require.resolve("css-loader"),
  options: {
    importLoaders: 1,
+   modules: true,
    minimize: true,
    sourceMap: shouldUseSourceMap
  }
},

Storybook

  • コンポーネントを管理しやすいのでstorybookを追加する
  • storybookの追加
yarn global add @storybook/cli
getstorybook
  • TypeScriptで実装するので、設定を修正する。
/react-ts-app/.storybook/config.js

- // automatically import all files ending in *.stories.js
- const req = require.context('../stories', true, /.stories.js$/);
+ // automatically import all files ending in *.stories.tsx or jsx
+ const req = require.context('../src', true, /\.stories\.[jt]sx?$/);
  • tsx のストーリーに対しても動くように設定を変える。
yarn add -D @types/storybook__react @types/storybook__addon-actions

  • .storybookのWebpackの設定を修正する
/react-ts-app/.storybook/webpack.config.js

const dev = require('../config/webpack.config.dev');
module.exports = {
    plugins: [
        // your custom plugins
    ],
    module: dev.module,
    resolve: dev.resolve,
};

  • storybookのファイルはトランスパイルしないよう除外設定を修正
/react-ts-app/config/webpack.config.dev.js


- exclude: [/\.js$/, /\.html$/, /\.json$/],
+ exclude: [/\.js$/, /\.html$/, /\.json$/, /\.ejs$/],
  • .gitignore へ storybook-static を追加

Storybookの確認のためコンポーネントを作成してみる

  • srcの下にcomponentsディレクトを作成して以下3つのファイルを作成する
/react-ts-app/src/components/Button.css

.root {
  border: 1px solid red;
  background-color: gray;
}
.content {
  font-size: large;
  color: white;
}
.description {
  color: red;
}
/react-ts-app/src/components/Button.stories.tsx

import { action } from "@storybook/addon-actions";
import { storiesOf } from "@storybook/react";
import * as React from "react";
import Button from "./Button";
storiesOf("Button", module)
  .add("with hello", () => <Button onClick={action("clicked")}>Hello</Button>)
  .add("with hey", () => <Button onClick={action("clicked")}>Hey</Button>);

/Users/ka-yamao/workspace/react-ts-app/src/components/Button.tsx

import * as React from "react";

import * as style from "./Button.css";

export default (props: {
  children?: string;
  onClick(event: React.MouseEvent<HTMLButtonElement>): void;
}) => (
  <button className={style.root} onClick={props.onClick}>
    <span className={style.content}>{props.children}</span>
    <span className={style.description}> I am a button..</span>
  </button>
);
  • ts-loader が古くて動かなかったので、もう一度追加する。
yarn add ts-loader
  • "ts-loader": "^5.3.2",だと動いた。
  • Storybookで確認してみる
 yarn storybook
  • http://localhost:6006/ をブラウザで開く

ここまでしたことのソース

参考サイト

次にしたいこと

  • webpack3からwebpack4へバージョンアップ
  • typescript-fsa、typesafe-actionsを追加して実装を進める
  • redux-sagaの導入
  • クロスドメインを気にせず実装したいから、webpackでプロキシの設定をする