11
9

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 3 years have passed since last update.

ReactをBabelとWebpackしてElectron

Last updated at Posted at 2020-10-29

もしかしてElectronでデスクトップアプリを開発したくて、ReactでUIを作りたいと思ってませんか?
この記事を見ているということはそういうことですね。

では、ReactをBabelとWebpackしてElectronしましょう:hugging:

準備

これからやることは至ってシンプルです。

React (のコード)を Babel (でトランスパイル)と Webpack (でひとつのjsに変換)して Electron (上で動か)します。

正確にはHello, world!を表示させるReactのコードをElectron上で動かすところまでの基礎チュートリアルです。

まずは必要な環境の構築から行っていきましょう。

Node.jsとnpmのインストール

大半の人が終わっているでしょう。Node.jsに全く触れずにこの記事に来ているあなたはとても勇敢です。
Node.jsのインストール

console
$ node --version
v14.5.0

Node.jsインストールの際には付属でパッケージマネージャのnpmもインストールされているはずです。
npmは最初にアップデートしましょう。

console
$ npm i -g npm
+ npm@6.14.8
updated 1 package in 4.852s

完ぺきですね:relieved:

パッケージ立ち上げと必要パッケージインストール

Node.jsの新規パッケージ立ち上げはinitサブコマンドです。
パッケージ用のディレクトリを作って、カレントディレクトリをその中に移してからコマンドを打ちます。

console
$ npm init

いくつか質問されますが、これらは後でpackage.jsonで変更が可能なので全てEnterを押して進めましょう。

開発に必要なパッケージをnpmで導入しましょう。

console
$ npm i -S react react-dom
$ npm i -D electron webpack webpack-cli webpack-loader @babel/core @babel/plugin-transform-react-jsx @babel/plugin-transform-react-jsx-self babel-loader css-loader style-loader

package.jsonの編集

自動生成されたpackage.jsonファイルを編集します。

今回は

  1. src/main.jsを最初に呼び出されるスクリプトに指定する
  2. scriptsbuildstartを追加

の2点を変更します。
1はmainの値の書換、2はscriptsの下に追記しましょう。

以下は2020/10/30時点でのバージョンです。

package.json
{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "src/main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "electron ."
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.3",
    "@babel/plugin-transform-react-jsx": "^7.12.1",
    "@babel/plugin-transform-react-jsx-self": "^7.12.1",
    "babel-loader": "^8.1.0",
    "css-loader": "^5.0.0",
    "electron": "^10.1.5",
    "style-loader": "^2.0.0",
    "webpack": "^5.3.2",
    "webpack-cli": "^4.1.0",
    "webpack-loader": "0.0.1"
  }
}

準備完了!

webpackの設定

webpackの設定にはwebpack.config.jsファイルを用います。パッケージのディレクトリ直下にファイルを作り、以下のように編集しましょう。
この設定を簡単に説明すると、

  1. src/app.jsファイルを基点にインポートされているファイルをまとめる
  2. jsjsxが拡張子のファイルはBabelでトランスポートするbabel-loaderでまとめる
  3. cssが拡張子のファイルはstyle-loadercss-loaderでまとめる

となっています。

webpack.config.js
module.exports = {
  mode: 'development',
  entry: './src/app.js',
  output: {
    path: `${__dirname}/src/dist`,
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.js[x]?$/,
      exclude: /node_modules/,
      use: 'babel-loader'
    }, {
      test: /\.css$/,
      use: ['style-loader', {loader: 'css-loader'}],
    }]
  },
  target: 'node',
  resolve: {
    extensions: [".js", ".jsx"]
  },
}

Babelの設定

このままではBabelがReact構文のjsを読みこめません。
そこでBabelがReact構文のjsをトランスパイルできるようにパッケージのディレクトリ直下にbabel.config.jsを設置してプラグインを指定します。

babel.config.js
module.exports = {
  "plugins": ["@babel/transform-react-jsx"]
}

Reactのファイルを設置

事前設定が一通り終わったのでアプリの中身のコーディングに移りましょう。
srcディレクトリを作り、app.jsを以下の内容で設置します。

src/app.js
import React from 'react'
import ReactDOM, { render } from 'react-dom'

const App = () => {
  return (
    <div>
      <h1>
        Hello, world!
      </h1>
    </div>
  )
}

render(<App />,document.getElementById('app'))

Electronのファイルを設置

Electronのメインプロセスのファイルをsrcディレクトリ下に以下の内容で設置しましょう。
これはpackage.jsonmainに指定した 最初に呼び出されるスクリプト に当たります。
内容はほぼ公式Quick Start Guideのままです。
ただしwin.loadFile()の引数に'src/index.html'を与えるよう書き換えましょう。

src/main.js
const { app, BrowserWindow } = require('electron')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  win.loadFile('src/index.html')
  // win.webContents.openDevTools() // 開発者ツールを非表示にするためコメントアウトしています!

}

app.whenReady().then(createWindow)

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

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

続いてレンダラープロセスを担うindex.htmlファイルを同様に以下の内容で設置します。

レンダラーのhtmlは最小限の構成ですが、重要なのはReactで使うidappdivタグと、Webpackされて出力されるsrc/distディレクトリ下のbundle.jsscriptタグで読み込む点です。

src/index.html
<html>
  <head>
    <meta charset="utf-8">
    <title>DemoApp</title>
  </head>
  <body>
    <div id='app'></div>
    <script src='./dist/bundle.js'></script>
  </body>
</html>

ディレクトリ構造おさらい

ここまででのディレクトリ構造は以下のようになります。

tree
demo (package name)
├── src
│   ├── dist
│   │   └── bundle.js
│   ├── app.js
│   ├── index.html
│   └── main.js
├── babel.config.js
├── package-lock.json
├── package.json
└── webpack.config.js

(node_modulesディレクトリは記載していません。)

ReactをBabelとWebpackしてElectron

タイトル回収です。ではやっていきましょう。

ReactをBabelとWebpackしてElectron

console
$ npm run build && npm run start

demoapp.png

みなさん大好きなHello, world!が出ました、やったね:hugging:

あとは思うがままに、コンポーネントを増やしたりしてアプリのUIをカスタムしましょう!

最後にお願い

この記事を書いた私は趣味でしかプログラミングをしたことがない学生です。
このチュートリアルで足りない点はまだ多いと思いますので、経験豊富な方々は是非ご意見をお寄せください
この記事がより良いElectron + Reactのチュートリアル記事になれば、と思っています。

11
9
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
11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?