0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Electronでアプリ作成2 Node.jsのモジュールを活用

Last updated at Posted at 2023-10-26

概要

 いまさらかもしれませんが、ElectronはNode.js環境でブラウザベースのデスクトップアプリケーションを作成できるフレームワークです。前回は基本的なアプリ作成方法について、ご説明しました。
 今回は、もう一歩踏み込んで、Node.jsのモジュールを活用する方法を学びます。サンプルとしファイル操作を行うfsモジュールを利用したElectronアプリを紹介します。
 htmlファイルにJavascriptでコーディングしても、ブラウザからファイル操作は基本的にできません。Electronはブラウザベースのアプリですが、nodeベースのアプリでもあります。nodeのfsモジュールはファイル操作がでます。とういうことは、ブラウザベースのアプリもElectronなら、nodeの力をかりてファイル操作が、できるはずではありませんか!
 そうなんだ、じゃあ簡単に出来るんだ!と思っていたら、自分のようなJavascript知識レベルが浅はかな人間では、実行できるまで、まぁまぁ時間がかかってしまいました。自分のやろうとしていることの解説サイトも少ないようでした(検索力がないだけかも)。
 というわけで、ElectronがNode.jsのモジュールを活用するためのサンプルコードをできるだけ、簡略した形で書いております。今回も公式サイトを存分に活用しております。

準備1

ファイルの書き込みを行う、Electronアプリを作成します。以下の環境にて動作を確認しております。
Windows11
node.js v18.18.1
electron v27.0.0

Promise型について理解があった方がよさげです。わかりやすい解説ありがとうございます。

準備2

 まずは、前回と同様にElectronアプリの作成を行います。

この先、
・preload.js
・main.js
・index.html
を修正していきます。

preload.js

ざっくり言えば、以下の通りです。
・main.js メインプロセス(Node.js)
・index.html レンダラープロセス(ブラウザ表示)
・preload.js メインとレンダラーの橋渡し
セキュリティ面からレンダラープロセスとメインプロセスを分離する必要があるので、その仲介役としてpreload.jsが存在しています。以下の例の場合、レンダラープロセスからwindow.myObj.appendTxt()にてメインプロセスにアプローチします。メインプロセスではチャンネル'appendTxt'を拾って、処理を実行します。

preload.js
// preload.jsはレンダラーからNode.jsにアクセスするためのファイルです
const { contextBridge, ipcRenderer } = require('electron');

// メインプロセスから分離した処理をレンダラーに'myObj'として公開します
// preload.jsのinvokeとmain.jsのhandleがセットになっており
// invokeされたをチャンネル'appendTxt'をメインプロセスのhandleで拾う
contextBridge.exposeInMainWorld('myObj', {
    appendTxt: async (myText) => ipcRenderer.invoke('appendTxt', myText),
});

main.js

app.whenReady内のipcMain.handleにてチャンネル'appendTxt'を拾って処理をします。第2引数がPromise型のコールバック関数として、処理を記述しています。プロジェクト内に「text.txt」ファイルをなければ作成し、fsモジュールを使って文字列を追記しています。コールバック関数はPromise型でなくてもよいようですが、asyncを外しても、なぜかPromise型で返るのだけど、、、理由はわかりません。サンプルコードもPromise型になってるので、第2引数はPromise型と思いこんどきます。

main.js
// main.jsはNode.jsにて動作する requireにてelectronモジュールを読み込んでいる
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
//fsモジュールの読み込み
const fs = require('fs');

// ウィンドウの作成準備
const createWindow = () => {
    const win = new BrowserWindow({
        width: 800,   //ウィンドウサイズ
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js'), //プレローダーの指定
        }
    });
    // 読み込むファイル
    win.loadFile('index.html');
    // デベロッパーツールを開く 不要ならコメントアウト
    win.webContents.openDevTools();
}

//ウィンドウの初期化時
app.whenReady().then(() => {
    // preload.jsにてinvokeされたチャンネル'appendTxt'を拾い呼び出される
    // 第2引数がPromise型のコールバック関数になっています。
    ipcMain.handle('appendTxt', async (eve, myText) => {
        const writeString = new Date().toLocaleString() + ':' + myText + '\n';
        fs.appendFileSync('./text.txt', writeString, 'utf-8', (err) => {
            if (err) throw err;
        });
        return "書き込み文字列:" + writeString;
    });
    
    // ウィンドウの表示
    createWindow();
    // macOS用
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow();
    });
})

// ウィンドウのクローズ
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit();
})

index.html

window.myObj.appendTxt()を呼び出し、文字列をファイルに書き込みます。プロジェクトフォルダ内に「text.txt」が作成され、ボタンを押すたびに文字列が追記されます。

index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <title>Electron基本2</title>
</head>

<body>
  <h1>Electron基本2</h1>
  <input type="text" id="text">
  <input type="button" id="button" value="書込">
  <script>
    const write = document.getElementById("button");
    const text = document.getElementById("text");
    write.onclick = () => {
      // preload.js経由にてメインプロセスの処理を呼び出します。
      window.myObj.appendTxt(text.value)
        .then((value) => { console.log(value) })
        .catch((reason) => { console.log(reason) });
    }
  </script>
</body>

</html>

image.png

できる限り、簡素なコーディングにしたつもりですが、いかがでしょうか。Electronでnodeの機能がフルに使えるとなると、やれることも広がるのではないでしょうか。つたない説明でしたが、読んでもらって感謝です。ありがとうございました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?