Blazorで作成したウェブサイトをGitHub Pagesで公開する

# 概要

Blazorのクライアント版をGitHub Pagesで公開するための手順メモです。
以前公開した[Firebase上にホスティングする場合](https://qiita.com/nobu17/items/67c11cf622f2e4721635)と比較して、色々と手間がかかり大変でしたが何とか公開できたのでメモとして残しておきます。

## 環境及び前提

使用している.NET Core及びBlazorのテンプレートのバージョン等は下記です。

-  .NET Core 3.0 Preview SDK 3.0.100-preview7-012821
-  Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview7.19365.7
-  Visual Studio 2019 Preview

また、GitHub Pagesはdocsフォルダを使った公開方法になります。

## wwwrootフォルダ内の変更

Blazorのwwwroot以下の各種編集を行います。

### 既定URLの変更

デフォルトの設定のままだと、cssなどの各種ファイルの参照URLが
https://アカウント名.github.io/
となってしまうため
https://nobu17.github.io/リポジトリ名/
となるように、baseタグ内のhrefのデフォルト値は"/"となっていますが、"/リポジトリ名/"に変更します。


```html:index.html
<!DOCTYPE html>
<html>
<head>
    //略
    // / → /リポジトリ名/
    <base href="/RadzenBlazorTest/" />
    //略
</head>
<body>
    <app>Loading...</app>

    <script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

```
(2019/11/30追記)
NavigationManagerでページ遷移する際には、先頭に"/"をつけないように注意してください。
OK："counter"
NG："/counter"


(2020/12/03追記)

VisualStudioでのデバッグ実行時にうまく動くようにProperties\launchSettings.jsonの値を変更します。

applicationUrlのURLの末尾にもリポジトリ名を追加します。

```json:launchSettings.json
{
  "iisSettings": {
    ...
    "iisExpress": {
      "applicationUrl": "http://localhost:58331/RadzenBlazorTest",
      "sslPort": 44314
    }
  },
 ...
```

### GitHub PagesでSPA対応を行うための設定

Blazorだけではなく、ReactなどのSPAをGitHub Pagesで公開するために使用するテクニックで、
ページが見つからないと404.htmlを表示する特性を利用する設定を行います。

詳細は下記
https://github.com/rafrex/spa-github-pages

やることとしては、

framework/blazor.webassembly.jsを読み込む前に参考先にあるスクリプトを追記する。
<!-- Start Single Page Apps for GitHub Pages --> から
<!-- End Single Page Apps for GitHub Pages -->　まで

```html:index.html
<!DOCTYPE html>
<html>
<head>
    //略
</head>
<body>
    <app>Loading...</app>

    <!-- Start Single Page Apps for GitHub Pages -->
    <script type="text/javascript">
        // Single Page Apps for GitHub Pages
        // https://github.com/rafrex/spa-github-pages
        // Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License
        // ----------------------------------------------------------------------
        // This script checks to see if a redirect is present in the query string
        // and converts it back into the correct url and adds it to the
        // browser's history using window.history.replaceState(...),
        // which won't cause the browser to attempt to load the new url.
        // When the single page app is loaded further down in this file,
        // the correct url will be waiting in the browser's history for
        // the single page app to route accordingly.
        (function (l) {
            if (l.search) {
                var q = {};
                l.search.slice(1).split('&').forEach(function (v) {
                    var a = v.split('=');
                    q[a[0]] = a.slice(1).join('=').replace(/~and~/g, '&');
                });
                if (q.p !== undefined) {
                    window.history.replaceState(null, null,
                        l.pathname.slice(0, -1) + (q.p || '') +
                        (q.q ? ('?' + q.q) : '') +
                        l.hash
                    );
                }
            }
        }(window.location))
    </script>
    <!-- End Single Page Apps for GitHub Pages -->

    <script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

```

また上記レポジトリ内にある404.htmlをコピーしてindex.htmlと同じ階層に配置します。

```html:404.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Single Page Apps for GitHub Pages</title>
    <script type="text/javascript">
      // Single Page Apps for GitHub Pages
      // https://github.com/rafrex/spa-github-pages
      // Copyright (c) 2016 Rafael Pedicini, licensed under the MIT License
      // ----------------------------------------------------------------------
      // This script takes the current url and converts the path and query
      // string into just a query string, and then redirects the browser
      // to the new url with only a query string and hash fragment,
      // e.g. http://www.foo.tld/one/two?a=b&c=d#qwe, becomes
      // http://www.foo.tld/?p=/one/two&q=a=b~and~c=d#qwe
      // Note: this 404.html file must be at least 512 bytes for it to work
      // with Internet Explorer (it is currently > 512 bytes)
      // If you're creating a Project Pages site and NOT using a custom domain,
      // then set segmentCount to 1 (enterprise users may need to set it to > 1).
      // This way the code will only replace the route part of the path, and not
      // the real directory in which the app resides, for example:
      // https://username.github.io/repo-name/one/two?a=b&c=d#qwe becomes
      // https://username.github.io/repo-name/?p=/one/two&q=a=b~and~c=d#qwe
      // Otherwise, leave segmentCount as 0.
      var segmentCount = 0;
      var l = window.location;
      l.replace(
        l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
        l.pathname.split('/').slice(0, 1 + segmentCount).join('/') + '/?p=/' +
        l.pathname.slice(1).split('/').slice(segmentCount).join('/').replace(/&/g, '~and~') +
        (l.search ? '&q=' + l.search.slice(1).replace(/&/g, '~and~') : '') +
        l.hash
      );
    </script>
  </head>
  <body>
  </body>
</html>

```

### .nojekyllの作成

GitHub Pagesでは_から始まるフォルダがデフォルトでは読み込まれないため、Blazorでビルド時に作成される_frameworkフォルダなどが無視されてしまいます。
これを回避するために、
.nojekyll
といった空のファイルを作成しておきます。

### フォルダ構成まとめ

上記の対応で下記のようなフォルダ構成になります。

```dir
wwwroot
├ .nojekyll
├ 404.html
├ index.html
…(略)
```

## ホスティングするファイルの準備

GitHub Pagesでホスティングするために、docsフォルダ以下に配置するファイルを準備します。

作成したBlazorのプロジェクトをローカルに出力します。
Visual Studioのソリューションエクスプローラから右クリック→発行を選択します。

![vs1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149198/374bc2db-c740-ed6b-c38e-9dea138af45b.png)

発行先の選択で、フォルダーを選択し、出力先を指定します。
発行ボタンを押下してファイルを出力します。
![vs2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149198/7a7330a9-e794-3cb8-ab97-aad24a726cb0.png)

"出力したフォルダ/プロジェクト名/dist"
以下にindex.htmlが作成されるので、distフォルダ内の全ファイル、フォルダをコピーして

```dir
docs/
├ .nojekyll
├ 404.html
├ index.html
…(略)
```


となるようにして、GitHubにpushします。

### アップロードされないフォルダの強制push

pushしても、"docs\\_framework\\_bin"がpushされていない状態となります。
(GitHubのデフォルトのルール？)

強制的にaddしてpushすることで対応します。

```cmd
git add -f docs/_framework/_bin
git push
```

これで作業は終了です。
実際にアクセスして確認してみましょう。



(2020/12/03追記)
久しぶりに実施すると、Failed to find a valid digest in the 'integrity' ~ というエラーが出るようになっていました。

![error.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149198/5befee1d-292e-424a-7da4-076a52229a90.png)

下記に対策方法が載っていました。
https://github.com/dotnet/aspnetcore/issues/19907

以下の手順を実施することでうまく動くようになりました。

1.docsフォルダ以下の中身を一度削除
2.docsフォルダ内に.gitattributesファイルを作成してファイル内に* binaryと記載して、pushする
3.docsフォルダ内に削除したファイルを再び入れてpushする



## 最後に

ということで、GitHub PagesでBlazorのサイトをホスティングする手順でした。
色々と試行錯誤しましたが、何とかアクセスできるまでたどり着けました。
この手順で公開したサイト及びソースは下記になります。
(下記のソース内容BlazorのUIフレームワークを使用したものとして、別途記事を近日公開予定で作成中です。)

ホスティング
https://nobu17.github.io/RadzenBlazorTest/
ソース
https://github.com/nobu17/RadzenBlazorTest/

正直色々と大変なので、ソースコードと一緒に管理したい以外の目的では素直にFirebaseで公開したほうが楽で良いと思います。。。


参考にしたサイトや記事等
https://stackoverflow.com/questions/54260158/properly-publishing-deploying-a-blazor-project-to-github-pages
https://github.com/aspnet/Blazor/issues/942
https://github.com/rafrex/spa-github-pages
https://github.com/blazor-demo/blazor-demo.github.io
https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/blazor/client-side?view=aspnetcore-3.0