78
74

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Electron+ReactなサンプルアプリをES6で作成する

Last updated at Posted at 2016-02-24

JavascriptはES6以前、ES6(ECMAScript2015)で書き方が違うので、Electronを紹介するサイトによって結構差異があります。サーバーサイドばかりでこのあたり詳しくなく、どっちが新しいの?と混乱しながらサンプルを作っていました。。。

また、Reactも頻繁に新しい機能が追加されるので、ReactDOMを使わずに書いてる古い形式も混在してたりカオスな状態です。なので現時点(2015/02/24)で、調べた限りで新しいスタイルで記述してみました

フロントエンド技術に詳しくないため、間違った記述等あればプルリク・コメントお待ちしています!

リポジトリ : https://github.com/kegamin/electron_test

アプリの機能

HelloWorld的な機能のみです.

  • Reactを使った画面表示
  • ボタンクリックを認識して、コンソールログにクリックカウントを出力
  • デバッグ用にデベロッパーツールを表示
  • babel-registerによるjsxの自動変換
  • ESLintによる検証

何故か動かない!という時に便利なデベロッパーツールを表示させたり、クリック制御ってどうやるの?的な事を知りたかったので入れています

使い方

cd repository_dir
clone https://github.com/kegamin/electron_test.git electron_test
cd electron_test
npm install
npm start

やらなかった点

最終的には以下も試したいが、レポジトリが複雑になると参考にしずらいので今回はやっていません

  • bowerを利用したフロントエンドの管理(bootstrapとか)
  • reduxを使ったMV*的な作り込み
  • react-route等のReactの色々な機能
  • gulpを利用した自動化

リポジトリ構成

.
├── .eslintrc         # ESLint設定ファイル
├── app               #
│   ├── index.html    # Electron メイン画面
│   ├── main.js       # Electronアプリ本体
│   ├── script        #
│   │   ├── click.jsx # ボタンクリック時の制御を記載したスクリプト
│   │   └── react.jsx # Reactの制御を記載したスクリプト
│   └── view          #
│       └── view.jsx  # ReactのViewファイル
├── index.js          # Electron起動時に呼ばれるファイル(package.jsonで指定)
└── package.json      # Node.js(Electron)設定ファイル

以下のような流れで処理が進んでいき、最終的に画面表示がされます.
(ちょっと語弊がありますが、ファイルの読む順番として理解してもらえれば)

package.json -> index.js -> main.js -> index.html -> (react.jsx + view.jsx)
                                           click! -> click.jsx

ES6/React用に考慮・変更した点

以下本アプリを作りにあたって、参考サイトから変更したりした点です.

  • require -> importに統一
  • varからconst/letに変更
  • babel-registerを利用したJSX->JS変換
  • 文字列中の変数をテンプレートリテラルに
  • ReactDOMを利用する
  • React.Componentを継承したクラス

require -> importに統一

色んなサイトで混在してたけど、ES6の形式であるimportに統一しています

参考:Babelで理解するEcmaScript6の import / export

const App = require('App');
const ipcMain = require('electron').ipcMain;

変更

import app from "app";
import {ipcMain} from "electron";

default export is not declared in imported moduleエラー

すべてimportに統一して実行しようとしたら、以下のコード部分でESLintでdefault export is not declared in imported moduleというエラーが発生してしまいました

import React from 'react';

これはreactモジュールで、export default class react {...}のような形でクラスが定義されてないというのが原因の模様。ReactがES6以前の形式で作られているからですね。

参考: ES6のimportでdefault export is not declared in moduleとなってしまう。

以下のような形に修正するとESLintのエラーは治ります

import * as React from 'react';

varからconst/letに変更

varでサンプル作ってる人も居ましたが、ES6ではconst/letを使う方がいいですね。varは怖い…

ES6のconstを使い倒すレシピ1 - 前提共有編 〜 JSおくのほそ道 #034

const myButton = document.getElementById("Click");

let clickCount = 0;

babel-registerを利用したJSX->JS変換

Reactで使用するjsxファイルは、最終的にjsファイルに変換してElectronが読める状態にする必要があります.Gulpを利用しているサイトもありましたが、babel-registerの方がカジュアルだったので今回採用しています.

以下のコードをindex.jsとindex.htmlに入れています.

require('babel-register');

ただしこのままで実行時にエラーになります。以下のようなエラーしか吐かないので、原因わかるまで苦労しました…

Uncaught Exception: SyntaxError: Unexpected token import....

これはpackage.jsonで以下の指定をしてES6及びReact形式をbabelに認識させる必要があります。

  "babel": {
    "sourceMaps": "inline",
    "presets": [
      "es2015",
      "react"
    ]
  },

文字列中の変数をテンプレートリテラルに

ES6で使えるようになった機能。rubyとかでやる"#{hoge}"と同じ形式が使えるようになったので合わせました。

参考:JavaScript の テンプレートリテラル を極める!

mainWindow.loadURL(rootPath + "/index.html");

変更

mainWindow.loadURL(`${rootPath}/index.html`);

ReactDOMを利用する

Reactは途中からDOMを制御する部分を分離し、ReactDOMを使うようになりました

import React from 'react';

React.render(
  <Main />,
  document.getElementById('content')
);

変更

import React from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
  <Main />,
  document.getElementById('content')
);

React.Componentを継承したクラスを使用する

ES6なのでReact.Componentを継承したクラスを作って利用できるようになりました。
以下はapp/view/view.jsxのソースコードですが、一番いろんなサイト参考にしたかも.

メソッド追加して色々やるのに、こっちの方が断然拡張性・保守性がいいですね.つか見やすい

import React from 'react';

export default class Main extends React.Component {
  constructor(props) {
    super(props);
    this.state = { message: "hello message from react" };
  }
  return (
    <div>{this.state.message}</div>
  );
}

ESLintを使う

Javascriptの静的検証ツールを入れて、逐次問題ないか確認しながらやりました。
特にIntelliJのような開発環境を使うのであれば必須ですね。ここもReact+Electronで使うにあたって情報が少なく結構困った…

参考:ESLint 最初の一歩

最低限?しか入れてないですが、おおよそ以下の設定でエラー無くなりました。ESLintのプラグイン等でもっと整理する必要はありますが、とりあえず一旦これで進めました。dotfilesのように黒魔術になるなこれは…

{
  "extends": "eslint:recommended",
  "parser": "babel-eslint",
  "ecmaFeatures" : {
    "jsx": true,
    "objectLiteralShorthandMethods" : true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "strict": 0,
    "indent": [ 2, 2],
    "semi": [2, "always"],
    "no-console": 0,
    "react/jsx-uses-vars": 1,
    "react/jsx-uses-react": 1
  },
  "env": {
    "es6": true,
    "node": true,
    "browser": true
  }
}

※※※ is defined but never used ワーニング

以下のコード部分で、Main部分はESLintでワーニングが発生します。
原因はno-unused-varsのチェックが働いているためで、宣言してるのに使ってないからというメッセージです。

import Main from '../view/view.jsx';

ReactDOM.render(
  <Main />,
  document.getElementById('content')
);

※追記
これはESLintのReactプラグインにより対処できました。

  "rules": {
    ...
    "react/jsx-uses-vars": 1,
    "react/jsx-uses-react": 1
  },

補足

IntelliJでElectron開発

一緒にIntelliJの設定でも苦労したので、qiitaに登録しています

IntelliJ(or WebStorm)でElectron開発環境を準備する

次にやること

以下を追加してもうちょっとらしいアプリにする!

  • redux
  • react-route
  • bower
  • bootstrap
  • gulp

参考サイト

もっとありましたが、一番参考にしたサイトは以下の通り

78
74
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
78
74

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?