Electron + Reactの環境作成

# 下準備
```bash:下準備
npm init

# なんでもいいけど、エントリーポイントはmain.jsにしておく
entry point: (index.js) main.js
```

```bash:必要なモジュールのインストール
npm install \
electron-reload \
material-ui \
ramda \
react \
react-dom

# electron-reload　・・・　開発時のオートリロード用
# material-ui ・・・ MaterialUI
# ramda ・・・　個人的に使いやすいのでRamda.js

npm install -D \
electron \
electron-packager \
webpack \
webpack-cli \
webpack-node-externals \
babel-loader \
html-loader \
html-webpack-plugin \
babel-cli \
babel-preset-env \
babel-preset-react \
babel-preset-stage-1 \
babel-register

# electron-packager　・・・　Electronをパッケージするのに使う
# webpack-node-externals　・・・　node_modulesをwebpackの対象から外す
# babel-preset-stage-1　・・・　MaterialUIで必要だったはず
# babel-register　・・・　webpack.configだってES6で書きたい
```

↓.babelrcとwebpack.configはコピペで。

```json:.babelrc
{
    "presets": [
        ["react"],
        ["stage-1"],
        [
            "env",
            {
                "targets": "electron"
            }
        ]
    ]
}
```

```js:webpack.config.babel.js
import HtmlWebpackPlugin from 'html-webpack-plugin';
import nodeExternals from 'webpack-node-externals';
import webpack from 'webpack';

export default {
    mode: 'development',
    target: 'electron-renderer',  // レンダラープロセスをメインターゲットに
    externals: [nodeExternals()], // node_modulesは依存関係から外すよ
    entry: './src/js/index.js',
    devtool: 'inline-source-map',
    module: {
        rules: [
            {
                test: /\.(html)$/,
                use: {
                    loader: 'html-loader'
                }
            },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            'babel-preset-react',
                            'babel-preset-env'
                        ]
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/html/index.html'
        }),
        new webpack.ProvidePlugin({
            $: 'jquery'
        })
    ]
};
```

# ブラウザプロセス
以下をコピペ。

※内容は、
 <公式の記載>
 + \<electron_reload>
 + <パッケージ後のメニュー>
 + <ロードするhtmlの変更>

```js:main.js
const {app, BrowserWindow, Menu} = require('electron');
require('electron-reload')(__dirname);
const path = require('path');
const url = require('url');

const template = [
    {
        label: 'Edit',
        submenu: [
            {role: 'undo'},
            {role: 'redo'},
            {type: 'separator'},
            {role: 'cut'},
            {role: 'copy'},
            {role: 'paste'},
            {role: 'pasteandmatchstyle'},
            {role: 'delete'},
            {role: 'selectall'}
        ]
    },
    {
        label: 'View',
        submenu: [
            {role: 'reload'},
            {role: 'forcereload'},
            {role: 'toggledevtools'},
            {type: 'separator'},
            {role: 'resetzoom'},
            {role: 'zoomin'},
            {role: 'zoomout'},
            {type: 'separator'},
            {role: 'togglefullscreen'}
        ]
    },
    {
        role: 'window',
        submenu: [
            {role: 'minimize'},
            {role: 'close'}
        ]
    },
    {
        role: 'help',
        submenu: [
            {
                label: 'Learn More',
                click () { require('electron').shell.openExternal('https://electronjs.org'); }
            }
        ]
    }
];
  
if (process.platform === 'darwin') {
    template.unshift({
        label: app.getName(),
        submenu: [
            {role: 'about'},
            {type: 'separator'},
            {role: 'services', submenu: []},
            {type: 'separator'},
            {role: 'hide'},
            {role: 'hideothers'},
            {role: 'unhide'},
            {type: 'separator'},
            {role: 'quit'}
        ],
    });

    // Edit menu
    template[1].submenu.push(
        {type: 'separator'},
        {
            label: 'Speech',
            submenu: [
                {role: 'startspeaking'},
                {role: 'stopspeaking'}
            ]
        }
    );

    // Window menu
    template[3].submenu = [
        {role: 'close'},
        {role: 'minimize'},
        {role: 'zoom'},
        {type: 'separator'},
        {role: 'front'}
    ];
}

let win;

function createWindow () {
    win = new BrowserWindow({width: 800, height: 600});
  
    win.loadURL(url.format({
        // ここのhtmlをdistのhtmlにする
        pathname: path.join(__dirname, 'dist/index.html'),
        protocol: 'file:',
        slashes: true
    }));

    //win.webContents.openDevTools();

    win.on('closed', () => {
        win = null;
    });

    const menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
}

app.on('ready', createWindow);

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

app.on('activate', () => {
    if (win === null) {
        createWindow();
    }
});
```

```js:webpack.config.babel.js

```

# レンダラープロセス
## 前準備
```bash
mkdir -p ./src/html ./src/js ./src/jsx dist
```

## HTML
index.htmlはReactの入り口だけ作ってあげる。
MaterialUI用にRobotoの設定もここで。

```html:src/html/index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">
    <style>
      * {font-family: 'Open Sans', sans-serif;}
    </style>
    <title>タイトル</title>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>
```

## JS
ReactDOM.render。

これもほぼコピペでよく、あとはコンポーネントを増やして、追記していけば良い。

MuiThemeProviderをここで記載して、どこでもMaterialUIを使えるようにしておく。

```js:src/js/index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

class App extends Component {
  render() {
    return (
        <MuiThemeProvider>
            hoge
        </MuiThemeProvider>
    );
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
```

# Electron起動
```bash
$(npm bin)/webpack
$(npm bin)/electron .
```

# 一応コンポーネントも増やしてみる
```js:src/jsx/sub.jsx
import React, { Component } from 'react';

export default class Sub extends Component {
    render() {
        return (
            <div>
               Sub
            </div>
        );
    }
}
```

index.jsでは、Subをimportする。

```src/js/index.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';

import Sub from '../jsx/sub.jsx';

class App extends Component {
  render() {
    return (
        <MuiThemeProvider>
            hoge
            <Sub />
        </MuiThemeProvider>
    );
  }
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
);
```