はじめに
「JQueryもいいけれど、そろそろReactを使ってみたいな」
そう思って挑戦してみたところ、なかなかに難儀でしたので、それをまとめてみます。「React + TypeScript + Webpack 」をASP.NET MVC5に適用する内容になっています。
次にような方に役立つのではないでしょうか。
- JQueryは使ったことあるけれど、Reactを始めてみたい方
- 1から作るのはサンプルやcreate-react-app をやってはみたものの、既存プロジェクトへの適用の仕方がよく分からない方
各パッケージの役割を整理
正直なところフロントエンドがここまで複雑化しているのとは思いませんでした。
たくさん登場人物がいて、さらに誰が何を担当しているのが分かりにくいです…。そもそもなんでフロントエンドの話に、サーバーサイドである、Node.js が出てくんねん!って感じですよ。過渡期なのでしょうけど、ちょっと魔境すぎません?
色々な登場人物が出てくる流れ
大まかにこういう流れだと理解しています。
1. React を使いたい
- やることは React.jsをインポートする。JQuery導入と同じ。怖くない。
2. JSXが登場
- これまでのJavaScriptはHTMLに紐づくものだったけど、WEBサイト機能が複雑になってきたし機能単位でまとめた方がいいよね。JavaScript主体のJSXで書く方が便利。
- JSXは Babel でコンパイルしないと使えない。Babel 登場。
- Babelを使うのに Node.jsが必要。Node.jsも登場。
3. TypeScriptが登場
- JavaScriptを直接書くより、最近のプログラミング言語っぽく書けるTypeScriptを使った方がいいよね。JSXじゃなくてTSXにしよう。
- TSXの導入に伴い Babel は必要なくなった。でも TSXファイルをコンパイルするのに Node.js が必要なので、こいつは残ります。
4. webpackが登場
- 機能の拡大と共にJavaScriptファイルが沢山増えてしまった。沢山あると読み込みが遅くなる。そこでwebpackです。こいつは一括で取り込めるようにまとめたJavaScriptを作成できます。ついでに圧縮(miniファイル作成)もできるよ。
- TypeScriptのコンパイルを実行したり(コンパイルそのものは ts-loaderが行う)、どこにまとめたJavaScriptを置くかも担当します。
- Webpackを使うのにもやっぱりNode.jsが必要です。
5. Reactを使う
- 4で出力した JavaScriptを読み込めば使用できます。
要はブラウザのスクリプト言語としてはJavaScriptがデファクトスタンダード。でもJavaScriptは使いづらいから、それを何とかしようと色々している結果、今現在のような複雑なことになっているのだと思います。
前提
既存プロジェクトとして、ここでは、ASP.NET MVC5とします。.NET Coreじゃなく.NET Framework 4.7.2 の方にしてみます。(その方が既存プロジェクトっぽいし、.NET Coreの方はテンプレートあるしね……)
IDEは Visual Studio 2019 Community で確認していますが、Visual Studio 2017でも大丈夫でしょう。
テンプレート通りに作成(既存プロジェクトのつもり)
npmを導入
npmとは
各種パッケージを管理するものです。Visual Studioのデフォルトとしてある Nugetと同じような機能です。
同じような機能を二つ使うのはややこしいですが、Nugetに無いので仕方がありません。フロントエンドのパッケージを管理するのが npm、サーバーサイドのパッケージを管理するのが、Nugetと分けるのがよさそうです。
(※デフォルトでは NugetでJQueryやBootstrapを管理しているので、後々削除する必要があります)
拡張機能のインストール
Visual Studioではデフォルトでは npm を使えないので、拡張機能の管理を呼び出します。
ここでは、NPM Task Runner と Package Installerを入れておきます。
WebPack Task Runner もあとで使うので入れておきます。
一度 Visual Studioを閉じてインストールを実行します。
npmでReactをインストール
ソリューション エクスプローラー で右クリックをして、Quick Install Packagesを選択します。
npm を選び、react のバージョンを16.8.6(現時点の最新版)を選択し、Installを実行します。同じように react-domもインストールします。
すると、プロジェクトの直下に packeage.json が作られているのが確認できます。これがパッケージを管理するファイルになります。プロジェクト管理にはなっていませんが、package-lock.jsonファイルと node_modulesフォルダも作成されていることが確認できます。node_modulesにパッケージの実体が存在します。
(参考)
package-lock.jsonについて知りたくても聞けなかったこと
package.jsonの変更
このまま必要なパッケージをnpmコマンドでインストールしていってもいいのですが、直接package.jsonを書き換えた方が早いのでそうします。
{
"name": "myproject",
"version": "1.0.0",
"scripts": {
"build": "webpack",
"watch": "webpack -w"
},
"devDependencies": {
"ts-loader": "^5.4.3",
"typescript": "^3.4.4",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.1"
},
"dependencies": {
"@types/react": "^16.8.14",
"@types/react-dom": "^16.8.4",
"react": "^16.8.6",
"react-dom": "^16.8.6"
},
"private": true
}
package.jsonの中身の詳細については下記ページが勉強になります。
変更後のpackage.jsonのパッケージをインストール
Visual Studio のメニューの 表示 -> その他のウィンドウ -> タスクランナー エクスプローラーを表示します。
Defaultsでインストールを実行します。
インストール終了。
インストールが成功すると、node_modulesフォルダ内のパッケージが増えていることが確認できます。
(注釈)ここまで「あれ?」と思った方もいると思います。package.jsonを作成して、直接書き換えることが出来るならば「Package Installer」は必要なさそうと思うかもしれません。確かにそうなのですが、今後追加でインストールしたいものが出来た時に便利です。
TypeScriptの設定
新しい項目の追加で、tsconfig.json を追加します。
そして、tsconfig.json を次のように変更します。
{
"compilerOptions": {
"sourceMap": true,
"target": "es5",
"module": "es2015",
"jsx": "react",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"lib": [
"es2019",
"dom"
]
}
}
tsconfig.json の中身の詳細については package.json と同じく下記ページを参考にしています。
webpackの設定
新しい項目の追加で、webpack.config.js を追加します。
そして、webpack.config.js を次のように変更します。
ここでは「entry」に設定されている "./src/main.tsx"のファイルを ./dist/main.js として変換すると設定しています。
module.exports = {
// モード値を production に設定すると最適化された状態で、
// development に設定するとソースマップ有効でJSファイルが出力される
mode: "development",
entry: "./src/main.tsx",
// ファイルの出力設定
output: {
// 出力ファイルのディレクトリ名
path: `${__dirname}/dist`,
// 出力ファイル名
filename: "main.js"
},
module: {
rules: [
{
// 拡張子 .ts もしくは .tsx の場合
test: /\.tsx?$/,
// TypeScript をコンパイルする
use: "ts-loader"
}
]
},
// import 文で .ts ファイルを解決するため
resolve: {
extensions: [".ts", ".tsx", ".js", ".json"]
}
};
webpack.config.js の中身についてもこちらを参考に(というかコピー)しています。
TSXファイルの追加と変更
新しい項目の追加で、TypeScript JSXファイルを追加します。場所は上記 webpack.config.js で指定した./src/main.tsxです。
内容は create-react-app のHello Worldみたくしてみます。
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App />, document.getElementById('root'));
同じくTypeScript JSXファイルを./src/App.tsx に追加します。
import React from 'react';
const App: React.FC = () => {
return (
<div className="App">
<header className="App-header">
<p>
Hello, World!!
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
WebPack Task Runnerでコンパイル
WebPack Task Runnerを使って、TypeScriptのコンパイルを実行します。
コンパイルが無事に実行されると ./dist/main.js が作成されます。
以後、TSX(TypeSciprt) が変更されるたびにコンパイルするのは面倒なので、ビルドする前にWebPack Task Runnerでコンパイルが走るようにバインドしておきます。
main.jsをHTML側で呼び出す
main.jsを使うために、適当な index.cshtml を変更します。
@{
ViewBag.Title = "Home Page";
}
<div id="root"></div>
<script src="~/dist/main.js"></script>
ビルドして動作確認
ビルドして、Hello World! が確認できれば無事に React が使えていることになります。
おわりに
登場人物がたくさん出てきて混乱してしまいますが、一つ一つ誰が何をやっているかを理解していければ大丈夫だと思います。色々やってますけど、最終的にはJavaScriptになるというだけです。
逆に理解しないまま「とりあえずサンプルあるし~」と進めていくと、上手く行っている時はいいのですが、トラブル発生時にどこに問題が発生しているのか分からないことになります。というか、なった。