Dev ContainerでGUI開発をしてみた話（Tauri+Vue.js+Typescript）

# 読み飛ばしてください
お久しぶりです、しなもんです。
高2になってデザイン系かエンジニア系かで進路選択を迫られています。つらい。

さて、最近とあるGUIアプリ開発の作業がようやく持ち上がったのですが、
複数人開発なのでDevContainerを使ってよしなにできないかなぁと思いました。

しかしDevContainerというのは画面を持たない仮想環境内で作業するものであり、
GUIアプリ開発には不向きです。

ということでいろいろ調べてみた結果、noVNCというVNCクライアントで
コンテナ内のGUIデスクトップにアクセスできるという情報が...！

# 本題
以下の構成でGUIアプリ開発をするものとします。

・Tauri(Rust)
yarnで構築します。
・Vue.js(Typescript)
yarnで構築します。

またｍ以下の環境が事前に用意されているものとします。

・Docker + Docker compose
・VisualStudio Code

以上のものが用意できる環境であれば、OSは何でもいいはずです　たぶん

# サクッとDevcontainerを立てる

### 1.ファイルを用意する
構造は以下の通り
```
workspace/
└─.devcontainer
    ├─devcontainer.json
    └─Dockerfile
```

```devcontainer.json
{
    "name": "tauri-project",
    "build": {
        "dockerfile": "Dockerfile"
    },
    "init": true,
    "features": {
        "ghcr.io/devcontainers/features/desktop-lite:1": {
            "version": "latest",
            "noVncVersion": "1.2.0",
            "password": "vscode",
            "webPort": "6080",
            "vncPort": "5901"
        },
        "ghcr.io/devcontainers/features/node:1": {
            "version": "20"
        },
        "ghcr.io/devcontainers/features/rust:1": {
            "version": "1.79",
            "profile": "minimal"
        }
    },
    "forwardPorts": [
        6080
    ],
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-azuretools.vscode-docker",
                "Vue.volar",
                "tauri-apps.tauri-vscode",
                "rust-lang.rust-analyzer"
            ]
        }
    },
    "remoteUser": "vscode"
}
```
```Dockerfile:Dockerfile
FROM mcr.microsoft.com/devcontainers/base:bullseye
RUN cat /etc/apt/sources.list
RUN apt-get update \
    && apt-get install -y libwebkit2gtk-4.0-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev \
    && apt-get clean -y && rm -rf /var/lib/apt/lists/* 
```

### 2.拡張機能をインストール
VSCodeにDev Containersをインストールします。
検索すれば出てきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927831/3600f525-3c87-7dd5-cab7-ead1346eb027.png)

### 3.コンテナをビルド
左下に現れる青い><をクリックすると、オプションが出てくるので
「コンテナーで再度開く」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927831/b032b300-b7a3-c9f7-0b3f-4e11784cc76c.png)

そうするとビルドが始まります。
環境によると思いますが、体感5分程度でした。

# プロジェクトを作成する
### 1.ターミナルを開く
構築できたら、以下のリンクにアクセスするとnoVNCに入ることができます。
（devcontainer.jsonに記述したポートです）
http://localhost:6080

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927831/cadd0d57-a909-cc06-1c93-a573e5bdaa53.png)

「接続」をクリックすると仮想デスクトップにアクセスできます。

左下からターミナルを開くことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927831/58563e38-07e0-a181-1994-ab4ce46a30cb.png)

ここで注意点なのが、VScodeのワークスペースと同期しているのは
/workspacesの内部です。
（知らなくて数分間さまよってました）

```bash
$ cd /workspaces
```
その中にvscodeで開いているフォルダがあります。
```bash
$ cd 任意のフォルダ名/
```
### 2.viteを初期化
プロジェクトを作成していきます。
まずフロントエンドを担うviteプロジェクトを作成します。
```bash
$ yarn create vite
```

:::note info
ディレクトリについて（追記）
Project nameの項目では「.」にすることをおすすめします。

プロジェクト名を指定してしまうと、ディレクトリ構成が以下のようになります。
```
workspaces/
├─.devcontainer
└─[プロジェクト名]
    ├─.gitignore
    ├─package.json
    ├─README.md
    ...
```
この状態だと、あとでgithubで公開したときにreadme.mdの場所が認識されなかったり、主要ファイルがルートディレクトリに無いのでなんか見にくくなったりする気がします（個人的感想）

プロジェクト名を「.」にすると、
```
workspaces/
├─.devcontainer
├─.gitignore
├─package.json
├─README.md
...
```
のようにいい感じになってくれるのでおすすめです。
今回の記事作成時点では知らなかったのでプロジェクト名を「vite-project」にして進めています。
:::

Select a frameworkの項目では、vueを選択します。
vueではtsを使いたかったのでTypescriptを選択しました。
どちらもお好きなものを選んでください！

```bash
yarn create v1.22.22
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...

success Installed "create-vite@5.3.0" with binaries:
        - create-vite
        - cva
✓ Project name: … vite-project
✓ Select a framework: > Vue
✓ Select a variant: > TypeScript

Scaffolding project in /workspaces/フォルダ名/vite-project...

Done. Now run:

    cd vite-project
    yarn
    yarn dev

Done. in 108.04s.
```
:::note info
余談
ここまで進めていればお気づきかもしれませんが、
noVNCではクリップボードが同期してくれません。
そのため、上記のようなログはすべて手書きです。うぅ...
:::

ファイルが生成されていると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927831/9a9b1334-d704-f094-f489-5e4a2d3ce738.png)

そしたら、プロジェクトに移動して依存パッケージをインストールします。
```bash
$ cd [プロジェクト名]/
$ yarn
```
:::note info
先ほど追記したように、プロジェクト名を「.」にした場合は移動は不要です。
:::

```bash
yarn create v1.22.22
info No lockfile found.
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Saved lockfile.
Done. in 43.22s.
```

よしなにやってくれます。
### 3.tauriを初期化
さて、tauriと連携していきます。
まずvite.config.tsを書き換えます

```Typescript:vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  // prevent vite from obscuring rust errors
  clearScreen: false,
  // Tauri expects a fixed port, fail if that port is not available
  server: {
    strictPort: true,
  },
  // to access the Tauri environment variables set by the CLI with information about the current target
  envPrefix: ['VITE_', 'TAURI_PLATFORM', 'TAURI_ARCH', 'TAURI_FAMILY', 'TAURI_PLATFORM_VERSION', 'TAURI_PLATFORM_TYPE', 'TAURI_DEBUG'],
  build: {
    // Tauri uses Chromium on Windows and WebKit on macOS and Linux
    target: process.env.TAURI_PLATFORM == 'windows' ? 'chrome105' : 'safari13',
    // don't minify for debug builds
    minify: !process.env.TAURI_DEBUG ? 'esbuild' : false,
    // produce sourcemaps for debug builds
    sourcemap: !!process.env.TAURI_DEBUG,
  },
})
```

tauriプロジェクトを初期化する前に、cliとapiを追加しておきます。
```bash
$ yarn add -D @tauri-apps/cli
$ yarn add -D @tauri-apps/api
```
完了したら、infoを確認してみます。
```bash
$ yarn tauri info
```
全てにバージョン情報が表示されていればOKです。

それでは、Tauri関係のファイルを初期化します。

```bash 
$ yarn tauri init
```
> Where are your web assets (HTML/CSS/JS) located relative to the <current dir>/src-tauri/tauri.conf.json file that will be created?

の項目では、Tauri が本番用ビルドをするときにフロントエンドのアセットをロードするパスです。
`../dist`にしておきます。

> What is the URL of your dev server?

`http://localhost:5173`に変更します。
viteで使用するポートと同じものにする必要があります。

> What is your frontend dev command?

フロントエンドを起動するコマンドを入力します。
yarnでvue.js構築していますので、`yarn dev`に変えます。

> What is your frontend build command?

上記と同じく、`yarn build`に変えておきましょう。

# 起動してみる
```bash
$ yarn tauri dev
```
で起動します。
tauri側でのビルドが入るので、少し時間がかかります。
こちらの環境だと5分かかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1927831/9e7607ff-e877-523f-d4bc-a91546dbe954.png)

起動できました。おつかれさまでした。

# 所感
環境構築が複雑な構成ほど、Devcontainerを使いたくなりますよね。
noVNCを利用することでGUI開発もできるようになるのは魅力的でした。

それでは私はこれからvueをごりごりに書いてくるので、これで失礼いたします。
うおおおおおおぉぉぉぉぉぉぉぉぉぉぉ...

# 参考記事

https://qiita.com/nikawamikan/items/74e9a561e2d07feb8566

https://pc.atsuhiro-me.net/entry/2023/04/12/040513

https://tauri.app/v1/guides/getting-started/setup/vite/

https://zenn.dev/koichiba/scraps/05d8eb2bf86c61

https://zenn.dev/secondselection/articles/how_to_devcontainer

ありがとうございました...✨