【Day24】アセットやビルドに関する記事【QAC24】


# 終局

コード的な記事は少し終わりにしましょう！

現在は`pnpm tauri dev`コマンドで実行していますが、それを`.exe`ファイルにしてあげてやりたいと思います。

# ビルドの前準備

これまで、TypeScript のコード内でエラーがあってもまぁ動いたと思います。
（特に、VSCode で黄色に表示されるような、警告と呼ばれるようなものも）

> 例として挙げるなら、未使用変数や未使用インポートなど。

そもそも論として、ブラウザ (WebView) では、TypeScript は動作しません。

`pnpm tauri dev`では、Vite がなんかうまい事良しなにしてくれるので、TypeScript のコードそのままで動いていました。

## Vite？

ヴィートと呼ばれるこの子は、フロントエンド開発をなんかうまい事やってくれる子です。

今回までの記事で Vite がした仕事は、TypeScript で書いてたコードをなんかうまい事ブラウザで動かせるようにしてくれていました。
これは、Vite の開発サーバーというものです。

## TypeScript のビルド

ビルドを行っていくにあたって、これから TypeScript のコードを JavaScript に変換されて行くのですが、その際に、TypeScript のコードにエラーがあるとビルドが失敗します。
まずは、そこら辺のエラーを削除していきましょう。

```sh
$ pnpm tsc
```

このコマンドを入れてみましょう。

エラーがあったらなんか出てきます。
正常だったらなんも表示されずにコマンドが終わるかなって思います。

...

`tauri-specta`を入れているそこのあなた、多分エラーになると思います。
これはよくない。

VSCode で`src/bindings.ts`を開いてみると、警告が表示されていると思います。

これは...手動で消してください。

# ビルド

さぁ戻ってきました。
まずは試しにビルドしてみましょう。

```sh
$ pnpm tauri build
```

なんの問題もなければ、`Finished`とか出てきて成功すると思います。

その出力を見てみると、どうやら`src-tauri/target/release/bundle/`に`.exe`ファイルと`.msi`ファイルが生成されているようです。
試しに実行してみましょう。

今回何も触ってないので、マップエディター画面が出てくると思うのですが...
あれ？タイルパレットが出ませんね？

どころか、何も表示されません。多分。

# アセット？バンドル？

## 新規ウィンドウ...

まずはタイルパレットのウィンドウについてお話ししましょうか。

ビルドされた結果については、`dist`というフォルダに出力されていると思います。
ここを見ると、HTML ファイルについては`index.html`しかないと思います。

一方、多分新しいウィンドウのやつは別の HTML ファイルを作ったと思います。が、ここにはない....

これは、Vite の仕様で、デフォルトでは`index.html`のみがバンドルされて、設定を変更しないと他の HTML ファイルはバンドルされないのです。

...けど、マップエディターを触ってる間は`pnpm tauri dev`でやって、マップが完成して、作った MapClass を置いて初めてビルドしたら良いんじゃないんですかね。えぇ。

## 画像？

同様に`dist`フォルダを覗いてみると、画像ファイルがないと思います。

これじゃあタイル画像も読み込まれないし、なんもできないですよね。

当然このままでいいわけもなく、設定を変えていきましょう。

# Tauri の Resource 機能

Tauri は、様々なファイルを同梱するための方法として`resource`という機能を有しています。

まずは`src-tauri/tauri.conf.json`の中の`app`の`bundle`の中に、`resources`というキーを追加してみましょう。

```json
    "resources": {
      "../src/assets/rpg": "resources/rpg"
    }
```

この設定で、`../src/assets/rpg`をリソースの`resources/rpg`として利用できるようになりました。
(左を右にマッピングするような形。ファイルも実際にコピーされる。)

そのため、TypeScript 内のコードも編集しましょう。
タイルを生成する際に`src/assets/rpg`を参照していると思いますが、これを`resources/rpg`に変更してください。

次にこの 2 つをインポートしましょう。

```ts
import { resolveResource } from "@tauri-apps/api/path";
import { convertFileSrc } from "@tauri-apps/api/core";
```

そして、fetch に渡しているパスを`await resolveResource(...)`で囲み、更にそれを`convertFileSrc(...)`で囲んでください。

```ts
await fetch(
  convertFileSrc(await resolveResource("resources/rpg/hogehogeTile.png"))
);
```

`await resolveResource`で、`resources/...`のパスを実際にそのファイルがあるパスへ変換します。
ですがこれは、ファイルのパスを返すだけで、`fetch`に渡すときは http(s)の URL が必要です。

そこで、`convertFileSrc`を使うことで、`http://assets:localhost/...`のような URL に変換してくれます。

ただ、これだけではまだダメで、[CSP](https://developer.mozilla.org/ja/docs/Web/HTTP/CSP)の観点から、通常ではこの Assets のリンクにアクセスすることは出来ません。
また、Tauri ではファイルアクセスに対して厳しいセキュリティーを持っているので、リソースにアクセスするための権限設定も必要です。

まずは`fs-plugin`をインストールしましょう。

```sh
$ pnpm tauri add fs
```

そして`src-tauri/capabilities/default.json`で`fs:allow-resource-read-recursive`を追加します。

```json
{
  "permissions": [
    ...
    "fs:allow-resource-read-recursive"
  ]
}
```

そしてさらに`permissions`の中に、アクセス許可をしたいパス、今回はリソースなので以下のように追加します。

```json
{
  "permissions": [
    ...
    "fs:allow-resource-read-recursive",
    {
      "identifier": "fs:scope",
      "allow": [{ "path": "$RESOURCE/**" }]
    }
  ]
}
```

分かりにくいですが、`$RESOURCE`と`resources`は別物です。
`$RESOURCE`はリソースのパスを指します。
`resources`は勝手に名付けただけで、何でもよくて...

この`resources`を正式なパスで表すなら`$RESOURCE/resources`となります。

最後に、`src-tauri/tauri.conf.json`の`app`の`security`という項目を以下のように編集します。

```json
    "security": {
      "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost",
      "assetProtocol": {
        "enable": true,
        "scope": ["$RESOURCE/**"]
      }
    }
```

これで実行してみると...？

# 結果

~~ﾜｻﾞｯﾌﾟ (すいません時間無くて中途半端に切ってしまいました) ~~

この作業についてはあんまり日本語ドキュメントがなかったので軽くですが書いてみました。

ここから先は公式ドキュメントなどをモグモグしながら君自身で成長していっておくれ！

ちなみに CSP の設定をサンプルのままにしているため、このままだと場合によっては恐ろしいことが起こるかも。

以上で！