React + TypeScriptでアプリを書くことが多いですが、それを書き始めるセットアップは多種多様な方法があります。
自分がいつもやっているセットアップについてのメモ書きです。
事前準備
create-react-appをグローバルにインストールしておく必要があります。
npm install -g create-react-app
セットアップ手順
react-scripts-tsをインストール
create-react-appを使って、create-react-appのTypeScript版であるreact-scripts-tsをインストールします。
(.
で現在ディレクトリに展開出来ます。アプリ名を指定した場合はそのディレクトリが作られます)
create-react-app . --scripts-version=react-scripts-ts
Require all css from index.tsx
index.tsx
からすべてのcssファイルをrequireするように変更します。
これにより、.ts
, .tsx
, .css
のファイルを編集するとHot Reloadingによりすぐにアプリが再描画できます。
diff --git a/src/index.tsx b/src/index.tsx
index 1c66245..bf693b2 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,10 +2,16 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
-import './index.css';
+
+// import all *.css files
+function requireAll(r: any) {
+ r.keys().forEach(r);
+}
+
+requireAll((require as any).context('./', true, /\.css$/));
index.tsx
はwebpackのrequire.contextに依存し汚くなりますが、他のコンポーネントなどの依存はキレイに保つ意図があります。(各コンポーネントがcssをrequireしなくていい)
この変更は、次のパターンでコンポーネントを実装する際に役立ちます。
- JavaScriptとCSSは独立しているが同じディレクトリに並べる
ComponentName.tsx
ComponentName.css
- CSSはSUIT CSSなどのルールに習いコンポーネント名をクラス名にする
.コンポーネント名 {}
.コンポーネント名-子要素名 {}
.コンポーネント名.is-ステート名 {}
詳細は次のドキュメントに書いてあります。
アプリを起動
後はアプリを起動して書き始めるだけです。
npm start
サンプルリポジトリ
実際にこの手順でセットアップしたリポジトリがあります。
git clone https://github.com/azu/react-typescript-startup
cd eact-typescript-startup
yarn install
yarn start
実例
- azu/faao: Faao is a GitHub issue/pull-request client on Electron.
- azu/irodr: RSS reader client like LDR for Inoreader.
- proofdict/editor: Proofdict editor.
ステート管理はalminを使っていることが多いです。
デフォルトでTypeScriptに対応していて、TypeScriptに依存していないため。
- ドメインとか作らずにStoreだけで書くとクラスベースのReduxのReducerみたいになる
- https://github.com/azu/searchive/blob/master/packages/searchive-app/src/renderer/store/SearchIndexStore/SearchIndexStore.ts
Tips
tslintを無効化する
How to disable tslint? · Issue #133 · wmonk/create-react-app-typescript
tslint.json
の rules
fieldを空にすることで無効にできます。
diff --git a/tslint.json b/tslint.json
index eb5d66a..2b86576 100644
--- a/tslint.json
+++ b/tslint.json
@@ -1,99 +1,3 @@
{
- "extends": ["tslint-react"],
- "rules": {
- "align": [
- true,
- "parameters",
- "arguments",
- "statements"
- ],
- "ban": false,
- "class-name": true,
- "comment-format": [
- true,
- "check-space"
- ],
- "curly": true,
- "eofline": false,
- "forin": true,
- "indent": [ true, "spaces" ],
- "interface-name": [true, "never-prefix"],
- "jsdoc-format": true,
- "jsx-no-lambda": false,
- "jsx-no-multiline-js": false,
- "label-position": true,
- "max-line-length": [ true, 120 ],
- "member-ordering": [
- true,
- "public-before-private",
- "static-before-instance",
- "variables-before-functions"
- ],
- "no-any": true,
- "no-arg": true,
- "no-bitwise": true,
- "no-console": [
- true,
- "log",
- "error",
- "debug",
- "info",
- "time",
- "timeEnd",
- "trace"
- ],
- "no-consecutive-blank-lines": true,
- "no-construct": true,
- "no-debugger": true,
- "no-duplicate-variable": true,
- "no-empty": true,
- "no-eval": true,
- "no-shadowed-variable": true,
- "no-string-literal": true,
- "no-switch-case-fall-through": true,
- "no-trailing-whitespace": false,
- "no-unused-expression": true,
- "no-use-before-declare": true,
- "one-line": [
- true,
- "check-catch",
- "check-else",
- "check-open-brace",
- "check-whitespace"
- ],
- "quotemark": [true, "single", "jsx-double"],
- "radix": true,
- "semicolon": [true, "always"],
- "switch-default": true,
-
- "trailing-comma": [false],
-
- "triple-equals": [ true, "allow-null-check" ],
- "typedef": [
- true,
- "parameter",
- "property-declaration"
- ],
- "typedef-whitespace": [
- true,
- {
- "call-signature": "nospace",
- "index-signature": "nospace",
- "parameter": "nospace",
- "property-declaration": "nospace",
- "variable-declaration": "nospace"
- }
- ],
- "variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
- "whitespace": [
- true,
- "check-branch",
- "check-decl",
- "check-module",
- "check-operator",
- "check-separator",
- "check-type",
- "check-typecast"
- ]
- }
+ "rules": {}
}
Electronアプリの場合
electron-webpackを使うことでreact-scripts-tsと大体同じような構成を取れます。
electron-webpack-ts
のAddonを入れることでTypeScriptの対応が入るので、後は大体同じです。(webpackの面倒なところをスキップできます。)
実例: