Electronでデスクトップアプリを作ろうとしたメモ

月曜日の祝日、陰陽師の週替りイベントの好機を逃すという悲しい思いをしまして。
いつも開いてるPC版の隣で通知とかするアプリがあればなーと思ったとき、Electronで作れるんでは?とその存在を思い出したのでした。
いつの時代も悔しさは己の闘志を奮起してくれるものです。

ElectronはもともとGitHubがAtom作るために生み出したやつ。
6年前からあって名前はよく聞いてたけど、Web技術でデスクトップアプリ化したいと思うものがなかったら使う機会ないよなーっていう存在だった。
逆にいうとWeb技術しか無くてもデスクトップアプリが作れるすごいフレームワークである。

試してみる

どんなものか様子見するなら、
APIのデモリポジトリで動作デモとサンプルソースが見れるやつと、

クイックスタートのリポジトリ
Hello Worldが起動するやつが動かせる。

どっちも中身はhtml/js/cssの組み合わせたもの。
Electronの実態はChromiumとNode.jsである。
Photoshopのエクステンションを思い出す…。

Electron Forge使ってみる

イチからアプリを作る手順はここに書いてある。
これはnpm initして必要なファイルを手動で追加していくやつだが、
諸々お手軽にしてくれるツールElectron Forgeを使うこともできる。
これだとコマンド3つ叩くだけでHello World状態になる。

yarn create electron-app my-app
cd my-app
yarn start

webpackテンプレートもある。

yarn create electron-app my-new-app --template=webpack

TypeScript使えないと死んでしまう人はこっち使うのがよさそう。

Electron Forgeだとアプリ化するのもコマンド1つ叩くだけである。

yarn run publish

ReactとかVueとかを使う

Webpackが動くならReactもVueも使えるわけで、Electron Forgeで生成したやつでVueが動くようにしてみた。
CSSはPostCSSのみにしておく。

いるものインストールして、

yarn add vue
yarn add postcss postcss-loader file-loader --dev
yarn add autoprefixer postcss-preset-env
yarn add vue-loader vue-style-loader vue-template-compiler --dev

webpack.rules.jsに追加

{
    test: /\.vue$/,
    loader: 'vue-loader',
  }

webpack.renderer.config.jsに追加

const rules = require('./webpack.rules');
const VueLoaderPlugin = require('vue-loader/lib/plugin')

rules.push({
  test: /\.css$/,
  use: [
    'vue-style-loader',
    {
      loader: 'css-loader',
      options: { importLoaders: 1 }
    },
    'postcss-loader'
  ],
});

rules.push({
  test: /\.(png|svg|jpg|gif)$/,
  use: [
    'file-loader'
  ]
});

module.exports = {
  // Put your normal webpack config below here
  module: {
    rules,
  },
  plugins: [
    // make sure to include the plugin!
    new VueLoaderPlugin()
  ]
};

renderer.jsにVueのコード入れて、

import Vue from "vue";
import App from "./App.vue";

Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

index.htmlのルート要素にID振って

  <body>
    <div id="app"></div>
  </body>

App.vue作成する。

<template>
<div class="content">
  <h1>&#x1f496; Brahma!</h1>
  <p>Hello World!</p>
</div>
</template>

<script>
export default {
  name: "App",
}
</script>

<style lang="css">

:root {
  --textColor: #333;
  --secondaryColor: lab(32.5 38.5 -47.6 / 90%);
}

body {
  background: url('./images/bg.png');
}

.content {
  color: var(--textColor);
}

h1 {
  color: var(--secondaryColor);
}
</style>

で、yarn startして立ち上がったアプリがエラー無く動いてたらおk。

※プロジェクト名を神々の名前にしてる名残があるけど気にしないでほしい…

electron-vueの利用

Vue CLIみたいなやつで始めたいならelectron-vueを使う手もありそうだった。
これも一応試してみたが、長くメンテされてないせいでそのままだとNode.js v12.0では動かない。

Webpack ReferenceError: process is not defined #871のコメントより、
以下3箇所修正する。

src/main/index.js

  mainWindow = new BrowserWindow({
    height: 563,
    useContentSize: true,
    width: 1000,
    webPreferences: {
      nodeIntegration: true // ←追加
    }
  })

src/index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <% if (htmlWebpackPlugin.options.nodeModules) { %>
        <!-- Add `node_modules/` to global paths so `require` works properly in development -->
        <script>
          require('module').globalPaths.push('<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>')
        </script>
    <% } %>
</head>
<body>

<div id="app">
</div>

<!-- Set `__static` path to static files in production -->
<% if (!htmlWebpackPlugin.options.isBrowser && !htmlWebpackPlugin.options.isDevelopment) { %>
    <script>
      window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
    </script>
<% } %>

<!-- webpack builds are automatically injected -->
</body>
</html>

.electron-vue/webpack.renderer.js

new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve(__dirname, '../src/index.ejs'),
      minify: {
        collapseWhitespace: true,
        removeAttributeQuotes: true,
        removeComments: true
      },
      isBrowser: false,
      isDevelopment: process.env.NODE_ENV !== 'production',
      nodeModules: process.env.NODE_ENV !== 'production'
        ? path.resolve(__dirname, '../node_modules')
        : false
    }),

で、起動したアプリをよく見るとElectronのバージョンが2系と古すぎるので、入れ替えて6系にする。
うまく動けばこんな感じ。

※spectronとか古いバージョンで入ったやつ全部入れ替える必要がある。

electron-nuxtの利用

electron-nuxtはelectron-vueのメンテされなさに業を煮やした(のかもしれない)有志が作ったNuxt.js版である。
前述のVue版はあらゆるところでエラーを吐くので、その解決に時間取られるくらいならこちらを使う方が精神衛生的にも良さそう。

npm install -g vue-cli
vue init michalzaq12/electron-nuxt electron-nuxt
cd electron-nuxt
yarn
yarn run dev

rendererディレクトリの中がNuxt.jsになっている。

よく見るとこれもElectron5系でちょっと古いしテストが両方とも動かなかった。
CSSをSassにするとunitテストでエラーを吐いたりもする。
絶賛開発中みたいだから商業用途にはリスクがありそう。

Nuxt.js + Electron

create-nuxt-appして生成したNuxt.jsのプロジェクトディレクトリにElectronを導入する、つまり全部手動でやってる人もいた。
Nuxt.js+Electronを試してみるv2
人が作ってるものは更新止まったりするし、古い状態で止まってるのを修正する手間考えると最初から自前でやっつけた方が早いことはままありますな。

electron-react-boilerplateの利用

Reactの方はelectron-react-boilerplateというのがあった。
ちゃんとメンテもされているようす。

git clone --depth 1 --single-branch --branch master https://github.com/electron-react-boilerplate/electron-react-boilerplate.git electron-react
cd electron-react
yarn

yarn devでDevelopmentモード起動

いろいろ試してたら時間切れになった😇
モチベが残れば記事も続きます…

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください