Desktop App 開発
デスクトップアプリ開発において情報をまとめているページです。
各 OS ごとの開発方法は下記のページを参照してください。
関連リンク
各ディレクトリ詳細
root ディレクトリ
tailwind や TypeScript、webpack などの設定ファイルをまとめています。
Webpack の設定については、Electron Forge の Webpack Plugin に乗っかる形で実装しています。下記記事に詳細があります。
env ディレクトリ
各種 .env ファイルをまとめています。
.env.development: ローカルでの開発時に利用する環境変数をまとめています.env.staging: ステージング環境での開発時に利用する環境変数をまとめています.env.production: 本番環境での開発時に利用する環境変数をまとめています.env.build: ビルド時に利用する環境変数をまとめています
各ファイルに格納する値は、以降のドキュメントで詳細に説明します。
src/@types
デスクトップアプリの TypeScript の型定義ファイルをまとめています。
特記事項として、src/@types/renderer.d.ts 内において、下記のように Window オブジェクトを拡張する形で型定義を追加しています。 これは、src/renderer 内の TypeScript ファイルで、window.coreAPI や window.logger といったオブジェクトを参照するために必要です。
// src/@types/renderer.d.ts
// ...
declare global {
interface Window {
coreAPI: ICoreAPI;
logger: ILoggerAPI;
}
}
// ...src/api
renderer プロセス側に公開する API を定義しています。
例:
import { ipcRenderer } from "electron";
import { channelNameMap } from "@/api/constant";
export const coreAPI: ICoreAPI = {
showVideo: () => ipcRenderer.send(channelNameMap.showVideo),
recordVideo: (...data: any) =>
ipcRenderer.send(channelNameMap.recordVideo, ...data),
startRecording: (...data: any) =>
ipcRenderer.send(channelNameMap.recording.start, ...data),
stopRecording: (...data: any) =>
ipcRenderer.send(channelNameMap.recording.stop, ...data),
};
export const loggerAPI: ILoggerAPI = {
info: (...params) => ipcRenderer.send(channelNameMap.info, params),
};src/assets
デスクトップアプリのアイコンなど、静的なファイルをまとめています。
src/common
基本的なユーティリティ関数をまとめています。 独自に定義した Error クラスや、独自に実装したユーティリティ関数を含みます。
src/libs
src/libs は外部ライブラリをラップした関数をまとめたディレクトリであり、基本的には外部ライブラリをそのまま export する形で利用することを想定しています。
💡
src/libs層を作成している背景:外部ライブラリをラップした関数を作成することで、外部ライブラリのバージョンアップや変更による影響を最小限に抑えることができます。
src/main
Main プロセスで動かすロジックのソースコードをまとめています。 基本的にはサービスごとにディレクトリを作成し、その中にロジックをまとめています。
2023年7月12日現在、下記のような構成になっています。
tree main -L 3
main
├── index.ts
└── services
├── apiClient
│ ├── apiClient.ts
│ ├── index.ts
│ └── types.ts
├── recordSubscriber
│ ├── ebmlHandler.ts
│ ├── index.ts
│ ├── mpdBuilder.ts
│ ├── queue
│ ├── recordSubscriber.ts
│ ├── recordingChapters.ts
│ └── types.ts
├── recorder
│ └── recorder.ts
├── remoteStorage
│ ├── index.ts
│ ├── remoteStorage.ts
│ └── types.ts
└── taskManager
├── index.ts
└── taskManager.ts
8 directories, 16 filessrc/renderer
Renderer プロセスで動かすロジックのソースコードをまとめています。 基本的には React プロジェクトのような様相を呈しています。
2023年7月12日現在、下記のような構成になっています。
tree renderer/ -L 3
renderer/
├── components
│ ├── model
│ │ └── frontFacingCamera
│ ├── page
│ └── ui
│ ├── button
│ └── icons
├── globalState
├── hooks
├── models
├── pages
│ ├── front-facing-camera-bubble.tsx
│ └── main.tsx
├── services
│ └── recorder
│ ├── customMediaRecorder
│ └── recordPublisher
├── styles
│ └── global.css
└── usecases
18 directories, 3 filesディレクトリの分け方は下記のような記事を参考にしつつ、それぞれに役割を持たせて分割しています (TODO: ここに関しては別途 wiki を書きたい)
src/window
このディレクトリでは、Quden の Desktop App で利用する window を定義しています。
ここでいう Window とは、アプリケーションにおける window のことを指します。 例えば、
2023年7月12日現在、以下のように構成することを想定しています。(が、変更の可能性があります)
- Main
- 拡張機能で右上に表示されるような、カメラ・マイクなどのメディアの設定や、保存先ワークスペースを設定するためのウィンドウ
- Control Menu
- 録画に関する基本操作(停止、再開など)を行うコントロールメニューを持つウィンドウ
- Base Overlay
- 画面全体を暗黙的にカバーしたオーバーレイ層
- クリックの検知や、カーソルエフェクトの実装に利用する想定
- (Front Facing Camera Bubble)
- ビデオメッセージを実装する際に利用します
- 先にステップガイドを実装する想定のため、今のところ作成予定はの目処は不明です
実装の詳細
ログイン機能の実装について
ログインフローは、BrowserWindow を用いて、ブラウザ上でログインを行う形で実装しています。
詳しくは下記の issue を参照してください。
開発の進め方
Quden Desktop app を支える技術スタック
Quden のデスクトップアプリは、下記のようなツール群で構成されています。
- Electron
- Electron は、Web 技術を用いてデスクトップアプリを開発するためのフレームワークです
- Electron forge
- Electron forge は、Electron アプリの開発を支援するためのツールです
electron-forgeコマンドを利用することで、Electron アプリの開発が圧倒的に楽になります
- React
- メニュやコントロールメニューなど、フロントエンドの実装に React を利用しています
ビルドライフサイクル
Electron のビルドに置いては、下記のようなライフサイクルがあります。
- Package
- パッケージングを行います
- パッケージングとは、Electron アプリを実行可能な形に変換することを指します
- 例えば、macOS であれば
.appファイルに変換することを指します
- Make
- パッケージングされたアプリを配布可能な形に変換します
- 例えば、macOS であれば
.dmgファイルに変換することを指します
- Publish
- 配布可能な形に変換されたアプリを配布します
- 例えば、macOS であれば、配布可能な形に変換された
.dmgファイルを GitHub のリリースページにアップロードすることを指します
ライフサイクルは下記の画像、およびドキュメントがわかりやすいです。

Platform, Architecture とは
- Platform
- macOS, Windows, Linux などの OS のことを指します
- macOS は
darwinという名前で表現されます - Windows は
win32という名前で表現されます - Linux は
linuxという名前で表現されます
- Architecture
- x64, arm64 などの CPU のことを指します
- Intel mac は
x64, M1/M2 mac はarm64というアーキテクチャ名を持っています
Native module について
Quden の Desktop app では、クリックした位置の座標の取得や、クリック先の情報(アプリ名など)を取得するために、Node の addons の仕組みを利用しています。
具体的は、下記のファイルで実装しています。
src/main/addons/get-ui-element-info- アプリ名を取得するためのネイティブモジュール
src/main/addons/iohook- クリック位置を取得するためのネイティブモジュール
- iohook というモジュールをコピーして利用している
参考:
- desktop appでクリックイベント取得〜アプリの情報を取得するまで | ジパンク | Quden
- ネイティブ Node モジュール | Electron
- C++ addons | Node.js v21.1.0 Documentation
アプリの配布
アプリを配布するにあたってやることは、大きく下記のとおりです。
package.jsonの Version を更新する- zipunk/quden-desktop-app の Releases で、新しい Release を作成する
- 作成した Release に対して、アーティファクトをアップロードする
- アプリをパッケージ化、および署名して配布可能な形に変換する
- 署名について、macOS は make 段階で署名され、Windows は make 後に別途
signtoolコマンドを実行することで署名できます
- 署名について、macOS は make 段階で署名され、Windows は make 後に別途
publishコマンドを実行し zipunk/quden-desktop-app-update-server の Releases に draft release を作成する- macOS と Windows 機でそれぞれ
publishコマンドを実行する必要があります - Version number が同じであれば、同じ draft release に紐付いてアーティファクトがアップロードされます
- macOS と Windows 機でそれぞれ
- zipunk/quden-desktop-app-update-server の Releases で、draft release を latest に指定して publish する
macOS と Windows の配布については、それぞれのドキュメントを参照してください。
Version の更新
Publish されるアプリのバージョンは package.json 内の version に依存します。
下記手順に従ってバージョンの更新を行ってください。
1: yarn version コマンドを実行する
下記コマンドを実行することで、次の2が実行されます:
package.jsonの version が更新される- Git tag が作成される
git tagで確認できます
# prerelease バージョンを更新する場合
yarn version --prerelease
# ex: 0.0.1-beta.0 → 0.0.1-beta.1
# patch バージョンを更新する場合
yarn version --patch
# ex: 0.0.1 → 0.0.2
# major, minor バージョンを更新する場合も同様にです。詳しくはドキュメントを参照してください。2: git push する
# 通常の push です
git push origin <branch_name>
# tag の push です
git push origin <tag_name>3: すべての変更を main ブランチにマージし、新たに作成した tag で Release を作成する
Version 毎の変更内容を管理しやすくするため、zipunk/quden-desktop-app の Releases に新しく Release を作成してください。
実際の例はこちら
アプリ配布の仕組み
アプリの配布において重要なコンポーネントは以下の2つです。
- アプリの version を管理する update server
- レポジトリ: zipunk/quden-desktop-app-update-server
- Vercel が公開している Hazel をベースにしています
- Release で公開されたアプリのバージョン情報、およびパッケージされたファイルを管理しています
- Electron app
src/main/index.ts内で update server に対して定期的に情報を fetch しにリクエストを送っています- 新しいバージョンが公開されていれば、ダイアログを表示し、更新を実行することができます
参考の読み物
- Electron のメインプロセスとレンダラープロセスの違い
- Behind the Scenes: Building Loom for Desktop | Loom
- Loom における Desktop アプリの実装についての記事
- Building a video call overlay app with Electron and Daily (Part 1)
- Daily の API を用いて、Video call を実装する場合のチュートリアル