しゃべぶろ

気になった技術の備忘録を残します。

【TypeScript】【React】react-scripts-tsは何をしているのか?

概要

TypeScriptでReactを開発する時にcreate-react-appを使用してプロジェクトを作成すると、以下のようなpackage.jsonが作成される。

{
  /** 一部省略 */
  "scripts": {
    "start": "react-scripts-ts start",
    "build": "react-scripts-ts build",
    "test": "react-scripts-ts test --env=jsdom",
    "eject": "react-scripts-ts eject"
  },
}

毎回何となくraect-script-ts startをしてReact Appを起動させているので、今回調べた上で理解して動かすようにしたい。

恐らくwebpackts-loaderなどが設定されて良い感じに動くようになっているはず。。。

解剖してみる

まずnpm run ejectを実行して、react-script-tsを展開する。

実行すると以下のようなログが出力される。

ログを展開する

ts-react-practice-simple-app shabe$ npm run eject

> ts-react-practice-simple-app@0.1.0 eject /Users/shabe/Desktop/MyApp/practice/ts-react-practice-simple-app
> react-scripts-ts eject

? Are you sure you want to eject? This action is permanent. Yes
Ejecting...

Copying files into /Users/shabe/Desktop/MyApp/practice/ts-react-practice-simple-app
  Adding /config/env.js to the project
  Adding /config/paths.js to the project
  Adding /config/polyfills.js to the project
  Adding /config/webpack.config.dev.js to the project
  Adding /config/webpack.config.prod.js to the project
  Adding /config/webpackDevServer.config.js to the project
  Adding /config/jest/cssTransform.js to the project
  Adding /config/jest/fileTransform.js to the project
  Adding /config/jest/typescriptTransform.js to the project
  Adding /scripts/build.js to the project
  Adding /scripts/start.js to the project
  Adding /scripts/test.js to the project

Updating the dependencies
  Removing react-scripts-ts from dependencies
  Adding autoprefixer to dependencies
  Adding babel-jest to dependencies
  Adding babel-loader to dependencies
  Adding babel-preset-react-app to dependencies
  Adding case-sensitive-paths-webpack-plugin to dependencies
  Adding chalk to dependencies
  Adding css-loader to dependencies
  Adding dotenv to dependencies
  Adding dotenv-expand to dependencies
  Adding extract-text-webpack-plugin to dependencies
  Adding file-loader to dependencies
  Adding fork-ts-checker-webpack-plugin to dependencies
  Adding fs-extra to dependencies
  Adding html-webpack-plugin to dependencies
  Adding jest to dependencies
  Adding object-assign to dependencies
  Adding postcss-flexbugs-fixes to dependencies
  Adding postcss-loader to dependencies
  Adding promise to dependencies
  Adding raf to dependencies
  Adding react-dev-utils to dependencies
  Adding resolve to dependencies
  Adding source-map-loader to dependencies
  Adding style-loader to dependencies
  Adding sw-precache-webpack-plugin to dependencies
  Adding ts-jest to dependencies
  Adding ts-loader to dependencies
  Adding tsconfig-paths-webpack-plugin to dependencies
  Adding tslint to dependencies
  Adding tslint-config-prettier to dependencies
  Adding tslint-react to dependencies
  Adding uglifyjs-webpack-plugin to dependencies
  Adding url-loader to dependencies
  Adding webpack to dependencies
  Adding webpack-dev-server to dependencies
  Adding webpack-manifest-plugin to dependencies
  Adding whatwg-fetch to dependencies

Updating the scripts
  Replacing "react-scripts-ts start" with "node scripts/start.js"
  Replacing "react-scripts-ts build" with "node scripts/build.js"
  Replacing "react-scripts-ts test" with "node scripts/test.js"

Configuring package.json
  Adding Jest configuration
  Adding Babel preset

Running npm install...
up to date in 4.623s
Ejected successfully!

Please consider sharing why you ejected in this survey:
  http://goo.gl/forms/Bi6CZjk1EqsdelXk1

  • ログ見るとconfigscripts系のファイルが追加されている。
  • package.jsonに依存関係が追加されている。
{
"dependencies": {
    /** 一部省略 */
    "babel-jest": "20.0.3",
    "babel-loader": "7.1.2",
    "babel-preset-react-app": "^3.1.2",
    "ts-loader": "^2.3.7",
    "tslint": "^5.7.0",
    "tslint-config-prettier": "^1.10.0",
    "tslint-react": "^3.2.0",
    "webpack": "3.8.1",
    "webpack-dev-server": "2.11.3",
    "webpack-manifest-plugin": "1.3.2",
  },
  "scripts": {
    "start": "node scripts/start.js",
    "build": "node scripts/build.js",
    "test": "node scripts/test.js --env=jsdom"
  },
  "babel": {
    "presets": [
      "react-app"
    ]
  }
}
  • startコマンドを実行すると、scripts/start.jsを実行するようになっている。

scripts/start.js

簡単に説明するとconfig配下のwebpack.config.dev.jsなどの設定ファイルを読み込んでwebpack-dev-serverを起動するよう実装されている。

詳しくは中身を以下のソースを参照のこと。

github.com

config/webpack.config.dev.js

webpackの設定ファイルである。自分が知っているwebpack.config.jsと大分違う(設定が複雑で分からない...)

まぁ、ts-loadertsconfig周りだけ軽く見てみる。

ts-loader

  /** 一部省略 */
  {
    test: /\.(ts|tsx)$/,
    include: paths.appSrc,
    use: [
      {
        loader: require.resolve('ts-loader'),
        options: {
          // disable type checker - we will use it in fork plugin
          transpileOnly: true,
        },
      },
    ],
  },
  • testと書いているがこれはts-loaderが対象にするファイル拡張子のこと。
  • includetestで指定したファイルの場所を限定している、この例ではsrc配下のファイルが対象となる。
  • loaderで使用するローダであるts-loaderを指定している。

    • ローダーは他にもfile-loadercss-loaderなどがある。
  • optionstranspileOnlyはトランスパイルのみで型チェックをしなくなる。

tsconfig

// Perform type checking and linting in a separate process to speed up compilation
new ForkTsCheckerWebpackPlugin({
  async: false,
  watch: paths.appSrc,
  tsconfig: paths.appTsConfig,
  tslint: paths.appTsLint,
}),
  • ForkTsCheckerWebpackPluginを使う事で、別プロセスで型チェックや静的チェックを実行するのでスピードがあがるらしい。

実際のtsconfigファイルは以下になる。

/** 一部省略 */
"compilerOptions": {
    "baseUrl": ".",
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "importHelpers": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true
  },
  • moduleesnextはESモジュールの最新版と考えれば良さそう。
  • forceConsistentCasingInFileNamesはファイル名の大文字小文字のチェックを行う。
  • importHelperstslibのヘルパーをimportするかどうか。
  • 他は後々覚えていこう。

まとめ

react-scripts-tswebpackts-loaderなどの煩雑な設定を簡単にしてくれる物である。 但し、react-scripts-tsの状態では各種設定を弄る事は出来ないので、ejectする必要がある。 設定に疎いのであれば、react-scripts-tsに頼ってしまって問題ないのかなと思った。

参考