Skip to content

Latest commit

 

History

History
136 lines (107 loc) · 7.78 KB

コードの歩き方.md

File metadata and controls

136 lines (107 loc) · 7.78 KB

VOICEVOX エディタのコードの歩き方

VOICEVOX のエディタは Electron・TypeScript・Vue・Vuex などが活用されており、全体構成がわかりにくくなっています。 ここではどういう構成になっているのかを紹介します。コードを読む上で参考になれば幸いです。

コードが実行される順番

とにかくコードを読みたい方向けに、コードが実行される順番を簡潔に説明します。わかりやすさを優先したため正確な表現でない箇所もあることにご注意ください。

  1. electron がアプリケーションを起動します。このとき実行されるコードが src/background.ts です。
  2. src/background.tsから UI 表示のためのウィンドウを起動します。このとき実行されるコードが src/main.ts です。
  3. main.tsが Vue を使って UI がレンダリングされます。UI のルートコンポーネントが src/App.vue です。
  4. src/App.vueが様々な UI を呼び出します。src/viewssrc/componentsにそれぞれの UI があります。
  5. UI のレンダリングと同時に、アプリの状態やロジックを管理する Vuex のストアが初期化されます。src/storeディレクトリに Vuex 用のコードがあります。
  6. これらのコードは全て TypeScript で書かれています。Vue や TypeScript のコードは実行・ビルド時に自動的に JavaScript へトランスパイルされます。

また electron は、最初に起動するプロセス(メインプロセス)と UI ウィンドウ用のプロセス(レンダラープロセス)で通信するために、プリロードスクリプトsrc/electron/preload.tsを両方から読み込みます。

flowchart TB
subgraph Electron
    direction TB
    background.ts -.- preload.ts
end
background.ts --> main.ts

main.ts -.- preload.ts
main.ts --> Vue & Vuex

subgraph Vuex
    direction TB
    store/
end

subgraph Vue
    direction TB
    App.vue --> views/ & components/
end

設計

ここでは Electron 周り・Vuex 周り・UI 周りの設計方針を簡単に紹介します。

Electron 周り(src/electron/

TODO

Vuex 周り(src/store/

VOICEVOX では動的に変更される状態と、状態を変更する関数を、Vuex のStoreを介して管理しています。 Storeは音声・エンジン・UI などそれぞれの目的に応じて分割し、src/store/index.tsで統合しています。

Vuex の仕様を少し説明します。 状態はStateに保存し、状態の変更はMutationで行います。 Mutationは同期的に実行される必要がありますが、非同期処理を行いたい場合はActionを使います。 VOICEVOX 内では、UI から実行するものはActionを介するようにして、Action内からMutationを実行するようにしています。 これは後述する Undo/Redo 機構のための設計です。 関数は全て文字列を渡す形になっていますが、これも Vuex の仕様です。コードを追う際は文字列で全体検索を行うと便利です。

Vuex は型サポートが不十分なので、VOICEVOX では独自に型周りの機構を作っています(src/store/type.ts)。 関数を定義したい場合は、まずtype.tsに型を宣言し、対応するStore内に実装します。

UI から Electron やエンジンにアクセスしたい場合は、必ず Vuex を介するようにしています。 これは Vuex の元の思想である Flux の考え方を引き継いでいて、外部にアクセスすることで生じる予想外な状態の変更などをなるべく一元管理するためです。

VOICEVOX では Vuex のMutationをラップする形で Undo/Redo 機構を実現しています。 状態 A→B の変更を行った時、自動的にその逆方向 B→A の変更が Undo スタックに積まれます。 詳細はUndo/Redo を実装したい #116をご参照ください。

UI 周り(src/views/src/components/

TODO

ソースコードのディレクトリ構成

  • src
    • background.ts ・・・ Electron 版で最初に実行されるコード。ウィンドウを表示したり、エンジンを起動したりする。Electron のメインプロセス。
    • main.ts ・・・ ウィンドウを表示するために最初に実行されるコード。ここで Vue や Vuex を組み込む。
    • App.vue ・・・ Vue のルートになるコンポーネント。他の全てのコンポーネントの親。
    • views ディレクトリ ・・・ 画面全体を覆うような Vue コンポーネントのディレクトリ。
    • components ディレクトリ ・・・ UI のパーツになる Vue コンポーネントディレクトリ。
    • store ディレクトリ ・・・ Vuex のストアのディレクトリ。アプリのロジックの大半はここに書かれる。
    • electron ディレクトリ ・・・ Electron の ipc 通信などのコードが置かれるディレクトリ。
    • browser ディレクトリ ・・・ WIP
    • type ディレクトリ ・・・ TypeScript 用の型定義などが入るディレクトリ。
    • styles ディレクトリ ・・・ CSS や SCSS などのディレクトリ。
    • infrastructures ディレクトリ ・・・ UI 用のコードと UI 以外のコードを跨ぐときに一枚かませたいときのためのコードのディレクトリ。
    • openapi ディレクトリ ・・・ エンジンの API を叩くためのコードのディレクトリ。OpenAPI で自動生成される。
    • helpers ディレクトリ ・・・ 便利な関数を置くディレクトリ。
    • shared ディレクトリ ・・・ UI と Electron 両方から参照されるコードを置くディレクトリ。
  • public
    • アプリのリソースファイルが置かれるディレクトリ。
  • build
    • ビルドに必要なファイルが置かれるディレクトリ。

シーケンス図

Mermaid Flowを用いて書いています。mermaid のコードをサイトに貼り付ければ再編集も可能です。記述ルールは以下参照。

flowchart LR
  817736>"シーケンスの開始"] --> 584587["関数"]
  style 817736 fill:#ffbbbb,stroke:#ff0000
  584587 --> 965553(["状態変数の変更"])
  965553 --> 945949{{"分岐"}}
  945949 -->|"条件1"| 366994["能動的な処理は単線\n(関数の実行など)"]
  945949 -->|"条件2"| 871294["受動的な処理は点線\n(イベント発生など)"]
  366994 --> 617606["大きい関数(subgraph)"]
  871294 -.->|"発生条件"| 617606
  572391[["外に定義した関数"]] --> 314405>"なんらかの状態"]
  572391 --> 230853>"シーケンスの終了"]
  style 230853 fill:#bbbbff,stroke:#0000ff
  617606 --> 572391
  572391 ~~~|"透明な線で結んでもよし"| 513532["外に定義した関数"]
  subgraph 617606["大きい関数(subgraph)"]
    776462["処理開始"] --> 992786["処理終了"]
  end
  subgraph 513532["外に定義した関数"]
    327013["処理"]
  end

処理の prefix 一覧

  • back: background.ts の関数
  • app: app のイベント
  • win: win のイベント
  • engine: EngineManager のメソッド
  • store: electron-store のメソッド
  • Vuex: Vuex の関数