初書:2021/10/16
mac : 11.6
electron : 15.1.2
webpack : 5.58.1
きっかけ
Electronでアプリバージョンを取得しようと試みたときに、
どうしてもうまいこといかないので埋め込んでしまえ!となった。
(余談)nodeでアプリバージョンを取得する。できなかった
記事にするほどでもないけどどこかに書いておきたかったので簡単にメモ。
飛ばしてもらっていいです。
地味にどう調べたらいいかわからないこれ。
簡単に説明すると、nodeで作成しているアプリケーションのバージョンが、
package.json
のversions
に保存されているが、
これを取得したい。
参考サイト:node.js — Nodejsコードでpackage.jsonからバージョンを取得する方法はありますか?
それっぽい回答のページ。色々と方法は載っている。
process.env.npm_package_version
やproject-version
パッケージを使用する、など。
開発中はこれで一応できるのだが、これをelectron_builder
でビルドし、
アプリケーションとしてしまうと、undefinedを返す(project-version
に関しては起動できなくなった)
仕方ないので、コード内に直接バージョン情報を埋め込めばいいのではないか、となった。
cross-envを使ってみる
webpackでビルドする際、cross-env
を使用している。
"build": "cross-env NODE_ENV=\"development\" webpack --progress",
これ、2つ以上の環境変数をセットすることが出来るらしい。
なのでこれを増やす。
"build": "cross-env NODE_ENV=\"development\" VERSION_ENV=\"v1.0.0\" webpack --progress",
ここで問題点が一つ。バージョン情報をここで埋め込んでしまう。
(ここで失敗することに気づけばこれ以降のことをする必要がなかったのだが、上の問題点に先に気づいてしまったためにやった。)
ということで受け取るようにする。
上の余談の回答の一つに、
% node -p "require('./package.json').version"
でバージョン情報が取得できるとの情報を得た。これを渡せばいいのでは。
変数を使って情報を渡す
参考サイト:bashでパイプ(標準入力)から受け付けた内容を変数に代入する | 俺的備忘録 〜なんかいろいろ〜
echo ABC | { read v ;echo -e "$v"_TEST; }
という書き方で上手いこと渡せるらしい。
ということで組み合わせる。
"build": "node -p \"require('./package.json').version\" | { read v ;cross-env NODE_ENV=\"development\" VERSION_ENV=\"$v\" webpack --progress; }",
はい。これで失敗しました。
後に気づくとあることに対応すればこれでいけるかもしれないが。
cross-env-shellを使う
cross-env
にcross-env-shell
が存在しているのを知る。(どこを見て気づいたか忘れました。。)
これは、変数にシェルコマンドを書き込むことでcross-env-shell
が勝手に書き換えてくれる拡張版。
ということで先程のを書き換える。
"build": "cross-env NODE_ENV=development VERSION_ENV=\"node -p \"require(\'./package.json\').version\" webpack --progress",
記録残すの忘れました。これでエラーが出たらエスケープの数適当に増やすなり消すなりしてください。
そしてこれも無事に失敗する。原因が他のところにあるからなのだが。。
env-cmdを使う
cross-env側の問題だと思っているので、他のライブラリを使ってみます。
参考サイト:環境変数設定は基本cross-envだけどたまにenv-cmdも使う - Qiita
これは、cross-env
ではコマンドに直接書いていた変数を、別途ファイルに書き込んでそれを読み込む形式のもの。
ということで設定ファイルを用意し、
exports.NODE_ENV = "development";
exports.VERSION_ENV="v1.0.0";
コマンドを書き換え、
"build": "env-cmd -f cmd.js webpack --progress",
実行するが意味なし。
webpackから直接envファイルに埋め込めないかを調べる。
そして調べているうちに察する。
cross-env
が書き換えているわけではなく、webpackが書き換えていることに。
今まで渡していたのは、webpackとして実行されるjavascriptファイルに、
development
で変換するかproduction
で変換するかを渡していた。
変換後のprocess.env.NODE_ENV
が書き変わっているのはおそらくwebpackが勝手にやってるから。
なので、それ以外のprocess.env
は、手動で指定しなければいけなかった。
そして辿り着いたのがここ。
参考サイト:webpackで環境変数をモジュールに渡す - Qiita
手動で書かないといけないんですねー。
ということでwebpackを書き換える。いや追記する。
webpack.config.tsを編集する
tsと書いてるがjsでも特に変わらない。
デフォルトで存在しているDefinePlugin
クラスを使用することで、変換時に該当するコードを置き換えてくれる。
今回はprocess.env.VERSION_ENV
なのでこれだけ指定する。
(process.envも指定する必要がある。)
plugins : [
new DefinePlugin({
'process.env.VERSION_ENV': `"${require('./package.json').version}"`,
})
]
右辺は余談の時に出てきた参考サイトにあったコード。埋め込むならローカルで動くコードでいいやという感じで。
ちなみに変数を使って情報を渡す
のところにあったこれで、右辺をprocess.env.VERSION_ENV
にするか
EnvironmentPlugin
というクラスにすれば動いたのかもしれない。
あと、webpack
の方で指定するため、package.json
側はデフォルトのままでいい。
終わりに
書き換える場所さえ気づけば大回りする必要がなかったなあと思う今日この頃。
あと記事の書き方がどうでもいい失敗談→結果という書き方は果たしてみやすいのだろうか。少し気になる。