Help us understand the problem. What is going on with this article?

Nuxt.js+Electronを試してみるv2

More than 1 year has passed since last update.

はじめに

以前nuxt+electronの記事を書いたのですが、だいぶ古くなってきていて最新バージョンのElectronだと動かないみたいなことが起きていたので書き直すことにしました
前記事をリンクしている記事とかもあったので、編集は避けて新規記事としています

今回の記事を元に少し手を加えたリポジトリ

準備

Nuxt.js

プロジェクトを作るフォルダをカレントディレクトリにして下記を実行

npx create-nuxt-app

実行されると色々質問されますが、この記事では下記のような感じで最小構成としています
※Single Page Appにすること

create-nuxt-app v2.10.1
✨  Generating Nuxt.js project in .
? Project name nuxt-electron
? Project description nuxt-electron
? Author name tamfoi
? Choose the package manager Npm
? Choose UI framework None
? Choose custom server framework None (Recommended)
? Choose Nuxt.js modules (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose linting tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Choose test framework None
? Choose rendering mode Single Page App
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)

Electron

下記コマンド実行

npm install --save-dev electron
npm install --save-dev electron-builder
npm install --save-dev electron-devtools-installer
  • electron = electron本体
  • electron-builder = electronのビルドツール
  • electron-devtools-installer = vue devtoolsを開発中に使うために必要

その他のモジュール

下記コマンド実行

npm install --save-dev cross-env
  • cross-env = スクリプト実行時に環境変数を設定できるようにする

ファイル編集 & 作成

package.json

下記のように編集

package.json
{
  "name": "nuxt-electron",
  "version": "0.0.0",
  "description": "nuxt-electron",
  "author": "tamfoi",
  "private": true,
  "main": "entry-point.js",
  "scripts": {
    "dev": "cross-env NODE_ENV=development electron .",
    "build": "cross-env NODE_ENV=production nuxt build && electron-builder"
  },
  "build": {
    "appId": "nuxt-electron",
    "directories": {
      "output": "build"
    }
  },
  "dependencies": {
    "nuxt": "^2.0.0"
  },
  "devDependencies": {
    "cross-env": "^5.2.1",
    "electron": "^6.0.7",
    "electron-builder": "^21.2.0",
    "electron-devtools-installer": "^2.2.4"
  }
}

nuxt.config.js

下記のように編集

nuxt.config.js
module.exports = {
  mode: "spa",
  /*
   ** Headers of the page
   */
  head: {
    title: process.env.npm_package_name || "",
    meta: [
      { charset: "utf-8" },
      { name: "viewport", content: "width=device-width, initial-scale=1" },
      {
        hid: "description",
        name: "description",
        content: process.env.npm_package_description || ""
      }
    ],
    link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: "#fff" },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [],
  /*
   ** Nuxt.js modules
   */
  modules: [],

  router: {
    mode: "hash"
  },

  dev: process.env.NODE_ENV === "development",

  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {
      config.output.publicPath = "./_nuxt/";
    }
  }
};

entry-point.js

ファイルをプロジェクトのルート直下に作成して下記のように編集

entry-point.js
const http = require("http");
const path = require("path");
const { Nuxt, Builder } = require("nuxt");
let config = require("./nuxt.config.js");

config.rootDir = __dirname;

const nuxt = new Nuxt(config);
const builder = new Builder(nuxt);
const server = http.createServer(nuxt.render);

let _NUXT_URL_ = "";
if (config.dev) {
  builder.build().catch(err => {
    console.error(err);
    process.exit(1);
  });
  server.listen();
  _NUXT_URL_ = `http://localhost:${server.address().port}`;
  console.log(`Nuxt working on ${_NUXT_URL_}`);
} else {
  _NUXT_URL_ = "file://" + __dirname + "/dist/index.html";
}

let win = null;
const electron = require("electron");
const app = electron.app;
const newWin = () => {
  win = new electron.BrowserWindow({
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.resolve(path.join(__dirname, "preload.js"))
    }
  });
  win.on("closed", () => (win = null));
  if (config.dev) {
    const {
      default: installExtension,
      VUEJS_DEVTOOLS
    } = require("electron-devtools-installer");
    installExtension(VUEJS_DEVTOOLS.id)
      .then(name => {
        console.log(`Added Extension:  ${name}`);
        win.webContents.openDevTools();
      })
      .catch(err => console.log("An error occurred: ", err));
    const pollServer = () => {
      http
        .get(_NUXT_URL_, res => {
          if (res.statusCode === 200) {
            win.loadURL(_NUXT_URL_);
          } else {
            console.log("restart poolServer");
            setTimeout(pollServer, 300);
          }
        })
        .on("error", pollServer);
    };
    pollServer();
  } else {
    return win.loadURL(_NUXT_URL_);
  }
};
app.on("ready", newWin);
app.on("window-all-closed", () => app.quit());
app.on("activate", () => win === null && newWin());

preload.js

ファイルをプロジェクトのルート直下に作成してください。
中身は空で良くて実際に開発していく時に使うようになります。

おわりに

前回からいくつかアップデートしましたが一番大きいのはElectronのセキュリティ対策に追従したところになります。
どういう変更があったかは下記のスライドを見ると良いかと思います。このスライドにpreload.jsの使い道も書いてあります!
Electron: Context Isolationの欠如を利用した任意コード実行 / Electron: Abusing the lack of context isolation - CureCon(ja)

まだ今回のセットアップでアプリを作りきってないので何か不具合が出るかもしれません。その時はコメントで教えていただければ幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away