Using electron in
Monaca & Onsen UI Team

Electron Meetup in Tokyo #1

Masa Tanaka

https://slides.com/masa-tanaka/emu-2017/

MASA TANAKA

Founder & CEO, Asial Corporation

Tokyo, Japan

@massie

masahirotanaka

Hi!

Our Products

Monacaとは

ハイブリッドモバイルアプリの

開発プラットフォーム

For iOS and Android

MonacaのToolchain

Evergreen Technology

Progressive & past aware

Cross platform

CordovAとElectron

Native Code

Cordova

Cordova Plugins

Your

Code

 Native Bridge

Native Code

Node.js (V8)

Main Process

Renderer

IPC

モバイルでもPCでも

Electron in Monaca

Monaca Localkit

  • Electron製
  • Monacaアプリの開発、実機デバッグ、ビルドを行える

 

構造

Electron

monaca-lib

AngularJS

NeDB

IPC Receiver

Directive & Controller

BrowserWindow

Main Process

  • フロントエンド側のフレームワークはAngular 1を使用
    (開発開始が2014年なので)
  • DBはNeDBを使用
  • Windows、Mac、Linux版を提供

開発中に遭遇した課題を紹介します

開発における課題 1/4

複数の開発ツールのサポート

Monaca Localkit

Monaca CLI

Monaca for Visual Studio

Monacaクラウドと同期

共通 npmライブラリ

monaca-libを全ツールにバンドル

Monaca Localkit

Monaca CLI

Monaca for Visual Studio

Electron

+

monaca-lib

Node.js CLI
+

monaca-lib

C#

+

Edge.js
+

monaca-lib

C#にNode.jsを組み込むためのライブラリ

using System;
using System.Threading.Tasks;
using EdgeJs;

class Program
{
    public static async Task Start()
    {
        var func = Edge.Func(@"
            return function (data, callback) {
                callback(null, 'Node.js welcomes ' + data);
            }
        ");

        Console.WriteLine(await func(".NET"));
    }

    static void Main(string[] args)
    {
        Start().Wait();
    }
}

開発における課題 2/4

インストーラーの作成

Localkitは通常のファイル設置に加え、いくつか特殊な処理が必要。

 

  • Monaca Localkit自体がHTTPサーバーとして動作する
  • Monaca iOS Webkit Debug ProxyもTCPポートの受付を行う

Inno Setupを使用 

フリーで使えるInno Setupを用いてWindows用インストーラーを作成。


gulp.task('build-win32', 'Build Electron package for Windows', [ 'asar' ], function () {
  var deferred = Q.defer();
  var destination = 'out/package/win32';
  fs.emptyDirSync(destination);

  var packageJson = require("./package.json");
  var prop = {
    platform: 'win32',
    // snip...
  };

  electronPackager(prop, function(err, appPath) {
    if (err) {
      console.log("Error occurred when packaging electron: " + err);
      return deferred.reject(err);
    }
    step2();
  });

  function step2() {
    fs.copySync("misc/win32/installer-bundles", destination + '/monaca-localkit-win32-ia32');

    require("innosetup-compiler")(path.resolve("./misc/win32/installer.iss"), {
        gui: false,
        verbose: false
    }, function(error) {
      if (error) {
        return deferred.reject(error);
      }

      run('start misc\\win32\\sign.bat').exec("", function(err) {
        if (err) {
          return deferred.reject(err)
        }
        return deferred.resolve("Build complete!");
      });
    });
  }

  return deferred.promise;
});

開発における課題 3/4

多言語への対応

Angular 1 + Angular-Gettextにて対応。

<div class="ng-modal-dialog-header">
  <h1 translate>New Project</h1>
</div>
<tr class="required">
  <th translate>Project Name</th>
  <td>
    <input type="text" size="30" name="projectName" id="projectName" ng-class="{'fieldInvalid' : showValidation && create.form.projectName.$invalid , 'fieldValid': !showValidation }" ng-required="true" required ng-model="project.name">
    <p class="annotation" translate>Name shown in Project List</p>
    <p class="error" ng-show="showValidation &&  invalidPname" translate>Please input valid project name, without including {{ invalidChars }} characters.</p>
  </td>
</tr>
$ gulp run i18n-extract

開発における課題 4/4

Cookieの共有

Node.js (monaca-lib) でログインしたユーザーを

BrowserWindowに引き継ぎたい

Node側

新しいBrowserWindow

Node.js側で確立したセッションをBrowserWindowに受け渡す

var cookie = {
  "name": "Cookie Name",
  "value": "Cookie Value",
  "url": url,
  "domain": "." + domain,
  "hostOnly": false,
  "path": "/",
  "secure": false,
  "httpOnly": true,
  "session": true
};

browserWindow.webContents.session.cookies.set(cookie, function(error) {
  if (error) {
    Logger.log("Cookie set error: " + error);
  } else {
    Logger.log("Cookie correctly set up.");
  }
});

運用における課題

ユーザーの状況が分からずデバッグしづらいため、ログは必須。

monaca-libのデフォルト出力がconsoleのため、強制的に出力先を変更する

// Logger for Monaca Localkit
var fs = require('fs');
var process = require('process');
var _old_console = {
  debug: console.debug,
  log: console.log,
  error: console.error
};

function debug() {
  var line = formatDate(new Date()) + "\t" + "[DEBUG] " + sprintf(arguments);
  if (global.LOG_FILE_PATH) {
    writeFromBuffer();
    fs.appendFileSync(global.LOG_FILE_PATH , line + "\n");
  }
  else {
    appendToLogBuffer(line);
  }
  _old_console.log.apply(console, arguments);
}

// Override console to store in Localkit's Logger
console.debug = debug;
console.log = log;
console.error = err;

module.exports.debug = debug;
module.exports.log = log;
module.exports.err = err;

まとめ

特に大きな課題もなく

スムーズに導入&運用できています。

Thank you!

HTML5でモバイルアプリを開発できる

Monacaも是非触ってみてください

Contact me for any questions: masa@monaca.io

Slides available at: https://slides.com/masa-tanaka/emu-2017/

Electron Meetup Tokyo #1

By Masa Tanaka

Electron Meetup Tokyo #1

Using Electron in Monaca & Onsen UI team

  • 1,665