📘

Blazor WebAssemblyのサンプルアプリをAWS環境へデプロイする

2021/08/21に公開

はじめに

最近WebAssemblyに興味があってちょこちょこ調べているのですが、.NETにもBlazor WebAssemblyというのがあって、.NET絶賛入門中でもあったのでちょっとどんなものなのか触ってみました。
今回は、チュートリアルにあるサンプルの実装とそれをAWS環境にデプロイするまでの流れをまとめたいと思います。

WebAssemblyとは

公式などに詳しく記載がされています。

  • ブラウザ上で動作するオープンバイナリ標準です。
  • 複数の言語で記述されたコードを、ネイティブ水準でブラウザ上で動作させることができます。
    • WebAssemblyとしては異なるプラットフォーム間でのネイティブ水準での動作速度がでることを目標としています。
  • C、C++、Rust 等の低水準言語にとって効果的なコンパイル対象となるように設計されています。

Blazor WebAssembly とは

WebAssemblyのオープンバイナリ標準を使って、.NETコードをブラウザ上で実行させることができます。
どのように実行されるかというと、まず.NETアセンブリにコンパイルされた.NETコードは.NETランタイムとともにブラウザにロードされます。
Blazor WebAssembly が.NETランタイムを初期化して、.NETアセンブリを構成します。
Blazor WebAssemblyはJavaScriptのサンドボックス内で実行され、DOMの操作やブラウザのAPIの呼び出しをJavaScriptを介して行います。
アプリはブラウザの機能に制限されることになりますが、JavaScriptを介してブラウザの全機能にアクセスすることができます。

開発環境の構築

今回はWSL2上で.NET CLI を使って開発していきます。

  • OS : Ubuntu v18.04
  • .NET CLI : .NET 5.0
  • Editor : VSCode

まずは.NET CLIのinstallです。最初にパッケージリポジトリを追加します。

$ wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
$ rm packages-microsoft-prod.deb

完了したらSDKをinstallします。

$ sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-5.0

バージョンが確認できればOKです。

$ dotnet --version
5.0.201

続いてVSCodeにC#の拡張機能 (C# for Visual Studio Code)をinstallします。
デバッグの設定も可能ですが、WSLやCodespacesでのデバッグはサポートされていません。サポートされている環境で動かす場合はDebug ASP.NET Core Blazor WebAssemblyを参考に設定してみてください。

サンプルアプリを作成する

CLIを使ってテンプレートを作成します。

dotnet new blazorwasm -o sample

-o オプションはテンプレートプロジェクトを作成するフォルダ名になります。
sample ディレクトリに移動して下記のコマンドを実行してみましょう。

$ dotnet run

localhost:5000にアクセスすると下記のような画面が表示されるかと思います。
テンプレートのBlazor WebAssembly アプリ

Ctrl + c でアプリを停止できます。

出来上がったプロジェクトを覗いてみると、Razorコンポーネントが作成されているのがわかると思います。
ちなみに描画されるまでの流れとしては、

  • ブラウザからリクエストが送信される
  • index.htmlが返却される
  • アプリの初期化処理が走る。
    • 初期化自体は _framework/blazor.webassembly.js を起点に行われています。
  • Blazorのルーターが読み込まれて、index.razor が表示される

といった感じです。
これらRazorコンポーネントはコンパイル時に.NETクラスに組み込まれてブラウザ上に描画されています。

Todoコンポーネントを追加する

これだけではさすがに味気ないので、作成したテンプレートプロジェクトにTodoコンポーネントを追加してみます。
sample ディレクトリに移動してCLIを使ってrazorコンポーネントを追加します。

$ dotnet new razorcomponent -n Todo -o Pages

PagesディレクトリにTodo.razorが作成されたのがわかるかと思います。
追加されたTodo.razorにpageディレクティブを追加し、/todoと相対URLを指定します。

Todo.razor
@page "/todo"

<h3>Todo</h3>

@code {

}

今度はNavMenu.razorにTodoコンポーネントへのリンクを追加します。

NavMenu.razor
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="todo">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Todo
        </NavLink>
    </li>

ちなみに、dotnet watch run で起動した場合は、コンポーネントの変更を検知してコンパイル、テストの実行、デプロイが開始されるので、再起動などの必要がありません。
NavMenu.razorにTodoコンポーネントのリンクを追加して保存をしたタイミングでサイドメニューにTodoのリンクが追加されるかと思います。

ここまでできたら次にTodoの処理を追加していきたいと思います。
まずTodoを管理するTodoItemを追加します。sampleディレクトリ配下に追加します。

TodoItem.cs
public class TodoItem
{
    public string Title { get; set; }
}

追加したTodoItemのリストをTodo.razorでバインドします。

Todo.razor
@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@code {
    private List<TodoItem> todos = new();
}

次にtodoを登録するフォームとイベントを追加します。

Todo.razor
@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo"/>
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}

Todo.razorを保存すると画面がリロードされて、Todoが追加できるようになっているかと思います。
Todoを追加
これで一旦アプリの作成は終了です。
公式のチュートリアルではもう少し続きがあるのですが、何となく書き方がわかったところでデプロイ方法の説明に移っていきたいと思います。

AWS 環境へデプロイする

今回は自分が使い慣れたAWS環境へのデプロイ方法を説明します。やり方は色々あり、そもそもどうやって動かすかなども決めておく必要があります。
今回はできる限り楽をしたいと思い、最初はAppRunnerを使ってみたのですが、わざわざコンテナにWebサーバーを立てる必要もなくないかと思い、S3上に展開する方式にしました。
最初は手動でS3にアップロードして試していたのですが、AWS .NET deployment tool でS3上に簡単に展開できることを知ったので、こいつを使ったデプロイの方法を説明します。

AWS .NET deployment tool が動く環境を整える

基本的にはReadmeに従って進めれば何も問題ありません。
事前に必要なものとしては、

  • AWS アカウントの作成とcredentialの設定
  • .NET Core 3.1 以上
  • Node.js 10.3 以上
    • 内部的にCDKを使っているため

です。
ローカルに直にこの環境を整えるよりVSCode のRemote Developmentを使った方が楽かと思い、以下のような .devcontainer/Dockerfile を使って実行しました。

.devcontainer/Dockerfile
FROM centos:7
WORKDIR /tmp

RUN yum install -y unzip less zip && \
    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
    unzip awscliv2.zip && \
    ./aws/install
RUN yum install -y https://rpm.nodesource.com/pub_14.x/el/7/x86_64/nodesource-release-el7-1.noarch.rpm && \
    yum install -y nodejs
RUN rpm -Uvh --force https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm && \
    yum install -y dotnet-sdk-5.0
RUN dotnet tool install --global aws.deploy.cli

ENV AWS_ACCESS_KEY_ID=<set your aws access key>
ENV AWS_SECRET_ACCESS_KEY=<set your secret access key>
ENV AWS_DEFAULT_REGION=ap-northeast-1

ちなみに最初はAWS CLI のインストールを省くためにAmazonLinuxをベースにしようと思ったのですが、AWS .NET deployment toolがうまく動かなかったのでCent7にしました。

デプロイする

環境が出来上がってしまえばあとはコマンドを1回実行するだけです。
.csproj ファイルがあるディレクトリに移動し下記コマンドを実行します。

$ dotnet aws deploy

コマンドを実行するとRegion選択を迫られますのでお好きなregionを選択ください。
このあとも色々聞かれますがデフォルトを選択すればOKです。

完了するとエンドポイントのURLが表示されるのでアクセスすると、作成したサンプルアプリが表示されるかと思います。
S3にDeploy
これで一通りの説明は以上になります。

後片付け

最後に、そのまま放置もまずいので後片付けだけして終了です。
まずdeployment toolで作成したstackの名前を確認します。

$ dotnet aws list-deployments

今回の場合は sample という名前になっていたかと思います。
この名前を指定して削除コマンドを実行したら完了です。

$ dotnet aws delete-deployment sample

コンソールから確認してもstackやbucketが削除されているのが確認できると思います。

まとめ

deployment toolをinstallするのが若干面倒かもしれませんが、それさえできてしまえば、作成からデプロイまで思ってた以上に簡単にできた印象です。
ドメインとか証明書の設定もdeployment toolでできるのかなど、まだわからないこともあるので、そこはこれから調べていきたいと思います。

参照

Discussion