create-react-appを使用せずにReact+TypeScriptの環境構築について解説します。(個人開発の備忘録も兼ねているので、何か気づいたことがあれば教えていただけると嬉しいです。)
create-react-appを使用しない理由
create-react-appを使用すると、簡単にReactのプロジェクトを作成することができるが、webpack(JSやCSSなどのリソースファイルを1つにまとめたり、JSXのような特殊な記法で書かれたファイルを変換するツール)の設定が隠蔽されているため、プロジェクトに応じてloaderやpluginを新たに読み込むことが難しくなります。
build周りの設定がブラックボックス化してしまうため、今回はcreate-react-appを使用せずに環境構築を行なっていきます。
##構成
最終的なフォルダとファイル構成は以下のとおり。
react_app/
├ node_modules/
├ dist/
└ bundle.js
├ public/
└ index.html
├ src/
├ App.tsx
└ index.tsx
├ package-lock.json
├ package.json
├ tsconfig.json
└ webpack.config.json
1. 準備
適当なディレクトリを作成し、必要なモジュールをインストール。
#プロジェクトのフォルダを作成
$ mkdir react_app
$ cd react_app
#package.jsonを作成
$ npm init -y
#typescriptをインストール
$ npm i -D typescript
#webpackをインストール
$ npm i -D webpack webpack-cli webpack-dev-server
#loaderをインストール
$ npm i -D ts-loader
#pluginをインストール
$ npm i -D html-webpack-plugin
#React、ReactDOMをインストール
$ npm i react react-dom
#型定義ファイルをインストール
$ npm i -D @types/react @types/react-dom
-
typescript
(typescript本体) - webpack
-
webpack
(webpack本体) -
webpack-cli
(webpackコマンドを使うために必要なパッケージ) -
webpack-dev-server
(開発環境用のローカルサーバー)
-
- loader
-
ts-loader
(webpackからtypescriptを読み込むために必要なローダー)
-
- plugin
-
html-webpack-plugin
(webpackが生成したバンドルファイルを指定したhtmlに埋め込む)
-
- react
-
react
(React本体) -
react-dom
(ReactのDOMライブラリ) -
@types/react
(reactの型定義) -
@types/react-dom
(react-domの型定義)
-
######補足
パッケージインストール時にオブション -D をつけると、package.jsonのdevDependenciesに記録される。
webpackやtypescriptなど開発専用のパッケージはdevDependenciesインストールする。
2. package.jsonの編集
ルートディレクトリのpackage.jsonを以下のように編集。
script.testを削除して、script.start(開発環境用のローカルサーバー起動コマンド)とscirpt.build(webpack.config.jsonで設定した自前のbuildコマンド)を追加。
{
"name": "portfolio",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack",
+ "start": "webpack-dev-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/react": "^17.0.38",
"@types/react-dom": "^17.0.11",
"html-webpack-plugin": "^5.5.0",
"ts-loader": "^9.2.6",
"typescript": "^4.5.4",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.2"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
}
}
3. webpack.config.jsの作成
ルートディレクトリにwebpack.config.jsを作成。
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
//モードをdevelopment、production、noneから設定(必須)
//development: 開発時のファイル出力モード(最適化より時間短縮、エラー表示を優先)
//production: 本番時のファイル出力モード(最適化されて出力)
mode: 'development',
//メインとなるjsファイル(エントリーポイント)
entry: './src/index.tsx',
//ファイルの出力設定
output: {
path: path.join(__dirname, '/dist'), //出力先のディレクトリ(絶対パスで指定)
filename: 'bundle.js' //出力ファイル名
},
//デバッグのためのSourceMap(ビルド前後の対応関係を記述したファイル)の出力設定
devtool: 'inline-source-map',
//対象のファイルを変換するためのloaderを設定
module: {
rules: [
{
test: /\.tsx?$/, //build対象(loaderを適用するファイル)を指定
loader: 'ts-loader', //適用するloaderを指定
}
]
},
//importの際に省略する対象の拡張子を配列で指定
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'] //指定されている拡張子のファイルはimportの際に拡張子を省略できる
},
//webpack-dev-serverの設定
devServer: {
static: path.join(__dirname, '/dist'), //表示する静的ファイル(HTML)の場所を指定
open: true, //ブラウザを自動的に起動
port: 3000 //ポート番号を指定(デフォルトのポート:8080)
},
//pluginの設定
plugins: [
new HtmlWebpackPlugin({ //webpackでbuildされたJSやCSSを表示するHTMLを自動的に生成するplugin
template: './public/index.html', //テンプレートとして使用するHTMLファイルを指定
filename: 'index.html' //生成するHTMLファイル名
})
]
}
4. tsconfig.jsonの作成
以下のコマンドを実行して、TypeScriptの設定ファイルを作成します。
$ tsc --init
作成されたtsconfig.jsonの内容を一部修正します。
(コメント文は省略)
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
+ "jsx": "react",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
5. HTML
ルートディレクトリにpublicフォルダを作成して、その中にindex.htmlを作成
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>react_app</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
6. React App
ルートディレクトリにsrcフォルダを作成して、その中にindex.tsxとApp.tsxを作成
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<App />,
document.getElementById('app')
)
import React from 'react'
const App = () => {
return (
<div>
<h1>Hello React!</h1>
</div>
)
}
export default App
7. webpackの実行
package.jsonで設定したscriptを実行。
npm run build を実行し、webpackがdist/bundle.jsを生成。
npm run start を実行し、http://localhost:3000にアクセスすると'Hello React!'と表示される。
$ npm run build #webpackの実行
$ npm run start #webpack-dev-serverの起動