vue-cli-plugin-electron-builder でセットアップしたElectronプロジェクトがビルドできない



## サマリ
 - 問題
     - [vue-cli-plugin-electron-builder](https://github.com/nklayman/vue-cli-plugin-electron-builder/) でセットアップしたElectronプロジェクトがビルドできない

 - うまくいった方法
     - `vue.config.js`に自分でパッチを当てる

 - うまくいかなかった方法
     - `--openssl-legacy-provider`をビルドスクリプト実行時にオプション指定する
     - 環境変数の`NODE_OPTIONS`に`--openssl-legacy-provider`をセットする

 - 試していない方法
     - Node.jsのバージョンダウン
<hr>

## 前提
Windows PowerShellを通常権限で実行し、以下のコマンドからプロジェクトを作成。

```Powershell
> vue create myproject
```


VSCodeで同プロジェクトを開く。ターミナルを開く（`` Ctrl+Shift+` ``）。
※この時点で`npm run build`は正常に完了します。

開いたターミナルから以下のコマンドを実行し、`vue-cli-plugin-electron-builder`を導入。
※このあたりは別にPowerShellでやってもかまわないですけど
スクリプト実行時に聞かれるElectronのバージョンは、`13.0.0`を選択。

```Powershell
> vue add electron-builder
```

## 問題
この状態でElectronのビルドをしようとすると、エラーが起きました。
```Powershell
> npm run electron:build
```

エラー内容は以下。
```Powershell
-  Bundling main process...node:internal/crypto/hash:71
  this[kHandle] = new _Hash(algorithm, xofLen);        
                  ^

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:71:19)
    at Object.createHash (node:crypto:140:10)
    at module.exports (C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\webpack\lib\util\createHash.js:135:53)
    at NormalModule._initBuildHash (C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\webpack\lib\NormalModule.js:417:16)
    at C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\webpack\lib\NormalModule.js:452:10
    at C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\webpack\lib\NormalModule.js:323:13
    at C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\loader-runner\lib\LoaderRunner.js:367:11
    at C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\loader-runner\lib\LoaderRunner.js:233:18
    at runSyncOrAsync (C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\loader-runner\lib\LoaderRunner.js:143:3)
electron-builder\node_modules\loader-runner\lib\LoaderRunner.js:232:2)
    at Array.<anonymous> (C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\loader-runner\lib\LoaderRunner.js:205:4)
    at Storage.finished (C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:55:16)
    at C:\johndoe\dev\myproject\node_modules\vue-cli-plugin-electron-builder\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:91:9
    at C:\johndoe\dev\myproject\node_modules\graceful-fs\graceful-fs.js:123:16    
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
  opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

Node.js v19.2.0
```

Node.jsのv17以降で、暗号アルゴリズムとしてMD4がデフォルトではサポートされなくなったため、MD4の利用箇所がunsupportedとしてエラーになってしまう、とのことです。


## うまくいかなかった方法

`--openssl-legacy-provider`をビルドスクリプト実行時にオプション指定する方法はうまくいきませんでした。
エラー内容は変わらず。


```diff_json
  "scripts": {
+    "electron:build": "vue-cli-service electron:build",
-    "electron:build": "vue-cli-service electron:build --openssl-legacy-provider",
```


次に試したのが、環境変数の`NODE_OPTIONS`に`--openssl-legacy-provider`をセットする方法です。

```diff_json
  "scripts": {
+    "electron:build": "vue-cli-service electron:build",
-    "electron:build": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service electron:build",
```

※環境変数の設定は、Windows環境のため`SET`を利用しています。このスクリプトではMac等では動かないので、代わりに`export`や`cross-env`を使ってください。

この方法で、ビルドはうまくいきます。しかし、デバッグ用の起動のほうができませんでした。
`electron: --openssl-legacy-provider is not allowed in NODE_OPTIONS`というエラーが出て動きません。

```diff_json
  "scripts": {
+    "electron:serve": "vue-cli-service electron:serve",
-    "electron:serve": "SET NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service electron:serve",
```

実行結果
```Powershell
 DONE  Compiled successfully in 512ms                                                                        9:59:56 AM

  File                      Size                                        Gzipped   

  dist_electron\index.js    803.15 KiB                                  175.89 KiB

  Images and other types of assets omitted.
  Build at: 2023-01-24T00:59:56.297Z - Hash: 9d1e69cca257155b2287 - Time: 512ms   

 INFO  Launching Electron...
electron: --openssl-legacy-provider is not allowed in NODE_OPTIONS
```


## うまくいった方法

[vue-cli-plugin-electron-builderのIssueへのポスト](https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1885#issuecomment-1316735840)を参考に、`vue.config.js`に直接MD4を捌くパッチを当てます。
※プロジェクトフォルダの直下にあります。

```diff_javascript
const { defineConfig } = require("@vue/cli-service");
+ const crypto = require('crypto');
+ 
+ /**
+  * md4 algorithm is not available anymore in NodeJS 17+ (because of + lib SSL 3).
+  * In that case, silently replace md4 by md5 algorithm.
+  */
+ try {
+   crypto.createHash('md4');
+ } catch (e) {
+   console.warn('Crypto "md4" is not supported anymore by this Node + + version');
+   const origCreateHash = crypto.createHash;
+   crypto.createHash = (alg, opts) => {
+     return origCreateHash(alg === 'md4' ? 'md5' : alg, opts);
+   };
+ }

module.exports = defineConfig({
  transpileDependencies: true,
});
```

これで、`npm run electron:serve`が機能するようになりました。実行するとアプリウインドウが立ち上がります。
※スクリプトの`SET=NODE_OPTIONS...`は不要なので、追加していたとしたら消しておきましょう。


<hr>

## 環境情報
 - Windows 10 Enterprise
 - Node.js: v19.2.0
 - @vue/cli: 5.0.8

## 参考にした情報
 - [How to Fix the Error Error:error:0308010C:digital envelope routines::unsupported](https://www.newline.co/@kchan/how-to-fix-the-error-errorerror0308010cdigital-envelope-routinesunsupported--0f8d3f17)
     - 問題への対処策の一覧
 - [vue-cli-plugin-electron-builder | issue#1885](https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1885#issuecomment-1316735840)
     - 上述のとおり、ここのポストが直接解になりました
   
## 他にぶつかった問題
 - 上記パッチ適用後、ビルド時に一部モジュールがAuth Errorでプロジェクトフォルダに移動できずに落ちる
     - `C:\user\AppData\Roaming`に一時的にダウンロードされたモジュールを、プロジェクトフォルダに別途手動で移すことで暫定解決。
     - プロジェクトをゼロから作り直したら再発しませんでした。
 - `vue create myproject`実行時のテンプレートとしてTypeScriptを選択すると、ビルド時のエラーに`ts(2571)`が起きる
     - [いつの間にか、try { } catch (error) { } の errorが `unknown` になってしまう問題。](https://zenn.dev/rabbit/scraps/1efe3f5fa86da1)
     - 問題部分を`catch(error:any)`に書き換えると、このエラー自体はパスできます。
     - TS関連の不整備は他にもぶち当たったので、プロジェクトはバニラJS構成で作り直しました。
         - (TS学習は別途やる)