4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Electronの子プロセスで、Expressサーバーを起動する

Last updated at Posted at 2025-02-28

◾️ はじめに

 現在、Electron + Vue + TypeScript を使ってアプリケーションを開発しています。
その中で、Electronの子プロセスで、Expressサーバーを起動する実装に苦戦したため、同じ問題で悩んでいる方の助けになればと思い、この記事を書きました。
参考になれば幸いです。
※今回は Electronの概要についての説明は省略します。

📂 ディレクトリ構造

electron
 |- server
 |  |- server.ts
 |- main.ts

◾️ やりたかったこと

 Electronのメインプロセスとは別に子プロセスを作成し、サーバーを起動したい!

◾️ 問題点

 最初に、Node.jsのchild_process.spawn()を使用して子プロセスを起動しようとしました。
しかし、spawn()を使用した際、サーバーが正常に起動しないという問題が発生しました。

spawn()を使った場合の問題点

child_process.spawn()を使用すると、Electronのメインプロセスとは完全に独立したプロセスとしてサーバーが起動してしまうため、以下の問題が発生しました。

1.サーバーが起動しない
spawn()でserver.tsを実行しようとすると、サーバーが正常に動作しませんでした。
stdio: 'inherit'を設定してもログが出力されず、原因の特定が難しかったです。

stdio: "inheritとは
子プロセスの標準入出力(stdin, stdout, stderr)を親プロセスと共有する。
→ 子プロセスのログやエラーメッセージがそのまま親プロセスのコンソールに出力される。

2.メインプロセスと通信できない
spawn()で起動したサーバープロセスは完全に独立したプロセスになるため、Electronのメインプロセスと IPC 通信ができず、状態管理が難しくなりました。

3.Electronの終了時にサーバープロセスを制御しづらい
detached: trueを設定すると、Electronを終了してもサーバープロセスが生き続ける可能性があります。

detached: trueとは
親プロセス(Electron)と子プロセス(サーバー)の紐付けを解除し、完全に独立したプロセスとして動作させることができる。

◾️ 解決策

child_process.fork()を使用することで、期待通りの動作を実現できました✨

child_process.fork()は、Node.jsのモジュールとして別プロセスを起動するため、spawn()とは異なり、Electronのメインプロセスと同じNode.js実行環境を引き継ぎます。

その結果、server.tsの依存関係や環境の違いによる問題が発生せず、fork()を使用することで正常にサーバーを起動できました。

一方で、spawn()を使用すると、完全に独立したプロセスとして起動されるため、Electronの実行環境を継承できず、サーバーが正しく動作しなかったのだと考えられます。

◾️ 実装方法

Express を使って、シンプルなローカルサーバーを作成します。

server.ts
import express from 'express'
import log from 'electron-log'

const PORT = 9090
const server = express()

// サーバー起動
server.listen(PORT, () => {
  log.info(`Local server started at http://localhost:${PORT}`)
})
main.ts
import { app, BrowserWindow } from 'electron'
import * as path from 'path'
import { fork } from 'child_process'

let mainWindow: BrowserWindow | null
let serverProcess: any

// アプリケーションが準備完了になった時に実行
app.on('ready', () => {
 // サーバースクリプトのパスを取得
  const serverPath = path.join(__dirname, 'server/server.js')
  // 子プロセスとしてサーバーを起動
  const serverProcess = fork(serverPath, [])

 // メインウィンドウの作成
  mainWindow = new BrowserWindow({
    'width': 800,
    'height': 600,
    'show': true
  })
})

// すべてのウィンドウが閉じられたときに実行
app.on('window-all-closed', () => {
  // サーバープロセスが存在していたら終了させる 
  if (serverProcess) {
    serverProcess.kill()
  }
  // アプリケーションを終了
  app.quit()
})

◾️ 最後に

最後まで読んでいただき、ありがとうございます!同じように悩んでいる方の助けになれば嬉しいです😊

4
0
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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?