この記事は C# Advent Calendar 2020 22日目の記事です。
ここで紹介したサンプルプロジェクトは、GitHubで公開しています。
Sumples/TypeScriptTest at master · Atria64/Samples
はじめに
今回はC#でのSPA開発が可能となる画期的なフレームワーク「Blazor」を話題に記事を投稿しようと思います。
Blazorが何かよくわからない方は、以下の記事を参照すると良いかもしれません。
また、Blazorを利用すると以下のようなものが作れます。
-
Atria64/CUIPortfolio: CUI風Portfolio
- Blazorで作成したCUI風のサイトです
-
Atria64/RandomSushi
- 某スシローのメニューからランダムで選定する
クソアプリです
- 某スシローのメニューからランダムで選定する
しかしここで断っておくと、初学者にとってこの記事の内容は少し難しいかもしれません。(難しく書いてすみません)
雰囲気だけでも楽しんでいただけたらなと思います。
BlazorでTypeScriptを導入する上で注意しなければならない事
はじめに注意しておかなければならないことは、C#とTypeScript間に型情報などは渡せないということです。
「じゃあ意味ねぇじゃねぇか」という人もいるかもしれませんが、少なからずメリットもあります。
Blazor/TypeScriptが提供するもの
Blazor/TypeScriptの構成では残念ながらC#/TypeScript間で型情報を渡すことができません。
しかし、TypeScript自身の型システムやコンパイル時のチェックの恩恵を受けることができます。
また、JavaScript恐怖症の方やTypeScriptを愛する人にとって、BlazorでTypeScriptを利用することができるというのは朗報であるはずです。
環境
- Visual Studio 2019
- ASP.NET Core 3.1.9
- Microsoft.AspNetCore.Components.WebAssembly.* 3.2.1
- Microsoft.TypeScript.MSBuild 4.2.1
導入方法
今回目指す動作
今回はTypeScriptを用いて、以下2つの動作をさせるのを目的とします。
- ボタンを押したときに、テキストエリアに書かれている文字列をalertする。(返り値なしの関数呼び出し)
- ボタンを押したときに、テキストエリアに書かれている文字列を加工してボタン名を変更する。(返り値ありの関数呼び出し)
ここまで簡単な操作であればTypeScriptを使うまでもありませんが、サンプルということでご容赦ください。
プロジェクトの作成
新しいプロジェクトの作成→Blazorプロジェクト→Blazor WEBAssembly App
の順にプロジェクトを作成します。
今回ここで作成するプロジェクト名は TypeScriptTest
にします。
詳しくは割愛しますので、他のサイトなどを御覧ください。
テスト用ページの作成
TypeScriptを呼び出すためのテストページを作成します。
Pages
からIndex.razor
ファイルを開きます。
今回は2つのボタンと一つのテキストエリアを必要とするため、以下のようにrazorファイルを書き換えます。
@page "/"
<h1>TypeScriptTest</h1>
<input @bind="text" @bind:event="oninput" />
<button @onclick="TsAlertClick">TsAlert</button>
<button @onclick="TsEditTextClick">@TsEditText</button>
@code{
string text;
string TsEditText = "TsEditText";
private void TsAlertClick()
{
}
private void TsEditTextClick()
{
TsEditText = "hoge";
}
}
TypeScriptファイルの作成
新しい項目の追加(Ctrl+Shift+A)からwwwroot
直下にTypeScriptファイルを作成します。
今回はTypeScript.ts
とします。
TypeSctipr.tsの中身は以下のようにします。
namespace Test {
class Functions {
//与えられた文字列をalertで表示します
public showAlert(message: string){
alert(message);
}
//与えられた文字列を編集して返します。
public editText(message: string): string {
return message+" : edited";
}
}
export function Load(): void {
window['Functions'] = new Functions();
}
}
Test.Load();
ビルドの構成
TypeScriptファイルが完成したので、ビルドの構成を行います。
まずはじめにMicrosoft.TypeScript.MSBuild
を追加します。
Microsoft.TypeScript.MSBuildの追加
NuGetパッケージマネージャを起動して、検索欄にMicrosoft.TypeScript.MSBuild
と入力します。
そして執筆時点での最新バージョンであるMicrosoft.TypeScript.MSBuild4.1.2
をインストールします。
インストール完了後、.csproj
ファイルを編集します。
.csprojファイルの編集
.csprojファイルに、TypeScriptファイルをコンパイルするような命令を記述します。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RazorLangVersion>3.0</RazorLangVersion>
<TypeScriptToolsVersion>4.0</TypeScriptToolsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="3.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Build" Version="3.2.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="3.2.1" PrivateAssets="all" />
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="4.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Net.Http.Json" Version="3.2.0" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="wwwroot\TypeScript.ts" />
</ItemGroup>
</Project>
<PropertyGroup></PropertyGroup>
には<TypeScriptToolsVersion>4.0</TypeScriptToolsVersion>
を追加してあげることで、プロジェクトのコンパイル時に使用するTypeScriptのバージョンをMSBuildに通知させます。
これを記述しなかった場合、MSBuildはシステムにインストールされている最新バージョンを利用します。
また、<ItemGroup></ItemGroup>
に<TypeScriptCompile Include="wwwroot/TypeScript.ts" />
を追加することで、MSBuildにどのファイルをビルドするかを通知させます。
ここで一度ビルドを走らせてみましょう。
うまくビルドが走った場合、TypeScript.map
とTypeScript.js
が新しくwwwroot
直下に生成されているはずです。
TypeScriptでコンパイルしたJavaScriptを呼び出す
あとは従来のJavaScriptをInvokeする手順とほとんど一緒です。
index.htmlへのタグ追加
wwwroot
直下のindex.html
に<script src="TypeScript.js"></script>
の一行を追加します。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>TypeScriptTest</title>
<base href="/" />
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
</head>
<body>
<app>Loading...</app>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="TypeScript.js"></script>
</body>
</html>
IJSRuntimeを用いた呼び出し
IJSRuntimeをinjectした後、InvokeVoidAsync
やInvokeAsync<T>
を利用してJavaScriptメソッドを呼び出します。
コードは以下のようになります。
@inject IJSRuntime JSRuntime
@page "/"
<h1>TypeScriptTest</h1>
<input @bind="text" @bind:event="oninput" />
<button @onclick="TsAlertClick">TsAlert</button>
<button @onclick="TsEditTextClick">@TsEditText</button>
@code{
string text;
string TsEditText = "TsEditText";
private void TsAlertClick()
{
JSRuntime.InvokeVoidAsync("Functions.showAlert", text);
}
private async Task TsEditTextClick()
{
TsEditText = await JSRuntime.InvokeAsync<string>("Functions.editText", text);
}
}
JavaScriptの呼び出しがイマイチわからない場合
僕の説明がわかりにくかった場合は以下の記事などを参考にすると良さそうです。
- ASP.NET Core Blazor で .NET メソッドから JavaScript 関数を呼び出す | Microsoft Docs
- BlazorアプリケーションでC#のコードからJavaScriptを呼び出す
動作確認
実際にビルドし実行するとTypeScriptのコンパイラが走りJavaScriptが生成され、うまく呼び出すことができるようになっています。
テキストエリアに書かれている文字列のalert
テキストエリアに書かれている文字列を加工したボタン名の変更
おわりに
今回はBlazorにTypeScriptを導入する試みを行ってみました。
この知見が誰かの役に立つことがあれば幸いです。
また、今回作成したプロジェクトはGitHubでも公開しておりますので、ぜひお役立てください。
Sumples/TypeScriptTest at master · Atria64/Samples
次回の C# Advent Calendar 2020 23日目は @nqdior さんです!