Tauri 2.0 x Next.js 初期セットアップ（疎結合,Web開発者向けver）

## Summary

- ミニマムな Tauri x Next.js の Template Repository の作成手順の忘備録です
- 公式ドキュメントの手順と違う部分として、Frontend ディレクトリに Next.js を完全に閉じ込めます (できるだけ公式 doc の通りに進める)
  - そのため、Tauri の文脈をほとんど意識せずに進められます。また、 Next.js のリポジトリを`git clone`やサブモジュールで組み込むことが可能です
- アプリのビルドを CI/CD で Windows, Mac, Linux に対応で自動化をします

## なぜ Tauri

- Tauri はネイティブアプリを Web のフロントエンドスタックを使用して作るためのツールです
- 主に Electron という同様のネイティブアプリを作るツールがあり比較されますが、Tauri は Rust 製で Electron よりもパフォーマンスが良いです
- ネイティブアプリの利点になりますが、サーバーを置かなくて良くなります
  - 小さなリソースでも、Web のサーバーを置くとどうしても発生してしまう管理コストなどを無視できます
- フロントエンドのライブラリやフレームワークをそのまま使用してデスクトップアプリを作れます
  - Rust を一切使わずに、アプリを作成できますが、高速化したい場合は Rust 側で定義した関数を API として呼び出すことができます
- クロスコンパイルにも対応しています (Windows, mac, linux)
  - モバイルはまだ不安定

https://zenn.dev/kumassy/books/6e518fe09a86b2/viewer/fd305b

## Stack

- Bun
- Next.js
  - お好きなフレームワーク(React, TailwindCSS など)
- Tauri

## Process

以下の手順では、tauri-nextjs-template というプロジェクト名で進めています

すべての手順を終えて Template Repository にしていただいてもよいですし、プロジェクト名を置き換えて進めてそのまま使用していただいてもよいです

### 環境構築

- Rust のインストール
- OS 依存の依存パッケージのインストール

こちらはコマンド打つだけなのと OS 差異が激しいので割愛

https://v2.tauri.app/start/prerequisites/

### Tauri プロジェクトの作成

`bun create tauri-app`

#### 対話形式で設定

```markdown
project name
  - tauri-nextjs-template

identifier
  - tauri-nextjs-template (そのまま Enter)

TypeScript / JavaScript
  - TypeScript

Choose your package manager
  - Bun

Choose your UI template
  - Vanilla (後でNext.jsに変更しやすい)
```

Tauri のプロジェクトが tauri-nextjs-template ディレクトリ以下に作成されます。

Git clone して作業している場合は、できたものをプロジェクトルートに移動:

```bash
cp -r tauri-nextjs-template/. . # このコマンドは隠しディレクトリも含む
rm -rf tauri-nextjs-template
```

これからリポジトリを作成する場合は tauri-nextjs-template ディレクトリで push

次にプロジェクトルートに作成された不要なファイルを削除します

```bash
rm -rf vite.config.ts index.html tsconfig.json src
```

パッケージから Vite を削除

```bash
bun remove vite 
```

Tips: Next.js は Vite より`next build`方が良い (Tauri も next build を推奨)

https://v2.tauri.app/start/create-project/

### Next.js のプロジェクトを作成

Frontend ディレクトリを作成してその中で Next.js を作成します

- `bunx create-next-app@latest`を使用したらディレクトリの調整が必要かも

例えば:

```bash
cd frontend
bunx create-next-app@latest
cp -r <nextjs-project-name>/. .
rm -rf <nextjs-project-name>
rm -rf .git
```

- Next.js の Template repository があれば、`git clone <url> . | rm -rf .git`できれいにいけます
  - 僕はサブモジュールを使用してみましたが、後述の output export の設定などで複雑になるのでやめました

Next.js が起動できるかテストしておきましょう

```bash
cd frontend
bun install
bun run dev
```

https://nextjs.org/docs/app/api-reference/cli/create-next-app

### フロントエンド ディレクトリに Next.jsを閉じ込めるための設定

- 前述の通り、Frontend ディレクトリに Next.js を閉じ込めていきます
- Tauri の公式の方法だと、Next.js のプロジェクトの中に、src-tauri ディレクトリが存在することになり、いくつかのファイルが Tauri のためだけのものになってしまいます
- 今回の方法では、Frontend ディレクトリの中に Next.js のプロジェクトを閉じ込めることで、このディレクトリの中に Tauri の文脈がほぼ存在しない形になっています
- こうすることで、Frontend ディレクトリの中ではほぼ通常の Next.js のプロジェクトとして開発できるようになります
  
#### output export の設定

作成した Next.js の next.config.tsx に公式 doc の設定をそのままコピー

```tsx
const isProd = process.env.NODE_ENV === 'production';

const internalHost = process.env.TAURI_DEV_HOST || 'localhost';

/** @type {import('next').NextConfig} */
const nextConfig = {
  // Ensure Next.js uses SSG instead of SSR
  // https://nextjs.org/docs/pages/building-your-application/deploying/static-exports
  output: 'export',
  // Note: This feature is required to use the Next.js Image component in SSG mode.
  // See https://nextjs.org/docs/messages/export-image-api for different workarounds.
  images: {
    unoptimized: true,
  },
  // Configure assetPrefix or else the server won't properly resolve your assets.
  assetPrefix: isProd ? undefined : `http://${internalHost}:3000`,
};

export default nextConfig;
```

こちらがおそらく Next.js x Tauri のコアとなる設定です。

この設定によって SSR が無効化され、SSG(Static Site Generation) モードでビルドされます。
そのため、Node 環境で SSR(Server Side Rendering)を行うことがなくなり、成果物の中で処理が完結します。
(html, js, css などのプレーンなファイルのイメージ)

こちらの設定で Next.js のビルド成果物は frontend/out に出力されます

#### プロジェクトルートからフロントエンドコマンドを触れるようにする

こちらの公式ドキュメントを参考にしつつ、config を少し変更します

https://v2.tauri.app/start/frontend/nextjs/

プロジェクトルートの`package.json`を編集
(ここでは bun を使用しています)

- コマンドは将来的にもう少しシンプルにしたいです

```json
{
  "name": "tauri-nextjs-template",
  "private": true,
  "version": "0.1.0",
  "type": "module",
  // ここから
  "scripts": {
    "dev": "cd frontend && bun i && bun run dev && cd ..",
    "build": "cd frontend && bun i && bun run build && cd ..",
    "preview": "cd frontend && bun i && bun run preview && cd ..",
    "tauri": "tauri"
  },
  // ここまで
  "dependencies": {
    "@tauri-apps/api": "^2",
    "@tauri-apps/plugin-shell": "^2"
  },
  "devDependencies": {
    "@tauri-apps/cli": "^2",
    "typescript": "^5.2.2"
  }
}
```

公式 doc を参照しつつ、`tauri.conf.json`を編集

- frontendDist を指定して、フロントエンドのビルド成果物を参照できるようにします

```json
{
  "build": {
    "beforeDevCommand": "bun run dev",
    "beforeBuildCommand": "bun run build",
    "devUrl": "http://localhost:3000",
    "frontendDist": "../frontend/out" // ここをfrontendディレクトリのoutを指すように変更
  }
}
```

この設定で Tauri が Next.js をハンドルできるようになります。
デスクトップアプリが起動できるかテストしておきましょう

dev

```bash
bun run tauri dev
```

開発用のアプリが起動します

![image-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3716127/7841d5ab-734b-e85e-c1a6-311db996a9df.png)

ビルド

```bash
bun run tauri build
```

成功すると mac なら .dmg ができます (Windows なら .exe ができると思います)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3716127/377fa369-62d7-681a-a0c8-a080e6a0e537.png)

## CI/CD の設定

公式が出している Github Actions でビルドを自動化します

- 以下の yaml は公式のもののコメントを日本語訳したものです
- tauri cli では、クロスコンパイルできないが、Github Action だと可能らしいです

https://v2.tauri.app/distribute/pipelines/github/#example-workflow

```yaml
name: 'publish'

on:
  workflow_dispatch:
  push:
    branches:
      - release

jobs:
  publish-tauri:
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: 'macos-latest' # ArmベースのMac（M1以上）用
            args: '--target aarch64-apple-darwin'
          - platform: 'macos-latest' # IntelベースのMac用
            args: '--target x86_64-apple-darwin'
          - platform: 'ubuntu-22.04'
            args: ''
          - platform: 'windows-latest'
            args: ''

    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      - name: install dependencies (ubuntu only)
        if: matrix.platform == 'ubuntu-22.04' # これは上で定義されたplatformの値と一致する必要があります。
        run: |
          sudo apt-get update
          sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

      # (bunのインストール)
      - name: setup bun
        uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest

      - name: install Rust stable
        uses: dtolnay/rust-toolchain@stable # これをdtolnay/rust-toolchain@nightlyに設定します。
        with:
          # これらのターゲットはmacOSランナーでのみ使用されるため、WindowsとLinuxのビルドを少し高速化するために`if`に入っています。
          targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}

      - name: Rust cache
        uses: swatinem/rust-cache@v2
        with:
          workspaces: './src-tauri -> target'

      - name: install frontend dependencies
        # `beforeBuildCommand`が設定されていない場合、ここでフロントエンドをビルドすることを検討してください。
        run: bun install # 使用するものに応じて、これをnpmまたはpnpmに変更します。(ここではbunに変更しています)

      - uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tagName: app-v__VERSION__ # アクションは自動的に\_\_VERSION\_\_をアプリのバージョンに置き換えます。
          releaseName: 'App v__VERSION__'
          releaseBody: 'このバージョンをダウンロードしてインストールするには、アセットを参照してください。'
          releaseDraft: true
          prerelease: false
          args: ${{ matrix.args }}

```


ポイント

- 1.bun の公式の GitHub action を使用して bun をインストールして、パッケージを install しています

https://bun.sh/guides/runtime/cicd

- 2.bun のキャッシュは公式の action がよしなに使ってくれます
- 3.GITHUB_TOKEN は設定不要です
- 4.branches は main など自分のブランチ戦略に合わせて変更してください
- 5.エラーがでたら Action の権限に、write 権限を付けてください

Release の確認

- Release が 1 つも作成されていないと、Repository の code 画面で Release が見えないです
- その場合は、<Repository URL>/releases にアクセスしてください

https://docs.github.com/ja/repositories/releasing-projects-on-github/linking-to-releases#linking-to-the-latest-release


![image-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3716127/3143a583-3f5a-4ee4-2f95-06f8072a7d1a.png)
![image-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3716127/5e515557-ff7f-d809-04ef-9e03ae89b3ed.png)





Mac の場合は、Apple のデベロッパー登録をしないと、壊れていると表示されますが以下の方法で実行を許可できました

https://yotiosoft.com/support/help/macos-blocked.html

こちらも参考にしてください!

https://zenn.dev/kumassy/books/6e518fe09a86b2/viewer/851c41

## まとめ

- Tauri を利用した開発は、React や Next.js が使える点や、小さなアプリをサーバーなどのリソースを気にせずサクサク作れるという点で、AI と相性が良さそうなので初期セットアップのフローを確立して、今後の発展を見守りたいです

- 環境差異によるバグや表示崩れに関して未知数なので知見をためていきたいです