適当おじさんの適当ブログ

技術のことやゲーム開発のことやゲームのことなど自由に雑多に書き連ねます

Electronアプリ開発時のwebpackの設定について

はじめに

こちらの記事 の環境を構築したあとで、webpackの設定をElectron向けに見直したときのメモです。この記事では、メインプロセス・レンダラープロセス関連のモジュールをwebpackで処理するように設定を見直しています。

上記記事では、レンダラープロセス関連のモジュールのみをwebpackの処理対象としていました。記事を書いた時点ではそれで十分だと思ったのですが、メインプロセス関連のモジュールが膨らむ未来が見えたので、早期に設定を見直すこととしました。

Electronの2種類のプロセス

Electronは、メインプロセスとレンダラープロセスという2種類のプロセスから構成されています。これらの2つのプロセスはそれぞれ異なる役割を持ちます。webpackの設定にも関わるので、まずこれらのプロセスについて整理しておきます。メインプロセスとレンダラープロセスが提供しているAPIは、公式ドキュメントで確認できます。中には、双方のプロセスが提供しているAPIもあります。APIの一覧からもなんとなく役割の違いが理解できるので、一度目を通して見ると良いです。

メインプロセス

OSレベルの処理を主に取り扱い、アプリケーションのライフサイクルを管理するプロセスです。デスクトップアプリケーションに不可欠なGUIの作成も担当しています。つまり、このメインプロセスがウィンドウを作成しています。ウィンドウの作成だけでなく、最大化/最小化、リサイズ、閉じるといった各種イベントをハンドリングします。アプリケーションメニューやショートカットの定義、アップデート処理などもメインプロセスで取り扱われています。メインプロセスの役割はウィンドウを作るところまでです。

レンダラープロセス

メインプロセスによって作られたウィンドウは、Webページとして作られたUIを持ちます。このWebページを描画しているプロセスが、レンダラープロセスです。ウィンドウがHTMLファイルをロードしてWebページを表示する際に、レンダラープロセスが作成されます。メインプロセスは1つしか存在しませんが、レンダラープロセスはWebページごとに存在します。1つのウィンドウの中に複数のWebviewがある場合、それぞれ対応するレンダラープロセスが存在することになります。

webpackの設定

以上のように、メインプロセスとレンダラープロセスは明確に役割が区別されています。また、メインプロセスはエントリーポイントとして実行されるのに対し、レンダラープロセスはWebページが作成されたタイミングで実行されます。処理内容も読み込みのタイミングも違うので、この2つのプロセスで扱うモジュールを1つにバンドルする意味はありません。

以上から、2種類のプロセスに応じた2つのバンドルファイルを出力するように設定します。バンドルファイルの名前はそれぞれ、メインプロセスは main.jsとし、レンダラープロセスは renderer.js とします。

フォルダ構成

以下のようなフォルダ構成を前提とします。ソースコードはsrc以下に作成し、バンドルファイルをdistに置きます。src以下のディレクトリをプロセスで分けて、その中にエントリーポイントとして index を名前に含んだファイルを作成しています。

.
├── dist  # バンドルファイルの出力先
├── index.html
├── package.json
├── src
│   ├── main  # Main Process関連のファイル置き場
│   │   └── index.js
│   └── renderer  # Renderer Process関連のファイル置き場
│       └── index.jsx
└── webpack.config.js

メインプロセスに関するモジュールを追加したい場合は src/main 以下に、レンダラープロセスに関するモジュールを追加したい場合は src/renderer 以下に配置するようにします。そうするとなんとなく綺麗な感じがします。

Targets について

JavaScriptはバックエンド、フロントエンドの双方を記述でき、デスクトップアプリケーションも作成できる言語です。webpackの target オプションは、どの環境に向けて書かれたソースコードであるかを示すものです。 指定された環境に応じて色々と裏側で設定してくれます。

デフォルト値は web です。 web はブラウザ向けであることを示しています。Electron向けには、 electron-mainelectron-renderer の2つの値が存在します。その名の通り、前者がメインプロセス、後者がレンダラープロセスのための設定値です。そのほかの設定値については、公式ドキュメント を参照してください。

Electron関連のバンドルファイルを作成する際には、target にこれら2つの値を指定すればよいです。しかしながら、 target には複数の値を設定できません。targetごとに設定を作成しなければなりません。

const mainConfig = {
  target: 'electron-main',
  ...
}
const rendererConfig ={ 
  target: 'electron-renderer',
  ...
}
module.exports = [ mainConfig, rendererConfig ]

わざわざ mainConfig などの変数に格納する必要もありませんが、個人的にはこちらの方が読みやすくて好きです。公式ドキュメント - Targets にも同じように書かれています。

設定例

以上を踏まえて、webpack.config.js は以下のようにしました。Webページの描画を担当するRenderer Process側の設定には .jsxcss を、Main Process側の設定には js のみを含めています。

rulesオプションの中を test: /\.(js|jsx)$/ として、メインプロセスとレンダラープロセスで設定を使いまわしてもよかったのですが、今回は別々に設定を作成しました。「メインに画面描画に関するモジュールを混ぜない!」という意思表示のためです。

参考