electron
, react
, babel
, webpack
, gulp
の環境にした。
今までのものからwebpack
を追加した。
その理由は、jsx
ファイルを分割して、他ファイルからrequire
するときに、正しくできないため。
require
が無いと言われたり、パスが異なると言われたりする。
パスが違う原因は、おそらくパス指定がhtml
ファイル基準になるためだと思う。
gulp
+babel
でのトランスパイルは、ファイルはまとまらないようなので、これではまずい。
この問題を解決するために、webpack
の導入を行った。
さらに、main.js
などのメインプロセス側ファイルの変更のホットリロードに対応するため、electron-connect
を導入し、gulpfile
からelectron
を操作できるようにした。
導入とwebpack関連のセットアップ
まずは、パッケージのインストール(追加分のみ、かつelectron-connect
は後回し)。
npm install -D babel-loader webpack webpack-stream
続いて、webpack
の設定。resolve
とmodule
の中身が大事:
// webpack.config.js
module.exports = {
// モード値を production に設定すると最適化された状態で、
// development に設定するとソースマップ有効でJSファイルが出力される
mode: "development",
// メインのJS
entry: "./renderer/index.jsx",
// 出力ファイル
output: {
filename: "bundle.js"
},
resolve: {
extensions: ['.jsx'] // デフォルトは、jsxファイルを探してくれない。
},
module: {
rules: [{
test: /\.jsx$/, // 拡張子がjsxで
exclude: /node_modules/, // node_modulesフォルダ配下でなければ
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react']
}
}
}]
}
}
次は、gulp
のタスク定義:
// gulpfile.js
const gulp = require('gulp');
const babel = require('gulp-babel');
const webpackStream = require('webpack-stream');
const webpack = require('webpack');
function transpileViaWebpack() {
// webpackStreamの第2引数にwebpackを渡す
return webpackStream(webpackConfig, webpack)
.pipe(gulp.dest("dist"));
}
exports.default = transpileViaWebpack;
また、watch
を変更すればwebpack
にしてもホットリロードができる。github
のソースでは、そうしている。しかし、electron-connect
を利用している点で異なる。(後述)
Reactのコンポーネント
renderer
プロセス用のファイル構成は下のようになる。
renderer/
├── components
│ ├── app.jsx
│ └── person.jsx
├── index.html
└── index.jsx
分割したので、index.jsx
は以下のようになる。
// index.jsx
const { App } = require('./components/app');
document.addEventListener("DOMContentLoaded", () => {
ReactDom.render(<App />, document.getElementById('app'));
})
分割先の./components/app.jsx
は以下に。
// components/app.jsx
const { Person } = require('./person');
class App extends React.Component {
render() {
return (
<div>
<h1>hello electron+react+webpack world!</h1>
<Person food="sushi" />
</div>
);
}
}
module.exports = {
App: App,
};
さらに分割した./components/person.jsx
は以下に。
// components/person.jsx
class Person extends React.Component {
render() {
return (
<p>i want to eat {this.props.food}!</p>
)
}
}
module.exports = {
Person: Person,
};
htmlでの読み込み元の変更
gulpfile.js
で、トランスパイル後の出力ディレクトリ先をdist
に変更したので、html
ファイルでの読み込み元もそれに合わせて変更する。
<!-- index.html -->
...
<!-- 以前の出力先 -->
<!-- <script src="../build/index.js"></script> -->
<!-- 現在の出力先 -->
<script src="../dist/bundle.js"></script>
gulpfileからelectronの起動・ホットリロード
今までの内容は、起動時のみ事前のトランスパイル(npx gulp
)が必要だった。
これは、若干面倒なので、npm start
時にトランスパイルするようにする。
これには、gulp
上でelectron
の実行ができればいいと考えた。
そこで、electron-connect
というツールが使えることがわかった。インストール:
npm install -D electron-connect
メインプロセス側でclient
を生成する。html
内に埋め込む形にした。配布時には除去できるらしい。(未確認)
<body>
...
<!-- build:remove -->
<!-- Connect to server process -->
<script>electronconnect.client.create()</script>
<!-- end:build -->
</body>
electronconnect
なのは、preload.js
でグローバル変数にセットしてあるから。
// preload.js
...
process.once('loaded', () => {
...
global.electronconnect = require('electron-connect');
})
gulpfile.js
に追記。watch
でcallback()
しないと、一度の変更時しか関数が実行されない。(なぜかelectron.restart
はしっかり動いたが。):
// gulpfile.js
const electron = require('electron-connect').server.create();
...
function runElectron() {
electron.start();
}
function watch() {
gulp.watch(paths.main.src, electron.restart);
gulp.watch(paths.renderer.srcjsx, (callback) => {
transpileViaWebpack();
electron.reload();
callback();
});
gulp.watch(paths.renderer.srchtml, (callback) => {
electron.reload();
callback();
});
}
exports.run = gulp.series(transpileViaWebpack, gulp.parallel(runElectron, watch));
これで、npx gulp run
すればOK。package.json
を変更して、npm start
でこれを実行するようにする。
// package.json
"scripts": {
"start": "gulp run",
...
},
electron-connect
はメインプロセスとレンダラープロセスの両方をリロードできるので、今まで使っていた、electron-reload
は不要になる。よって、アンインストールしておく。
npm uninstall -D electron-reload
後書き
gulp
のwatch
でcallback()
が必要なことに気がつくのに時間がかかった。
自分で環境を構築していくと、いろいろわかってきて楽しい。あまり時間はかけたくないが。
配布のためのパッケージングについても、そのうちまとめておきたい。
最後に現在のpackage.json
の依存関係を載せておく。:
// package.json
...
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"electron-connect": "^0.6.3",
"electron-mocha": "^8.0.3",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"webpack": "^4.35.2",
"webpack-stream": "^5.2.1"
},
"dependencies": {
"electron": "^5.0.6"
}
参考
- Module | webpack
- Gulpで始めるwebpack 4入門 - Qiita
- babel-loader - npm
- webpack-stream - npm
- electron-connect - npm
コメント