Electron を使って Vue3 から外部ローカルファイルを読み込む

# はじめに
デスクトップアプリでデジタルサイネージを作る際、設定ファイルを読み込んだり、他社からパソコンの指定の場所に出力されたファイルを読み込んだり、
株価やニュース、天気などの情報をWebから取得して画面に表示する、ということがよくあります。
[前回](https://qiita.com/kaluna/items/a8c5830ffc29a9c892d7)は、そういった外部ファイル（Jsonデータ）を読み込む手順を書きましたが、今回は、PC内に配置されている設定ファイルや画像、動画などを読み込んでいきたいと思います。
尚、使用するIDEはJetBrains社の[WebStorm](https://www.jetbrains.com/ja-jp/webstorm/)を使い、[Vue3](https://v3.ja.vuejs.org/)フレームワークでの使い方になります。

# 目次
1. Electron と Vue3 の準備
1. 外部ファイルを読み込む
1. ローカルファイルを読み込む
1. fsモジュールでの外部ファイルの読み込み
1. ファイルのパス
1. 開発環境と本番環境の確認
1. ビルド後もデータを編集したい
1. 参考

# 環境
- Windows 10 Pro 64bit
- WebStorm 2021.1
- Node.js v14.15.1
- Vue 3.0.0
- Electron 11.0.0

# 1. Electron と Vue3 の準備
前回同様、まずは、Vue3 が Electron で動作する環境を作ります。
これは、[WebStormでVue3のElectronアプリを作る](https://qiita.com/kaluna/items/256d1e32fe73986dc266Vue3%E3%81%8CElectron)を参考にセットアップしてみてください。
ここから先は、この環境が構築できたところからの解説になります。

# 2. 外部ファイルを読み込む
1. Web上にあるファイルを読み込む
1. localhostから下の階層にあるファイルを読み込む
1. パソコン内のどこかにあるファイルを読み込む

前回はこの「1.」「2.」を説明しましたので、今回は「3.」についての説明です。
Node.jsのモジュール`fs`を使ってみたいと思います。

# 3. fsモジュールでの外部ファイルの読み込み
前回使ったお天気のJsonファイルを使って読み込みたいと思います。
Jsonファイルの場所を仮にドキュメントに置いて、Jsonファイルのプロパティから、パスを調べます。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49845/27586eca-20ac-c9ec-3a05-b120d8007ce9.png)
場所が`C:\Users\accou\Documents`となっていますので、このパスを使います。
今回、ファイルの読み込みには、非同期処理の`fs.readFileSync`を使います。同期処理をしたい場合は、`fs.readFile`使います。

```vue:App.vue
<template>
<!-- 省略 -->
</template>
<script>
const fs = require('fs')
export default {
  name: 'App',
  mounted() {
    let response = JSON.parse(fs.readFileSync('C:/Users/accou/Documents/130000.json','utf8'))
    console.log(response)
  }
}
</script>
<style>
<!-- 省略 -->
</style>
```
Jsonファイルなので、fsモジュールでファイルを読み込んだ後に、`JSON.parse()`を使って、Json形式にデータを作り、出力します。
実行してみると、`fs.readFileSync is not a function`といったエラーが出てしまったので、これを解決します。
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49845/d2d4076c-3590-7b82-b55c-2ad908af6f8b.png)

`package.json`と同じ階層に`vue.config.js`ファイルを作成します。
作成したファイルに以下のコードを書きます。

```javascript:vue.config.js
module.exports = {
    pluginOptions:{
        electronBuilder:{
            nodeIntegration:true
        }
    }
}
```
![キャプチャ3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49845/3c4f9a2e-e65e-1475-8688-33c94452a42b.png)

これで実行してみます。
![キャプチャ4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49845/ba4f1af3-55a3-c1a7-ac52-b486c4931d33.png)

うまく読み込めたみたいです。

# 4. ファイルのパス
ファイルのパスを絶対パスで書けば、ファイルの読み込みが出来ることがわかりましたが、ElectronにはOS固有のパスを取得したり、実行中のアプリケーションのパスを取得する関数があり、設定ファイルのような、アプリケーションに付随するファイルのパスを指定する場合には便利です。
アプリケーションのディレクトリを取得する場合は、`app.getAppPath()`、
OS固有のディレクトリを取得する場合は、`app.getPath(name)`を使います。
`name`の所には、`home`や`appData`など、環境に合わせた名称をいれることで、絶対パスを取得できます。`name`に入る名称は[Electronのドキュメント](https://www.electronjs.org/docs/api/app#appgetpathname)で確認できます。
ということで、早速パスを取得してみます。

```vue:App.vue
<template>
<!-- 省略 -->
</template>
<script>
const fs = require('fs')
const remote = require('electron').remote  // <--追記
console.log('App path : ',remote.app.getAppPath())  // <--追記
console.log('Home path : ',remote.app.getPath('home'))  // <--追記
export default {
  name: 'App',
  mounted() {
    let response = JSON.parse(fs.readFileSync('C:/Users/accou/Documents/130000.json','utf8'))
    console.log(response)
  }
}
</script>
<style>
<!-- 省略 -->
</style>
```

実行してみると、また`Cannot read property 'app' of undefined`エラーが出てしまったのでこれを解決します。

`background.js`ファイルの`webPreferences`内に追記します。

```javascript:background.js
'use strict'
<!-- 省略 -->
async function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
      enableRemoteModule:true  // <--追記
    }
  })
  <!-- 省略 -->
}
<!-- 省略 -->
```

これで実行してみます。
![キャプチャ6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49845/e8d66711-1dda-81bd-05c7-32ff016dd7b0.png)
`App Path : C:\Users\accou\Dropbox\WebstormProjects\vue3-electron\dist_electron`、
`Home Path : C:\Users\accou\`
と表示されているので、うまく取得できたようです。
ただ、`getAppPath()`はindex.htmlからのパスになるため、開発環境と本番環境では、パスが変わってしまうことに注意してください。
# 6. 開発環境と本番環境の確認
開発環境と本番環境の確認方法は、`process.env.NODE_ENV`の値で確認できます。
値が`development`なら開発環境、`production`なら本番環境となりますので、この値を元に

```
const isDevelop = process.env.NODE_ENV==='development'
```
という感じで設定しておけば、`isDevelop`が`true`なら開発環境、`false`なら本番環境、といった具合に切り替えがしやすくなります。

# 7. ビルド後もデータを編集したい
本番環境にビルドした場合、`dist_electron`ディレクトリにデータが出力されますが、
インストーラ形式ではないアプリケーションデータは、`dist_electron/win-unpacked`という場所に保存されます。
htmlファイルなどの編集データは、`dist_electron/win-unpacked/resources/app.asar`という場所にパッケージ化されて保存されます。
パッケージ化させたくない場合、`vue.config.js`に追記を行います。

```javascript:vue.config.js
module.exports = {
    pluginOptions:{
        electronBuilder:{
            nodeIntegration:true,
            builderOptions:{  // <--追記
                asar:false    // <--追記
            }                 // <--追記
        }
    }
}
```

# 8. 参考
[app.getPath](https://www.electronjs.org/docs/api/app#appgetpathname)
[WebStormでVue3のElectronアプリを作る](https://qiita.com/kaluna/items/256d1e32fe73986dc266Vue3%E3%81%8CElectron)