Electron から Nightmare を使うときに注意すること


Nightmare は Electron を内蔵しているわけですが、母体の Electron から NightMare を起動したいときの注意点。

Nightmare じゃなくて Eramthgin を使う

Make nightmare isomorphic でも、述べられているように、 Electron の内部から Nightmare を起動する機能は実装中らしい。
代わりに [email protected] を使用するといいよと書いてある。

レンダラープロセスではなく、メインプロセスに書く

さらに上記に補足する感じで、母体の Electron の node を使用する関係上か、メインプロセスに書くことと記載されている。

LandingPage.vue
<template>
  <div id="wrapper">
    <button @click="add">お試し</button>
  </div>
</template>

<script>
import { ipcRenderer } from 'electron'

export default {
  name: "landing-page",
  methods: {
    add() {
      const result = ipcRenderer.sendSync('sync', '引数')
      console.log(result)
    }
  }
};
</script>

レンダラープロセスでメインプロセスと通信を行う。
ipcRendererを用いる。

index.js
import { app, Menu, BrowserWindow, ipcMain } from 'electron'

// 中略

const Nightmare = require("eramthgin");
const nightmare = Nightmare({
  show: true,
  backgroundColor: '#fff'
});

ipcMain.on('sync', (event, arg) => {  
  nightmare
    .goto("https://google.com/") // 指定URLに遷移
    .wait(1000)
    .screenshot(require('path').join(__dirname, 'screenshot1.png'))
    .end()
    .then(function () { console.log("Screenshot Saved") })
    .catch(function (error) {
      console.error('test failed:', error);
    });
  console.log(arg)
  event.returnValue = 'pong';

})

スクリーンショットはソースを修正する必要あり

母体の Electron のバージョンが 3x なので、そのままだと .screenshot() を使うと動作が止まる。
eramthgin は2年前なのでちと古い。

なので、/node_modules/eramthgin/lib/runner.js/node_modules/eramthgin/lib/actions.jsの2つを修正する。

runner.js
parent.respondTo('screenshot', function (path, clip, done) {
  // https://gist.github.com/twolfson/0d374d9d7f26eefe7d38
  var args = [function handleCapture(img) {
    // done(null, img.toPng());
    done(null, img.toPNG());
  }];
  if (clip) args.unshift(clip);
  frameManager.requestFrame(function() {
    win.capturePage.apply(win, args);
  });
});

img.toPng()からimg.toPNG()に修正する。

actions.js
exports.screenshot = function (path, clip, done) {
  debug('.screenshot()');
  if (typeof path === 'function') {
    done = path;
    clip = undefined;
    path = undefined;
  } else if (typeof clip === 'function') {
    done = clip;
    clip = (typeof path === 'string') ? undefined : path;
    path = (typeof path === 'string') ? path : undefined;
  }
  this.child.call('screenshot', path, clip, function (error, img) {
    // var buf = new Buffer(img.data);
    var buf = new Buffer(img);

    debug('.screenshot() captured with length %s', buf.length);
    path ? fs.writeFile(path, buf, done) : done(null, buf);
  });
};

img.dataimgに。
toPNG()にしたことによって、imgにはバイナリが入る模様。

それでは、よいElectronライフを