LoginSignup
17
18

More than 5 years have passed since last update.

React Tutorial Example (Electron)

Last updated at Posted at 2016-12-14

ReactRedux は 主に Webアプリケーション のライブラリなのですが
Electron を利用すると ディスクトップ アプリケーション を作成することができます。
前回 のアプリケーションを ディスクトップ アプリケーション にしましょう。

Learning

  • Electron で ディスクトップ アプリケーション を作成する。
  • Electron の メニューIPC(プロセス間通信) を利用する。

Environment

  • node: v6.9.2
  • npm: v4.0.5
  • yarn: v0.18.0

Comment Box Form

  • 完成される Source Code のファイルリストです。
    • main.jsserver.js の2ファイルが追加されます。
$ tree -a -I node_modules
.
├── .babelrc
├── app
│   ├── actions
│   │   └── index.js
│   ├── components
│   │   ├── Comment
│   │   │   └── index.js
│   │   ├── CommentBox
│   │   │   ├── index.js
│   │   │   └── style.css
│   │   ├── CommentForm
│   │   │   └── index.js
│   │   ├── CommentList
│   │   │   └── index.js
│   │   └── global.css
│   ├── containers
│   │   └── App
│   │       ├── index.js
│   │       └── style.css
│   ├── index.js
│   ├── reducers
│   │   └── index.js
│   └── store
│       └── index.js
├── test
│   └── app
│       ├── actions
│       │   └── index.test.js
│       ├── components
│       │   ├── Comment
│       │   │   └── index.test.js
│       │   └── CommentBox
│       │       └── index.test.js
│       └── reducers
│           └── index.test.js
├── index.html
├── main.js
├── package.json
├── server.js
├── webpack.config.js
└── yarn.lock

Let's hands-on

Setup application

  • git clone コマンドでアプリケーションをダウンロードします。
  • yarn コマンドで依存するモジュールをインストールします。
$ git clone https://github.com/ogom/react-comment-box-example.git
$ cd react-comment-box-example
$ git checkout jest
$ yarn

API ServerReact Tutorial Example (Express) をご利用ください。

Electron

  • Electron のモジュールをインストールします。
$ yarn add --dev electron

main.js

  • main.js ファイルに Electron の設定をします。
    • index.html ファイルを参照しています。
main.js
import { app, BrowserWindow } from 'electron'

let mainWindow

function createWindow () {
  mainWindow = new BrowserWindow({width: 800, height: 600})
  mainWindow.loadURL(`file://${__dirname}/index.html`)
  mainWindow.webContents.openDevTools()
  mainWindow.on('closed', () => {
    mainWindow = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})
  • package.json ファイルに mainscripts の設定します。
  • Electron でも babel を利用するので babel-registerrequire に設定します。
package.json
   "name": "react-comment-box-example",
   "version": "1.0.0",
   "private": true,
+  "main": "main.js",
   "scripts": {
-    "start": "webpack-dev-server -d --progress --colors",
+    "start": "electron --require babel-register .",
     "test": "jest",
     "test:watch": "npm test -- --watch"
   },
  • yarn start コマンドで Electron が起動します。
$ yarn start

electron_main

bundle.js ファイルがロードできないエラーが発生しています。 ( Failed to load resource: net::ERR_FILE_NOT_FOUND )
なので、bundle.js ファイルを参照できるように webpack の設定をしましょう。

server.js

  • server.js ファイルに webpack の設定をします。
    • webpack.config.js ファイルを参照しています。
server.js
import webpack from 'webpack'
import WebpackDevServer from 'webpack-dev-server'
import config from './webpack.config'

const options = {
  publicPath: config.output.publicPath,
  hot: true,
  inline: true,
  historyApiFallback: true,
  stats: {
    colors: true,
    hash: false,
    timings: true,
    chunks: false,
    chunkModules: false,
    modules: false
  }
}

const compiler = webpack(config)
const server = new WebpackDevServer(compiler, options)

server.listen(4000)
  • main.js ファイルに server.js をインポートします。
    • Electron の実行で webpack も実行されるようになります。
main.js
+import server from './server'
 import { app, BrowserWindow } from 'electron'

 let mainWindow
  • webpack.config.js ファイルに entry と output の設定をします。
webpack.config.js
 var webpack = require('webpack')
+var path = require('path')

 module.exports = {
-  entry: './app/index',
+  entry: [
+    'webpack-dev-server/client?http://localhost:4000/',
+    'webpack/hot/dev-server',
+    path.join(__dirname, './app/index')
+  ],
   output: {
+    path: path.join(__dirname, './dist'),
+    publicPath: 'http://localhost:4000/dist/',
     filename: 'bundle.js'
   },
  • index.html ファイルの bundle.js ファイルの参照先を変更します。
index.html
   </head>
   <body>
     <div id='content'></div>
-    <script src='/bundle.js'></script>
+    <script src='http://localhost:4000/dist/bundle.js'></script>
   </body>
 </html>

electron_server

bundle.js ファイルがロードできるので Comment Box が表示されました。
それに Hot Module Replacement の機能も使えるので開発が捗ります。

Menu

  • ディスクトップ アプリケーションのメニューは簡単に作成することができます。
  • Comment のメニューに Clear のサブメニューを作成します。
    • アプリケーションを終了する quit のメニューもあると開発が捗ります。
main.js
 import server from './server'
-import { app, BrowserWindow } from 'electron'
+import { app, BrowserWindow, Menu, dialog } from 'electron'

 let mainWindow

 function createWindow () {
   mainWindow = new BrowserWindow({width: 800, height: 600})
   mainWindow.loadURL(`file://${__dirname}/index.html`)
   mainWindow.webContents.openDevTools()
   mainWindow.on('closed', () => {
     mainWindow = null
   })
+
+  Menu.setApplicationMenu(
+    Menu.buildFromTemplate(
+      [
+        {
+          label: 'App',
+          submenu: [
+            {
+              role: 'quit'
+            }
+          ]
+        },
+        {
+          label: 'Comment',
+          submenu: [
+            {
+              label: 'Clear',
+              click(item, focusedWindow) {
+                dialog.showMessageBox({
+                  type: 'info',
+                  message: 'Message!',
+                  detail: 'message detail.',
+                  buttons: ['OK']
+                })
+              }
+            }
+          ]
+        }
+      ]
+    )
+  )
 }
  • メニューをクリックすると Message! のダイアログが表示されます。

electron_menu

IPC

  • Electron のメニューとブラウザを連携するには IPC を利用します。
  • IPCstore.dispatch(action) を設定すると Menu -> Redux -> React で連携が可能です。
    • さらに ipcRenderer.send('ipc::getState' store.getState())State をメニューに送信することもできます。
app/index.js
 import React from 'react'
 import ReactDOM from 'react-dom'
 import { Provider } from 'react-redux'
+import { ipcRenderer } from 'electron'

 import App from './containers/App'
 import configureStore from './store'

 const store = configureStore()

 ReactDOM.render(
   <Provider store={store}>
     <App />
   </Provider>,
   document.getElementById('content')
 )
+
+ipcRenderer.on('ipc::dispatch', (e, action) => {
+  store.dispatch(action)
+})
  • Actions はブラウザの app/actions/index.js ファイルをインポートすると DRY ですね。
main.js
+import * as Actions from './app/actions'
 import server from './server'
 import { app, BrowserWindow, Menu, dialog } from 'electron'
  • 先ほどのメニューに send('ipc::dispatch', Actions.showComments([])) を設定します。
main.js
               label: 'Clear',
               click(item, focusedWindow) {
                 dialog.showMessageBox({
                   type: 'info',
                   message: 'Message!',
                   detail: 'message detail.',
                   buttons: ['OK']
                 })
+                focusedWindow.webContents.send('ipc::dispatch', Actions.showComments([]))
               }
             }
           ]
  • webpack.config.js ファイルに target: 'electron-renderer' を設定します。
    • server.js ファイルに設定した項目は除去します。
webpack.config.js
-  devServer: {
-    hot: true,
-    port: 4000,
-    inline: true,
-    historyApiFallback: true
-  }
+  target: 'electron-renderer'
 }
  • これでメニューをクリックして Message! のダイアログの OK をクリックするとコメントがクリアされます。

electron_ipc

Congrats!


リリースをするためには electron-packager などでパッケージを作成するなど、いくつかの手順がありますが
Webアプリケーション のテクニックで ディスクトップ アプリケーション が作成できるのは便利ですね。
また、モバイル アプリケーションは React Native を利用すると作成できますよ。

React やその周辺のテクノロジーは変化が活発で、発展が楽しみなプロダクトです。
(React TutorialComment Box から Tic tac toe に変更されました :laughing:)

Enjoy React

17
18
0

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
17
18