【Electron入門】GithubのIssueを一瞬で確認できるアプリを作って業務効率化してみた #2


はじめに

前回はwindowの作成をしました。
今回はGithubAPIを導入していこうと思います。
長くなってしまうのでJavaScriptでDOMの操作をする部分やCSSの説明は省きます。
気になる方はコードをご確認ください!

完成品

option(alt) + Spaceで表示/非表示が切り替えられます。

現状

test.gif

Access Tokenを生成する

それではやっていきましょう。

Githubにログインし、
Settings > Developer settings > Personal access tokens
と進みます。

image.png

Generate new tokenを押すとtoken作成画面に進めます。

Noteにはtokenを識別するために用途を書きます。自分はgit-electronとしました。

Select scopesでtokenの権限を選択できます。今回はrepoの権限全てにチェックをつけます。

Generate tokenを押すとAccess Tokenが生成されるので、
後ほど使うので、赤く囲まれている部分のAccess Tokenをコピーしておきます。

スクリーンショット 2020-11-21 12.13.34.png

AccessTokenを使ってAPIにアクセスする

実際にGithubAPIを叩いてみます。

通信にはaxiosを使用しました。
Tokenの管理にはdotenvを使用しました。

1 . アプリのルートパスで.envファイルを作成して以下のように編集します。

.env
GH_ACCESS_TOKEN=[先ほどコピーしたAccess Token]
GH_BASE_URL=https://api.github.com

2 . main.jsに以下を追記して.envファイルを読み込みます。

main.js
require("dotenv").config({ path: __dirname + "/.env" });

※ AccessTokenは外部に見られたくないので、Githubで公開する際には.gitignoreを作成してremoteに送らないようにしましょう。

.gitignore
.env



3 . axiosを拡張する

axiosの設定を共通化するために拡張します。
自分はpluginsディレクトリを作成して、配下にaxios.jsを作成しました。

plugins/axios.js
const axiosBase = require("axios");

const axios = axiosBase.create({
  baseURL: process.env.GH_BASE_URL,
  headers: {
    Authorization: "Bearer " + process.env.GH_ACCESS_TOKEN,
    "Content-Type": "application/json",
  },
});
module.exports = axios;

これ以降、axiosを呼び出すときはこのaxios.jsを呼び出します。

これでGithub APIを呼び出す準備は整いました!

フロント(Window)からAPIを呼び出す

Electronにはメインプロセスレンダラープロセスがあります。

メインプロセス内(ここで言うmain.js)でBroeserWindowインスタンスを作成し、そのBroeserWindowインスタンスがレンダラープロセス内でWebページ(html)を表示します。
公式ドキュメント

よってhtmlから呼び出したJavaScriptなどはレンダラープロセスで実行する事になります。

ここで困ることが一点あります。
main.jsはメインプロセス上で動くので、Node.jsの文法が使えますが、レンダラープロセスでは使えません。

requireなどNode.js上で使えるメソッドをフロントからの要求に応じて使えるようにするには、
contextBridgeを使って、メイン⇔プロセス間の通信をセキュアにする必要があります。


詳しく知りたい方は以下の記事がうまくまとまっていると思うので参考にしてみてください!

ElectronでcontextBridgeによる安全なIPC通信 - Qiita
ElectronでcontextBridgeによる安全なIPC通信(受信編) -Qiita

contextBridgeを実装する

contextBridgeを使用する為のpreload.jsをルートディレクトリに作成します。

preload.js
const { contextBridge } = require("electron");

contextBridge.exposeInMainWorld("api", {
  github: {
    getIssues: () => {
      // メインプロセスで行いたい処理を書く
      const axios = require("./plugins/axios");
      axios
        .get("/issues")
        .then((res) => {
          console.log(res);
        })
        .catch((e) => console.log(e));
    },
  },
});

次にmain.jsを修正して、BrowserWindowでpreload.jsを読み込むよう設定します。

main.js
  const win = new BrowserWindow({
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: __dirname + "/preload.js",
    },
    // .....省略......
  })

最後にindex.htmlにscriptタグと発火用のボタンを追加して、preload.jsで定義した関数を呼び出せるようにします。

index.html
  <body style="-webkit-app-region: drag">
    <div style="background: #fff; height: 300px">
      <h1>Hello World!</h1>
      <button onclick="fetchAPI()">get issues</button>
    </div>
  </body>
  <script>
    function fetchAPI() {
      window.api.github.getIssues();
    }
  </script>

ボタンを押して、Electron上でDeveloper toolを開くとIssueのデータが取れていると思います!

image.png

デスクトップアプリとして使いたい場合は、npm run buildでelectron-builderが起動し、dist配下にアプリが生成されます。

DOMの生成やCSSはリポジトリを参考にしてみてください!

最後に

今回はElectroとGithubAPIを組み合わせて業務効率化アプリを作ってみました。

かなり手軽にデスクトップアプリを作成することができた一方、いくつか制限もあったので大規模開発での導入には検討が必要かもしれません。(と言ってもVSCodeなどもelectronで開発されているのである程度安心していいと思っています)

こんな感じで週1~2でアウトプットを記事にしていこうと思います。是非LGTM、フォローの方お願い致します!

Twitterのフォローもお願い致します!