[Electron] 駆け出しエンジニアの自社開発 製作過程や技術周りのお話

こんにちは、私は株式会社スミリオンで駆け出しエンジニアをやっています。

先日、スミリオンでは自社製品の「CSV編集アプリ BUGGY」をリリースしました。
本記事ではBUGGYの技術周りのご紹介と製作過程での苦労した点などを知見として共有します。


# BUGGYとは？
スミリオンで開発したフリーのデスクトップアプリで、
**1．読み込んだCSVファイルの項目を『編集』『並び替え』して出力する**
**2．編集手順をデータとして保存し、同じ編集作業の繰り返しを防止する**
の2つの機能をメインとして製作されたアプリです。

**CSV編集アプリ BUGGY**
https://csv-buggy.com/

# Electron
BUGGYは「**Electron**」というフレームワークを使って製作しました。
皆さんはElectronをご存じでしょうか？

このフレームワークはGoogleのChromeに使用されている
ChroniumエンジンとNode.jsを組み合わせてデスクトップアプリケーションを開発することが出来るフレームワークです。

**Webページを作るような感覚でデスクトップアプリを作ることが出来る**
という便利な特徴を持っています。

BUGGYも表面のデザインはhtml+CSS
内部の処理はjavascriptで記述されています。

**Electron公式ページ**
https://www.electronjs.org/

# BUGGY製作過程
### 画面デザイン取込
私がBUGGYの開発に参画した時、大まかな設計や画面デザインは完了しており、
最初の作業は自社のデザイナーさんからあがってきた画面デザインをhtmlとCSSで画面上に実装していく部分からでした。
ボタンの色の変化やデザインを1個1個構築していきますが、画面のレイアウト崩れが頻発したり画面上に謎の線が残ったりと知識に乏しい私には既に大変な作業でした。



<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696024/3f9b89f7-84d4-e225-a3b5-4b28bd52b389.png" width=50%>

(初期のデザインはこんな感じ)

### 各機能実装
次に裏側の処理の実装に入っていきます。
設計書を見つつ、実装方法を調べるの繰り返しで何とか作り上げていきました。
先輩と作業を分担しながら少しずつ進行していきます。



### テスト+障害対応
製造技術が未熟なためか、実装中に判明した分も含めて障害が結構な数出てきました。
障害管理表に原因と対応策を纏めながら障害を解消していきます。
デグレーション(障害を解消したら別の箇所で障害発生)に悩まされつつ、エラーの件数も徐々に減少し完成形が見えてきました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696024/654be989-739c-e498-3d28-4d33223e80bf.png" width=50%>
(完成版 初期と比べると所々デザインが変わったり新しいボタンが増えていたりします)

### パッケージング
パッケージングにはElectronフレームワークの機能の1つ、electron-builderを使用しました。
簡単に使用方法をご説明します。

①srcフォルダと同階層で以下のコマンドを実行し、electron-builderをインストールします。
```
$ npm install -g yarn
$ yarn add electron-builder --dev
```

②srcフォルダと同階層にpackage.jsonを作成、編集
```javascript:package.json

{
  "name": "BUGGY", // アプリ名
  "version": "1.0.0", // アプリバージョン
  "description": "csv_sort&edit_app", // アプリの説明
  "main": "src/main.js", // メインファイルのパス
  "author": "Smillione", // 作者名
  "license": "Smillione.Inc", // ライセンス者名
  "scripts": { // 起動時コマンド
    "start": "electron ./src"
  },
  "devDependencies": { // 開発版使用パッケージ
    "electron": "^13.1.3",
    "electron-builder": "^22.14.13",
    "electron-is-dev": "^2.0.0",
    "electron-reload": "^2.0.0-alpha.1",
    "electron-store": "^8.0.1",
    "eslint": "^8.5.0",
    "eslint-config-google": "^0.14.0",
    "npm-run-all": "^4.1.5"
  },
  "dependencies": { // 配布版使用パッケージ
      "electron-store": "^8.0.1"
      },
  "build": { // ビルド設定
    "appId": "BUGGY",
    "productName": "BUGGY",
    "directories": { // 出力先フォルダ名
      "output": "package"
    },
    "win": { // windowsパッケージング時設定
      "target": "nsis",
      "icon": "icon/icon.png" // アイコンに使う画像のパス
    },
    "mac": {
      "target": "dmg", // macパッケージング時設定
      "icon": "icon/icon.png"
    }
  },
  "files": [ // パッケージに同梱したいフォルダやファイルを全て記述
    "src",
    "***",
    "***",
    "***",
    "***"
  ]
}

```
③ パッケージ化コマンドを実行する
```
windows 64bit版 インストーラー
$ npx electron-builder --win --x64

macOS 64bit版　インストーラー
$ npx electron-builder --mac --x64
```

以上の比較的シンプルな設定でpackage.jsonのbuild->directories->outputで指定したディレクトリに、
windowsは.exe , macOSは.dmg のインストーラーが生成されます。

それぞれインストーラー単体で動作可能です。



# BUGGY開発 苦労話
BUGGYは私がスミリオンに入社して初めてしっかりと開発に関わったプロジェクトです。
Electronについての知識もゼロの状態で開発をスタートしました。
そこで、BUGGYの開発中に苦労したことを纏めて知見として残します。

### プロセス間通信
大きく躓いたところその①は**プロセス間の処理の受け渡し**です。

Electronフレームワークは、大きく2つのパーツに分けられています。
それが**メインプロセス**と**レンダラープロセス**です。
メインプロセスはOSと直接繋がっていて、Node.jsで構成されています。
レンダラープロセスはメインプロセス配下のプロセスで、一般的なWebページと同様にhtml,CSS,javascript等で構成されます。

ここで問題になってくるのは、メインプロセスとレンダラープロセス間は直接の関数呼び出しが不可であるという点です。
2プロセス間は内部で**IPC通信**という通信手段で接続されており、通信を介さなければ互いにアクセスが出来ません。
そのお陰でセキュリティが向上しているのですが、このIPC通信の概念を理解するのに苦心しました。

この通信が無ければレンダラープロセスからはNode.jsの機能すら呼び出せないので大変です。
**importやexportも使えないんです。**

社内の先輩方に伺い、色々なサイトの情報を巡ったりしてなんとか構築したのを覚えています。
最終的に**preload.js**という2プロセス間の通信を行うためのファイルを作成することで解決出来ました。

preload.jsを作成するに当たって、こちらの記事が大変参考になりました。

https://qiita.com/Quantum/items/4841aa18643b8ef1fc11

### CSVの禁則文字対応
**大きく躓いたところその２はCSVの禁則文字対応です。**

BUGGYでは読み込んだデータにカンマやダブルクォーテーションが含まれていると項目が不自然な箇所で切られてしまう、空欄となるなどの不具合が発生しました。
**障害例1：[デ,ータ1]という項目が[空欄][-タ1]の2項目に分割されて読み込まれてしまう
障害例2：出力した[デ,ータ1]の項目をExcelで読み込むと一部空欄になる、列がずれる**

これらはCSV項目を取り込むことが必須のソフトにとっては何としても解決しなければならない問題！
ということで色々と調べた結果たどり着いたのが、CSVの国際規格である**RFC4180規格に対応したCSVパーサ**でした。
このパーサに項目のデータを入力するとExcelや各種CSVエディタで正常に表示出来る形式に文字列を変更して出力してくれます。

CSVパーサは以下の物を使用させていただきました。

http://vird2002.s8.xrea.com/javascript/rfc4180.html

これを使えば問題解決！…と思ったのですが、まだ問題が続きます。

### inputタグの禁則文字対応
BUGGYは画面上への文字の表示にhtmlのinputタグに設定したvaluesの値を表示に使用する箇所が存在しているのですが、
values内の文字にダブルクォーテーションが2つ以上使用されていると、最初の2つのダブルクォーテーション間の文字を値としてしまいます。
① 表示する項目名が「"データ1"」
② valuesには=""データ1""が入る
③ この時、values=""（空欄）と認識するため画面上に文字が表示されない

タグの仕様のため一見解決策が見えず、inputタグを使用している箇所の処理を全部書き換えるかどうか本気で悩みました。
が、これもしっかりと解決法がありました。

ダブルクォーテーション(")を表す特殊文字に「＆quot;」が存在します。
この特殊文字はvaluesの中に値として入れた際、ダブルクォーテーションとして表示してくれる便利なものです。
そこでvaluesの中に入れる値が入った変数をリプレイスします。
```
[変数].replace(/\"/g, '&quot;')
```
の形で、中にあるダブルクォーテーションを特殊文字「＆quot;」に置き換えることで、綺麗に表示が出来ました。

### macだけ配布パッケージが展開出来ない

公開予定日のデプロイ作業時に発生した不具合です。
BUGGYはインストーラーを同梱したzipファイルを利用者にダウンロードして貰う形での配布を行っています。

事前に小さいサイズのフォルダでダウンロードテストを行っており、後はダウンロードするフォルダを差し替えるだけ…
の予定でしたが、ここで問題が発生します。

**mac環境でのみ、ダウンロードしたフォルダが展開できない**のです。
windows環境で作ったzipファイルが問題なのかと、mac環境で複数のツールを使ってパッケージングをやり直しても解決せず。
win-mac間のファイルの移動時に変換が入っている可能性や、ダウンロードサーバーへのアップロード時の問題？など色々と試行錯誤してみたもののどれも該当しませんでした。

心が折れそうになり、ふともう一度macでダウンロードをかけてみた時、ふと気付きました。
**「あれ？このパッケージ、ダウンロード早すぎない…？」**
BUGGYのパッケージは75MB程度の容量があるにも関わらずそのダウンロードが10秒に満たない時間で完了していたのです。
ダウンロードしたパッケージの容量を見てみると…**2.2MB!**

そう、失敗していたのはzipフォルダの展開処理ではなくパッケージのダウンロード処理そのもの、ということです。
windows環境では問題無くダウンロードが成功していたことから、盲点になっていました。

結果ダウンロードに使用する処理を変更し、ダウンロード可能に。
無事に公開作業は完了しました。

# 
そんなこんなで頑張って作ったBUGGYは以下のページからDL出来ます！
便利に使える場面が結構あるので、興味があれば是非使ってみてください！


↓DLはこちらのページ最下部から
https://csv-buggy.com/


# 参考文献
この記事は以下の情報を参考にして執筆しました。

- Electron アプリの配布パッケージを作る (electron-builder)
https://maku.blog/p/2tcs8n2/
- Electronをセキュアな設定の状態で、jsのrequierを行う
https://qiita.com/Quantum/items/4841aa18643b8ef1fc11
- rfc4180.js
http://vird2002.s8.xrea.com/javascript/rfc4180.html
- INPUTのvalueにダブルクォートとシングルクォートを表示させるには
https://atmarkit.itmedia.co.jp/bbs/phpBB/viewtopic.php?topic=13360&forum=7