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

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

Electron + React with Babel + Webpack でアプリ開発 〜環境構築編〜

はじめに

Electron + React なデスクトップアプリケーション開発の準備時に調べたことのメモです。Yarn, Electron, React, Babel, Webpack の概要と簡単なサンプルを記載しています。これらのライブラリ・ツールの実態がつかめずに抵抗感を抱いている方向けの内容となっています。最後に簡単なサンプルを掲載していますが、実装関連の深堀りはしていません。また、動かすことが目的なので、各ツールの込み入った設定については触れていません。

それぞれのバージョンは以下の様になっています。バージョンが違う場合は適宜読み替えてもらえればと思います。

ツール・ライブラリ バージョン
Yarn 1.7.0
Electron 2.0.2
React 16.4.0
Babel 6.26
Webpack 4.10.2

パッケージマネージャの導入

Electron + React なデスクトップアプリケーションを開発するためには、そのためのライブラリ・ツールが必要になります。パッケージマネージャを使えば、それらのライブラリ・ツールを容易に導入できます。もちろん、導入したパッケージの更新や削除も可能です。ライブラリが別のライブラリに依存していることも多く、そういった依存関係もいい感じに解決してくれます。つまり、手動で「あれも足りない、これも足りない」とやらなくて済みます。

npm と Yarn

有名なパッケージマネージャとして以下の2つが挙げられます。

Yarn は後発のパッケージマネージャで、 npm の欠点を補うことを目的として開発されました。しかし、npmも遅れを取ったままではありません。バージョン5 で Yarnと同様に lockファイルを生成するようになったりと改良が続けられています。

内部的な動作やコマンドオプションに違いはありますが、使用方法に大きな違いはありません。また、npm と Yarn は、同じレジストリ(パッケージが登録されているリストのようなもの)を参照しているので取り扱っているパッケージも同じです。こっちで使えてあっちで使えない・・・といったことはないはずです。

どっちを使う?

「とりあえずライブラリを導入したい」というだけであれば、個人的にはどちらを使っても良いと思っています。ただ、使わないという選択肢はないと思っています。これから開発を始めるにあたって、いずれかのツールは使えるように準備しておきましょう。各ツールのインストール方法は、公式ドキュメントを参考にしていただければと思います。

どちらを使っても良いと言いつつ、この記事では yarn を使ってる前提で話を進めていきます。npm を使っている人は適宜読み替えてもらえればと思います。下記コマンドを実行して、バージョンが表示されればインストールは成功です。

$ npm -v
6.1.0
$ yarn -v
1.7.0

パッケージマネージャをインストールできたら、プロジェクトを作っていきましょう。mkdircd には好きな名前を指定してください。イカしたアプリの構想があって名前も決まっているのであれば、ぜひその名前でディレクトリを作成してください。

$ mkdir try-react-electron
$ cd try-react-electron
$ yarn init -y

yarn init -y を実行すると、package.json というファイルが作成されているはずです。続いて、開発に必要なパッケージを導入していきましょう。

ライブラリの導入

先ほどインストールしたパッケージマネージャで Electron と React をそれぞれインストールしていきます。Electronがデスクトップアプリケーションを開発するための機能を、ReactがUIを開発するための機能をそれぞれ提供しています。

ここでは、それぞれのライブラリの紹介とインストール方法について書いています。具体的な実装例はここでは示しません。

Electronの導入

Githubが開発した HTML + CSS + JavaScriptといったWebのテクノロジーでデスクトップアプリケーションを開発できるすごいやつです。元々は Atom のために開発されたものですが、今はオープンソースとなっています。ChromiumNode.js を内包しているので、クロスプラットフォームなデスクトップアプリケーションを作ることができます。

パッケージは、 yarn add <パッケージ名> で追加します。yarn run は、yarnで導入したツールを実行します。インストールされたパッケージは、 node_modules というフォルダに保存されます。

$ yarn add electron --dev
$ yarn run electron

2行目を実行すると以下のような画面が表示されるはずです。これでElectron本体のインストールは完了です。

f:id:subarunari:20180624131829p:plain

Reactの導入

Facebookが開発した UIの部品を作るためのライブラリです。Reactでは、UIを部品ごとに定義し、それらの部品を組み合わせることでUIを作成します。また、仮想DOMという仕組みを提供しており、この仕組みによってUIが高速に描画されます。

同様に yarn add で、reactreact-dom という2つのパッケージをインストールします。reactはUIの部品を作成するもので、react-domはコンポーネントをDOMとしてレンダリングするものです。

$ yarn add react react-dom

Reactには React Native と呼ばれるモバイルアプリのUIを作るためのライブラリも存在します。そのため、Webブラウザの要素であるDOMを操作する react-dom は別のパッケージとして提供されています。

開発環境の構築

yarn add コマンドで「React」と「Electron」をインストールしました。開発にあたって、あと少しだけパッケージを導入しましょう。ここでは、 BabelWebpack という2つのツールを導入します。

Babel

Babelは、JavaScriptを変換するもので「トランスパイラ」と呼ばれています。JavaScriptの最新仕様と実行環境にはギャップがあり、新しい文法や機能で書いたものがすぐに試せるかというとそうではありません。Babelはこのギャップを埋めるために、ある仕様に対応していない実行環境でも実行できるようにJavaScriptを変換してくれます。新しい文法や機能を積極的に使わず、常に実行環境に合わせて書くのであれば、Babelを導入する必要はありません。

Reactの JSX を使うなら Babel は必要です。JSXは、JavaScriptの拡張形式で通常のブラウザでは実行できません。ブラウザで実行できるようにするために、JSXをBabelでJavaScriptにトランスコンパイルしなければなりません。Reactには JSX 以外の選択肢もありますが、少し辛い選択肢なのでここでは JSX を使っていきます。Reactの本家ドキュメントでもJSXが推奨されていますね。

It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. https://reactjs.org/docs/introducing-jsx.html

ということで、Babelが必要なのでパッケージマネージャで拾ってきましょう。Babel本体は、 babel-core という名前になっています。

$ yarn add --dev babel-core

Babel本体をインストールしただけでは、JavaScriptを変換できません。 Babelに仕事させるには、させたい仕事に対応したプラグインを導入する必要があります。

Babel Presets

プラグインは必要最低限の仕事だけをするように作られており、非常に多く存在しています。その中から自分の目的に応じて1つずつ見繕って、プラグインを入れていくのは大変です。

なので、今回はPresetを導入します。Presetとは、ある目的に応じてまとめられたプラグインの詰め合わせのことです。Presetはパッケージとして公開されているので、同様に yarn add でインストールできます。

$ yarn add --dev babel-preset-env babel-preset-react

Reactに関するプラグインをまとめたものが babel-preset-react、JavaScriptの最新仕様に関するプラグインをまとめたものが babel-preset-env となっています。プラグインを1つずつ入れたい場合は、公式ドキュメントのプラグインのページを参照ください。

Babelの設定

プラグインやプリセットを入れるだけでは実行できません。どれを使うかを設定ファイルに記載しなければいけません。 .babelrc もしくは package.json に設定を記載できます。 設定ファイルを1つにまとめたい場合は、 package.json に書くのが良いと思います。ここでは、わかりやすくするために .babelrc ファイルとして作成しました。

{                                                                        
    "presets": ["env", "react"]                                                 
}  

"presets" オプションに使用するプリセットのみ記載しています。これで Babel の準備は整いました。babel-preset-env にはもう少し細かい設定が可能で、フル活用するためにはそれらを設定することが推奨されています。

However, we don't recommend using preset-env this way because it doesn't take advantage of it's greater capabilities of targeting specific browsers. https://github.com/babel/babel-preset-env

今回はとりあえず動かすことが目標なので、これだけの設定としておきます。また、今回は babel-core のみをインストールしたので、コマンドライン等での実行はできません。後述するWebpack経由で Babel を実行します。Babel単体で実行できるようにしたい場合は、 babel-cli を使うと良いです。

Webpack

Webpackはモジュールバンドラーと呼ばれる「複数のファイルをひとまとめ(=バンドル)にするためのツール」です。JavaScriptやCSSがすべて別々のファイルだと、それらを取得するために個別にリクエストが送信されます。Webpackで1つにまとめておくことで、1回のリクエストで取得できるようになります。結果、サーバへのリクエスト回数を減らし、負荷を下げることができます。

「最初から1つのファイルに書けばいいじゃないか!」と思うかもしれませんが、開発が進むとファイルが肥大化していき地獄へと変わっていきます。Webpackを使えば、モジュール分割して快適に開発しつつ、それらのモジュールを読み込むときはまとめられたファイルを使えるということですね。

また、Webpackはバンドルするファイルを依存関係を元に選択します。つまり、どこからも参照されていないようなモジュールはバンドルの対象にはなりません。

例によって yarn add でWebpackをインストールします。 webpack-command は webpack をコマンド実行できるようにするためのものです。

$ yarn add --dev webpack webpack-command

コマンドツールには webpack-cliwebpack-command の2つがあります。webpack-cli はフル機能版で webpack-command は軽量版といった違いがあります。お好みでどうぞ。

Loader

WebpackはデフォルトでJavaScriptだけバンドルできます。JavaScriptだけでなく、CSSや画像も1つのファイルにまとめられると、バンドルの恩恵をより受けられます。

JavaScript以外をバンドルしたい場合は、対応するLoaderをインストールする必要があります。今回は CSS をバンドルしたいので、 css-loader style-loader をインストールします。

$ yarn add --dev css-loader style-loader babel-loader

babel-loader はWebpackからBabelを実行するためのものです。Webpack経由で実行することでBabelで変換しつつファイルをまとめてくれます。これもWebpackの強力なポイントです。Loader次第では、前処理しつつまとめる ということが可能となります。

Webpackの設定

インストールしたLoaderをどのように使うかなどを設定ファイルにまとめることができます。Webpackの設定ファイルは、webpack.config.js に書きます。

最低限動かすのに必要な項目をピックアップします。全貌を知りたい方は、公式ドキュメント を参照していただければと思います。

  • entry
    • 依存関係のスタート地点となるファイル名を書きます。
    • ここから依存関係をたどっていき、それらをバンドルします。
  • output
    • バンドルされたファイルの出力先です。
  • test
    • 選択対象とするファイルを指定します。正規表現も使えます。
  • exclude
    • 選択対象を探す際に、探索対象外とするものを指定します。
    • 自分で書いた部分だけが探索対象となるようにしましょう。
  • loader
    • Loaderを指定します。複数指定も可能です。

上記設定項目を要約すると、 「./src/index.js から依存関係を辿っていき、jsxの拡張子のファイルがあれば babel-loader で処理し、cssの拡張子のファイルがあれば css-loader, style-loader で処理し、最終的に1つにまとめて ./dist/bundle.js に出力してください」 という意味になります。

よりElectronに特化した記事も書いたので、必要に応じて参照いただければと思います。

www.subarunari.com

とりあえず動かしてみる

ElectronとReactを使って、Hello とツール名を並べただけの画面を表示するアプリケーションを作成します。

f:id:subarunari:20180624135408p:plain

フォルダ構成は以下のようにしました。ソースコードは基本的にsrc以下に作成し、バンドルファイルをdistに置くような構成とします。

try-react-electron/
├── .babelrc  # Babelの設定ファイル
├── dist/  # バンドルファイルの出力先
├── node_modules # パッケージ置き場
├── package.json
├── src/ # アプリのソースコード置き場
│   ├── index.html
│   ├── main.js
│   ├── assets/
│   │   └── css/
│   │       ├── library.css
│   │       └── main.css
│   └── components
│          └── hello.jsx
├── webpack.config.js  # Webpackの設定ファイル
└── yarn.lock

Electron関連のファイルを作成する

index.html と main.js が Electron関連のファイルです。index.jsは、Electron公式ドキュメントのElectron Development in a Nutshell とほとんど同じです。公式ドキュメントとはフォルダ構成が異なるので、 win.loadFile で指定するパスだけ変更しています。

index.html には、ReactコンポーネントをレンダリングするDOMとバンドルファイルの読み込みだけを記述します。CSSはバンドルファイルに含まれるので別途読み込む必要はありません。「Hello 〇〇」という文字列は、あとでコンポーネントとして定義します。

React関連のファイルを作成する

hello.jsx がReactコンポーネントのファイルです。先ほどのHTMLの id=sample なdivタグにレンダリングするように指定しています。パッケージに応じて文字色を変更するために、 className でクラス名を指定しています。

CSSを作成する

各種スタイルを定義しています。複数のCSSファイルがまとめられることがわかりやすいように、あえて2つのファイルで定義しています。

エントリーポイントの作成

JSXとCSSを作成したので、これらをWebpackで処理できるようにエントリーポイントを作成します。webpack.config.jsの entry に、./src/app.js と指定していたので、app.js という名前で作成しています。

これでimportを辿って、ファイルがバンドルされるようになりました。

Webpackでバンドルする

webpack コマンドでバンドルファイルを作成できます。yarnで導入したパッケージなので、 yarn run とつけるのを忘れずに。

$ yarn run webpack

成功すると、JSX形式のファイルは実行可能なJavaScriptに変換され、CSSと一緒に1つのファイルとしてまとめられます。そしてそのバンドルファイルは、webpack.config.js の output で指定したファイルパスに作成されているはずです。

失敗した場合、発生箇所を確認してエラーを取り除きましょう。修正の度に上記コマンドを実行するのが手間に感じるのであれば、--watch オプションをつけて実行すると良いです。

$ yarn run webpack --watch

--watchオプションをつけると、ファイルに変更が加えられた際に自動でバンドルしてくれるようになります。実行を忘れてうまく動作しなくなるのは悲しいので、自動で実行されるようにしておいたほうが良いかと思います。

アプリケーションを実行する

electron . とすることでアプリケーションを実行できます。このとき、最初に実行されるファイルは package.jsonの main で指定されているファイルです。実行前に "main": "./src/main.js" と変更しておきましょう。

$ yarn run electron .

これで冒頭の画像のような画面が表示されたはずです。

おわりに

以上、Yarn, Electron, React, Babel, Webpack の概要と簡単なサンプルでした。

常々、実際にモノを作りながらReactの勉強をしたいと思っていましたが、Webサービス作るのはつらいなぁと二の足を踏んでいました。WebテクノロジーをベースにしているElectronであればローカルで完結しつつReactの勉強をできる!と思い、Electron + Reactでのアプリケーション開発をすることとしました。フロントエンド開発をする際に使われているツール群に謎の抵抗感があったので、あわせてキャッチアップしました。同じような方の助けになれば嬉しいです。

後々、個別に掘り下げた記事も別途投稿していければと思います。