みかづきブログ・カスタム

基本的にはちょちょいのほいです。

ElectronでBrowserWindowではなく外部ブラウザを使う 💻

f:id:kimizuka:20211002150457p:plain

起動した際に、

・expressでサーバを立てる(ポートは3000)
・publicディレクトリの中身をホスティングする
・socket.ioでサーバとクライアントの通信を行う(ipc通信の代替)
・Google Chromeを起動しhttp://localhost:3000を開く(Chromeのダウンロードは別途必要)

ということを行うアプリをつくりました。

github.com

これだけでは、何の役にも立たないアプリなのですが、Express + socket.ioで作ったウェブサイトをChromium以外のブラウザで見るアプリを作りたい時に雛形として使えます。
Electronアプリにしてしまうと、Chromiumでレンダリングされてしまうので。

直近でChromiumではなくChromeでレンダリングしたいケースがあったので制作した次第ですが、ソースコードを書き換えれば他のブラウザを開くことも可能です。

ただ、Node.jsが入っているPCであれば、まったくもって必要ないアプリなのですが、Node.jsをインストールすることなくexpressサーバを立てることができるところが魅力です。
Macでのみ動作を確認してます。

ソースコード

package.json
{
  "name": "electron-chrome",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "electron .",
    "build": "electron-packager . electron-chrome --platform=darwin --arch=x64"
  },
  "repository": "git@github.com:kimizuka/electron-chrome.git",
  "author": "kimizuka <f.kimizuka@gmail.com>",
  "license": "MIT",
  "dependencies": {
    "express": "^4.17.1",
    "open": "^8.2.1",
    "socket.io": "^4.2.0"
  },
  "devDependencies": {
    "electron": "^15.1.0",
    "electron-packager": "^15.4.0"
  }
}

app.js
const { app } = require('electron');
const express = require('express');
const server = express();
const http = require('http').Server(server);
const io = require('socket.io')(http);
const open = require('open');

server.use('/', express.static(`${ __dirname }/public`));

io.on('connection', (socket) => {
  socket.on('disconnect', () => {
    app.quit();
  });
});

http.listen(3000, '0.0.0.0');

open('http://localhost:3000', {
  app: open.apps.chrome
});

public/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8" />
  <title>electron-chrome</title>
  <meta name="viewport" content="width=device-width, viewport-fit=cover, shrink-to-fit=no" />
  <link rel="stylesheet" href="index.css" />
</head>
<body>
  <h1>electron-chrome</h1>
  <script src="./socket.io.min.js"></script>
  <script type="module" src="index.js"></script>
</body>
</html>
public/index.js
'use strict';

const socket = io.connect();

socket.on('disconnect', () => {
  window.close();
});


非常に迷ったんですが、

・アプリが終了した際に、ブラウザを閉じる
・ブラウザを閉じた際に、アプリを終了する

を実現するために、app.jsとpublic/index.jsに、

io.on('connection', (socket) => {
  socket.on('disconnect', () => {
    app.quit();
  });
});
socket.on('disconnect', () => {
  window.close();
});

という記述を入れています。
app.js側はブラウザをリロードした際もdisconnectが走り、アプリが終了してしまうため、開発の時はコメントアウトしておいた方が良さそうです。