5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

BlazorAdvent Calendar 2020

Day 11

BlazorアプリケーションをNetlifyにデプロイする(Netlify Identityによる認証サンプル付き)

Last updated at Posted at 2020-12-10

概要

Blazor WebAssemblyアプリケーションと静的サイトのホスティングサービスのNetlifyに関して下記の点を説明しようと思います。

  • NetlifyにBlazorアプリケーションをデプロイする方法の紹介
  • Netlifyの認証サービス(Netlify Identity)をBlazorで使用してログイン機能の実装

背景

Blazor WebAssembly含めSPAアプリケーションのウリの一つとして、従来のWEBアプリケーションのようなサーバ実行環境を必要とせず、htmlファイルなど静的なファイルをホスティングするだけのサービスでアプリケーションがデプロイできる点が挙げられます。

AWS,GCP,Azure等のメジャーなクラウドサービスも静的サイトをホスティングするサービスを提供していますが、個人のちょっとした趣味で開発する上ではシンプルかつ無料もしくは、無料枠が大きいサービスを使用できるのが望ましいです。

そこでよく取り上げられるのが、Firebase,GitHub Page,Netlifyといった静的サイトのホスティングサービスになるかと思います。

Blazorの例ですとGitHub Page、Firebaseのデプロイの手順を見かけます。
(手前味噌ですが以前私のほうでも記事を書いています。)
AdventCalenderで@jsakamotoさんがGitHub Pageで簡単にデプロイできるためのライブラリをNugetで公開していますね。
Blazor WebAssembly アプリの GitHub Pages への発行を、より楽にする

今回はNetlifyにBlazorアプリケーションをデプロイする方法と認証機能の実装を試してみたいと思います。
本題ではないため詳細は省きますが、Netlifyの特徴として下記の点などが挙げられます。

  • 無料枠が大きい
  • SPAで使用するための認証機能やREST API(AWS Lambdaベース)が提供されている
  • CD/CI機能との連携

一方でFirebaseで提供されている、DBなどのデータストア機能は提供されていないので別サービスを使用する必要があります。

NetlifyにBlazorアプリケーションをデプロイする方法

前提条件

  • 対象はBlazor WebAssembly
  • GitHub Actionによる連携 (GitHub上のソースコードをNetlifyにデプロイする。)

事前準備

予め下記を実施しておいてください。

  • BlazorのソースコードをGitHub上にリポジトリとして作成する
  • Netlifyのアカウントを作成済みでGitHubアカウントと連携させる
  • (無料プランだけであればクレカ不要でGitHubアカウントでサインアップするだけで簡単に作成可能です。)

1.各種トークンの取得

今回はGitHub Actionとの連携を行い、GitHubにコミットしたソースをビルドしてNetlifyにデプロイします。
そのためにはGitHub Action側に連携を行うための各種情報が必要になるので取得を行います。

トークンの発行

Netlifyの個人ページにアクセスして、New  access tokenを選択します。

netli1.PNG

入力欄にNETLIFY_AUTH_TOKENと入力して、Generate tokenを選択します。
netli2.PNG

トークンが発行されるのでメモします。
netli3.PNG

サイトIDの取得

次にサイトIDの取得を行います。
先にIDの取得だけしたいので、フォルダと空のindex.htmlファイルを作成してください。


dummy (任意のフォルダ名)
|- index.html (空のファイル)

Siteのページにアクセスして、Want to...のエリアにdummyフォルダをドラッグ&ドロップしてください。

netli4.PNG

ダミーのサイトが作成されます。
https://~のURLが今後デプロイ後にも使われるURLなのでメモします。
次にSite settingsを選択します。

netli5.PNG

API IDの部分に記載された値をメモします。

netli6.PNG

2.GitHub Actionの設定

Netlifyから取得した情報を登録してGitHub Actionでデプロイできるように設定します。

GitHubへのシークレットの登録

デプロイしたいBlazorのGitHubレポジトリを開いて、Settings→SecretsからNew repository Sercretを選択します。

netli7.PNG

Netlifyで取得した2つのキーを登録します。
なお。APPIDはNETLIFY_SITE_IDというキーで設定します。

netli8.PNG

下記のように2つのSecretsが登録できればOKです。
netli9.PNG

GitHub Actionの作成

Actionのタブを選択します。

netli10.PNG

スクロールして、More continuous integration workflows...を選択して .NET Coreの項目を見つけてSet up this workflowを選択します。

netli12.PNG

dotnet-core.ymlの編集画面が表示されます。
このymlファイルを編集して、BlazorアプリをNetlifyにデプロイできるように設定します。

netli13.PNG

具体的に実施することとしては、下記になります。

  • dotnetコマンドを使用してビルドして、発行
  • netlifyのCLIでデプロイ

下記の例では、.NET5.0.100でビルドを行ってデプロイしています。


name: BlazorNetlifySample #任意の名称を指定
on: [push] #push時に実行

jobs:
  build:
    runs-on: ubuntu-latest #最新のubuntu環境をビルドに使用。(バージョンを固定したほうが良いかも)
    steps:
    - uses: actions/checkout@v1
    - name: Setup .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: 5.0.100 #ビルドに用いる.NETバージョン(2020/12/08時点での最新SDK ver)
    - name: Build with dotnet
      run: dotnet build --configuration Release
    - name: Publish Blazor webassembly using dotnet 
      #distディレクトリにpublish
      run: dotnet publish -c Release --no-build -o dist
    - name: Publish generated Blazor webassembly to Netlify
      uses: netlify/actions/cli@master #uses Netlify Cli actions
      env: # Netlifyの設定を環境変数として定義
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
      with:
          args: deploy --dir=dist/wwwroot --prod #dist/wwwrootディレクトリをデプロイ
          secrets: '["NETLIFY_AUTH_TOKEN", "NETLIFY_SITE_ID"]' 

ymlファイルの編集が終わったら、Start Commit → Commit new fileを選択します。

netli14.PNG

以上で、Actionの設定は完了です。
今後GitHubにpushする度に自動でデプロイが実行されます。
(本格的に使用するならば、relaseブランチやmainブランチなど特定のブランチに限定してデプロイするなどの設定を行う必要があるかと思います。)

ビルドの確認

Actionタブを選択
action.PNG

Create dotnet-core.ymlが☑マークになっていればビルド完了です。
(ビルドに2-3分程度かかります。)

action2.PNG

Netlifyの設定時にメモしたURLにアクセスして下記のようにBlazorアプリが起動すればデプロイ成功です。
netli15.PNG

以降、GitHubのmainにpushするたびにこのワークフローが実行されてNetlifyにデプロイされます。

git.PNG

個々のコマンド実行時の実行結果が確認できるので、どの処理に問題があるのかも判別しやすいかと思います。

build.PNG

Netlifyにデプロイする手順は以上です。

Netlifyの認証サービス(Netlify Identity)をBlazorで使用してログイン機能の実装

次にNetlifyの機能をBlazorに組み込む方法を考えてみましょう。
Netlifyのサービスの1つであるNetlify Identityを使ってログイン機能の実装を考えてみます。
Netlify Identityには、下記の方法でログイン機能が実装できます。

ウィジェットの使用を使用することでjsファイルの参照とタグを配置するだけでお手軽にログインが実装できますが、Blazorの動的にタグを配置するような仕組みだとうまくコンポーネントに適応されないようで諦めて、後者のGoTrue APIによる実装を行いました。

初期アカウントの登録等に関しては割愛しますので、別途登録等を行ってください。
既に登録済みのアカウントを使用した例を紹介します。

  1. GitHubからgotrue.jsファイルを取得して、wwwwroot/jsに配置してindex.htmlに参照を追加。
  2. 下記のようなGoTrueAPIをラップしたjsを作成する
netlifyIdentity.js

let auth;
function initAuth() {
    auth = new GoTrue({
        APIUrl: 'https://取得したホスティングのURL/.netlify/identity',
        setCookie: true
    });
}

async function loginAsync(email, passowrd) {
    return await new Promise((resolve, reject) => {
        auth.login(email, passowrd, true)
            .then((response) => {
                const result = { accessToken: response.token.access_token, userId: email };
                resolve(result);
            })
            .catch((error) => {
                reject(error);
            });
    });
}

async function logoutAsync() {
    return await new Promise((resolve, reject) => {
        const user = auth.currentUser();
        if (user) {
            resolve(null);
            return;
        }
        user.logout()
            .then(response => {
                resolve(response);
            })
            .catch(error => {
                reject(error);
            });
    });
}

function getCurrentUser() {
    const user = auth.currentUser();
    if (user) {
        return { accessToken: user.token.access_token, userId: user.email }
    } else {
        return null;
    }
}

次に、これらを呼び出すサービスをクラスを作成します。
AuthenticationStateProviderなどの実装に関しては以前の認証方法に関して記載した記事で説明しているので参照ください。
https://qiita.com/nobu17/items/91c96ede1bd043fe1373

NetlifyAuthService.cs

    public class NetlifyAuthService : IAuthService
    {
        private readonly IJSRuntime _JSRuntime;
        private readonly AuthenticationStateProvider _authenticationStateProvider;

        public NetlifyAuthService(AuthenticationStateProvider authenticationStateProvider, IJSRuntime jSRuntime)
        {
            _authenticationStateProvider = authenticationStateProvider;
            _JSRuntime = jSRuntime;
        }

        public async Task InitAsync()
        {
            await _JSRuntime.InvokeVoidAsync("initAuth");
            var user = await _JSRuntime.InvokeAsync<NetlifyLoginResult>("getCurrentUser");
            if (user == null)
            {
                await LogoutAsync();
            }
        }

        public async Task<LoginResult> LoginAsync(LoginModel loginModel)
        {
            try
            {
                var result = await _JSRuntime.InvokeAsync<NetlifyLoginResult>("loginAsync", new object[] { loginModel.UserID, loginModel.Password }).ConfigureAwait(false);
                // トークンを取得
                var res = new LoginResult()
                {
                    IsSuccessful = true,
                    IDToken = result.AccessToken
                };
                await ((SpaAuthticateProvider)_authenticationStateProvider).MarkUserAsAuthenticated(loginModel.UserID, res.IDToken);
                return res;
            }
            catch (Exception e)
            {
                return new LoginResult()
                {
                    IsSuccessful = false,
                    Error = e
                };
            }
        }

        public async Task LogoutAsync()
        {
            await _JSRuntime.InvokeAsync<string>("logoutAsync", new object[] { }).ConfigureAwait(false);
            await ((SpaAuthticateProvider)_authenticationStateProvider).MarkUserAsLoggedOut();
        }
    }

    [JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
    public class NetlifyLoginResult
    {
        public string UserId { get; set; }
        public string AccessToken { get; set; }
    }

これを組み込むことで下図のようなログイン機能を実装しています。

login2.gif

時間がなかったため、かなり雑で本当に少し参考になる程度ですが下記にソースコードも入れていますので興味ある方は参照ください。

GitHub Link

まとめ

Blazor WebAssemblyをGitHub Actionを使用してNetlifyにデプロイする方法を紹介しました。
GitHubと連携してデプロイ可能な点は便利ですね。
今後、Functionとの連携なども試す事ができればと思います。

下記のページなどを参考に試してみましたので、より詳細な情報をなどを確認したい場合には下記も合わせて参照ください。

Hosting Blazor on Netlify using Github Actions (Part 1 of Series)
Deploying a .NET Core Blazor App to Netlify using GitHub Actions

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?