ASP.NET Core 2.2 + ASP.NET Core MVC + React + TypeScript + SCSS + Webpack な環境を作成する
タイトルの通り、ASP.NET Core MVC 上で React を使うための環境を構築する。
Razor でサーバーサイドレンダリングしつつ、一部の動的な部分だけ React を使う感じの想定。
ついでに TypeScript や SCSS のコンパイルも Webpack で行うようにする。
ASP.NET Core Web アプリケーションのプロジェクト作成時に React.js を選択できるのですが、画面はすべて React で作るとかの環境なので、自力で1から作った。
リポジトリ
今回作成したサンプルプロジェクトのリポジトリ
インストールするもの
とりあえずアプリケーション。拡張などは後で記載。
最新版。自分の構築では Professional だが Community でも問題ない(はず)。
インストールするものについては、Web開発系のはとりあえずチェック入れておく。
最新版。Visual Studio が入れる Node.js はバージョンが古いので。
拡張等
Visual Studio 2017
Webpack をビルド後に起動とかするので。
TypeScript SDK for Visual Studio 2017
最初に入ってるのより新しいバージョンのが配布されていることがよくある。
現在の SDK のバージョンはプロジェクトのプロパティのTypeScript ビルドの TypeScript バージョンで見ることができる(後述)
外部WebツールのPATHの優先順を変更。最新の Node.js を使うため。
ツール → オプション を開く
プロジェクトおよびソリューションを展開 → Web Package Managementを展開 → 外部 Web ツール
.node_module\.bin を一番上に移動
$(Path) を二番目に移動
Node.js
特になし。npm も入ってるはず。コマンドで npm --version とか打てるなら問題なし。
npm のバージョンを最新にするなら以下のコマンドを打つ
> npm install -g npm
グローバルに Webpack 入れるとかあるなら以下のコマンドでする。
> npm install -g webpack
プロジェクト作成
Visual Stuido 2017 でプロジェクトを作成
「ASP.NET Core Web アプリケーション」を作成
構成は「Web アプリケーション (モデルビュー コントローラー)」で作成
TypeScript のビルドに使う SDK のバージョンを指定(必要に応じて)
プロジェクトのプロパティを開く
TypeScript ビルドの TypeScript バージョンを「使用可能な最新バージョンを使う」にする。
https://gyazo.com/eb3be17bc43c5cd22dc606a34f38fd88
プロジェクトによってはバージョン指定したほうがいい場合もあると思うのでそれは適宜。
ページの構成を(サンプル用に)簡素にする
wwwroot の中身を全部削除
Viewsの中身の以下のみになるように他のファイルを削除
https://gyazo.com/d1c93020585dbfa77d447c305530ceb5
Views/Home/Index.cshtm
Views/Shared/_Layout.cshtml
Views/_ViewImports.cshtml
@using AspDotNetCoreAndReact.Models の行を削除
Views/_ViewStart.cshtml
Models の中身は空に(今回は使わないので)
Controllers の HomeController.cs は Index 関数のみ残してあとは削除
https://gyazo.com/013849d85eb5345a907dd9c94c9fa7aa
React の環境構築
パッケージのインストール
プロジェクト(~~.csproj)のある場所で cmd なり Powershell のコンソールを開く。
まずは npm init。
適当にパッケージ名を入れる。
entory poit は webpack.config.js
npm でインストールするものは以下(package.json)
code:package.json
{
"name": "asp-dot-net-core-and-react-package",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"dependencies": {
"@types/react": "^16.7.17",
"@types/react-dom": "^16.0.11",
"awesome-typescript-loader": "^5.2.1",
"css-loader": "^2.0.1",
"glob": "^7.1.3",
"mini-css-extract-plugin": "^0.5.0",
"node-sass": "^4.11.0",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"sass-loader": "^7.1.0",
"source-map-loader": "^0.2.4",
"typescript": "^3.2.2",
"webpack": "^4.27.1",
"webpack-cli": "^3.1.2"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
上記のpackage.jsonを配置した場合は npm installで構築完了。
そうでない場合は以下のコマンドをパッケージの数だけ打つ。
> npm install --save react react-dom @types/react @types/react-dom
> npm install --save awesome-typescript-loader css-loader glob ...
※ --save-devでもいい気はする
なお、各パッケージのバージョンは書いてあるものでなく最新ので良いと思う。
その場合、npm-check-updatesが便利っぽい。以下参照
TypeScriptのコンパイルオプション
プロジェクト直下にtsconfig.jsonを作成し、中身を以下の様に設定する。
code:tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"noImplicitAny": true,
"strictNullChecks": true,
"module": "commonjs",
"jsx": "react",
"target": "es6"
},
"exclude": [
"node_modules",
"wwwroot"
]
}
これを配置するだけで、プロジェクトのビルド時にVisual Studioが*.tsxを*.jsにコンパイルします。
ASP.NET Core MVC (Razor) と React + TypeScript で何か表示する
とりあえず Hello World を表示する。
まだ SCSS(CSS)は使わない。
cshtmlは以下の様に記載
code:index.cshtml
@{}
<div>
<div id="content"></div>
<script src="~/assets/js/Home.bundle.js"></script>
</div>
code:share.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello React</title>
</head>
<body>
@RenderBody()
</body>
</html>
プロジェクト直下にScriptsフォルダを作成し、Scripts/Home/index.tsxを作成。
中身は以下の様に。
code:index.tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const App = (props: { name: string }) => {
return <div>Hello world!! {props.name}.</div>;
};
ReactDOM.render(
<App name="Fuhduki" />,
document.getElementById("content")
);
Webpackの設定と起動
プロジェクト直下にwebpack.config.jsを作成し、中身を以下の様に記載。
code:webpack.config.js
/// <binding AfterBuild='Run - Development' Clean='Run - Development' />
"use strict";
console.log(' ');
console.log('-------------------');
console.log(' ');
module.exports = [
{
mode: 'development',
entry: {
"Home": "./Scripts/Home/index.js",
},
output: {
path: __dirname + "/wwwroot/assets/js",
filename: "name.bundle.js" },
devtool: "source-map",
resolve: {
},
module: {
rules: [
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
]
},
},
{
mode: 'production',
// mode: 'development' と中身は同じ
},
];
webpack.config.js を右クリックして「タスクランナー」を選択
タスクランナーエクスプローラーが開くので、Run → Run -Developtment を右クリック
バインド → ビルド後・クリーンビルドにチェックが入っていることを確認
この状態でコンパイルすると、index.tsxと同じ場所に index.js,index.js.mapが作成される。
Visual Studio のソリューションエクスプローラーから見るとグループ化されている。
https://gyazo.com/950a3a72b857490aeee3975157db39be
wwwrootにassetsフォルダが作成され、その中のjsフォルダにHome.bundle.jsが作成されていればOK。
https://gyazo.com/7858613b51477dbc96dd7de0277e0e87
この状態で実行して、 「Hello world!! Fuhduki.」が表示されてればOK。
https://gyazo.com/bf31010ceb424031136fb8806ae3cb8f
SCSSに対応する
今度はSCSSに対応してスタイルシートを適用する構成にします。
SCSSのコンパイルと配置はWebpackで行います。
プロジェクト直下にStylesフォルダを作成し、index.scssとshare.scssを作成。
code:index.scss
.hello-world {
color: white;
}
code:share.scss
body {
background-color: black;
}
.hello-worldのスタイルを適用するために index.tsxを修正
code:index.tsx
const App = (props: { name: string }) => {
//ここを修正
return <div className="hello-world">Hello world!! {props.name}.</div>;
};
scssをコンパイルするようにwebpack.config.jsに追加
code:webpack.config.js
/// <binding AfterBuild='Run - Development' Clean='Run - Development' />
"use strict";
console.log(' ');
console.log('-------------------');
console.log(' ');
module.exports = [
{
mode: 'development',
entry: {
"Home": "./Scripts/Home/index.js",
},
...
},
{
mode: 'development',
entry: {
"Style": Glob.sync("./Style/*.scss")
},
output: {
path: __dirname + "/wwwroot/assets/css",
},
plugins: [
new MiniCssExtractPlugin({
})
],
module: {
rules: [
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader', options: {
url: false,
sourceMap: true
}
},
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
]
},
},
{
mode: 'production',
entry: {
"Home": "./Scripts/Home/index.js",
},
// mode: 'development' と中身は同じ
},
{
mode: 'production',
entry: {
"Style": Glob.sync("./Style/*.scss")
},
// mode: 'development' と中身は同じ
},
];
この状態でコンパイルする。
wwwrootのassetsフォルダの中にcssフォルダが作成され、その中のjsフォルダにStyle.cssが作成されていればOK。
※この時、同じ場所にStyle.jsも作成され、必要のないファイルだが上手く削除するいい方法が今のところ思いつかない。
https://gyazo.com/7d94fc415fa7f59770df63c4cb6512c9
作られたcssを適用するために_Layout.cshtmlを修正
code:_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello React</title>
<link rel="stylesheet" href="~/assets/css/Style.css" />
</head>
<body>
@RenderBody()
</body>
</html>
この状態で実行して、 黒背景白文字の「Hello world!! Fuhduki.」が表示されればOK。
https://gyazo.com/133b80ddd95bbd4ae8fee6428551443c
まとめ
これでASP.NET Core 2.2 + ASP.NET Core MVC + React + TypeScript + SCSS + Webpack な環境を作成できました。
後は ASP.NET Core MVC でサーバーサイドレンダリングしながら、Reactも適用できる環境が作れました。
スタイルシートはSCSSで適用できるしでそれなりにモダンな環境になったかと思います。
後は ASP.NET Core ↔ React 間の通信をどうするかになります。
単にREST Web API で JSON なデータのやり取りでもいいし、gRPCでの通信も可能な気がします。
そこらへんについては別の記事にしようかなと。
参考にしたページ
この環境を作るのに参考にしたページを以下に。