webpackを使って既存のwebフレームワークにReactを動かしてみた


# Background
CDNのみでReactを動かそうとしたのですが、CDNが非対応のライブラリが多そうと思いました。それで、webpackを使ってひとつのjsファイルを出力してみようと思います。

# Motivation
WordCloudを表示させたい!!
[react-tagcloud](https://github.com/madox2/react-tagcloud)のパッケージを使います。
![スクリーンショット 2022-07-03 10.41.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/5dc87fcf-34a2-5d80-7d47-5e829faf1279.png)

Demoページは[ここ](https://madox2.github.io/react-tagcloud/)。
慣れてくれば他のvisualize用のライブラリを使ってみようと思ってます。

# Method
1. プロジェクトを作成
1. 必要なパッケージをインストール
1. webpackの設定
1.  `package.json` にwebpackの実行コマンドを追加
1.  出力先フォルダを作成

# Compose Environment

##### プロジェクトを作成
```sh
mkdir frontend
cd frontend
```

##### 必要なパッケージをインストール

###### `package.json` を作成 
```sh
touch package.json
```

```package.json
{
  "name": "react-editor",
  "version": "1.0.0",
  "scripts": {
    "start": "echo 'Hello! package.json'"
  }
}
```

`npm init` で `package.json` を作成できるみたいですが。 必要最低限の内容として `name` `version` `scripts` だけで良いみたいです。

この状態で `package.json` 直下で `npm start` とコマンドすると `Hello! package.json` が出力されると思います。

```sh
$ npm start

> react-editor@1.0.0 start
> echo 'Hello! package.json'

Hello! package.json
```

##### インストール

追加するのは `webpack` `react` `babel`の3つです。
あとはお好みでreactのライブラリをインストールします。

```sh
npm install webpack
npm install @babel/core @babel/preset-env @babel/preset-react babel-loader
npm install react react-dom
npm install react-tagcloud
```

##### webpackの設定

webpackの設定には `webpack.config.js` が必要です。 `touch` で空のファイルを作成します。

```sh
touch webpack.config.js
```

```webpack.config.js

const path = require('path')

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dst'),
    filename: 'react_index.js',
  },
  resolve: {
    extensions: ['.js', '.ts', '.jsx']
  },
  module: {
    rules: [{
      test: /\.(js|mjs|jsx)$/,
      exclude: /node_modules/,
      use: [
        {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              '@babel/preset-react',
            ]
          }
        }
      ]
    }]
  }
}
```

`entry` で最初に読み込むファイルを設定し、 `output`で出力先のフォルダパスとファイル名を設定します。 `resolve` はここに拡張子を書いておくと実行読み込み時にimport文を簡略化することができます。例えば `./components/WordCloud.jsx`をインポートしたい場合、 `resolve` に `extensions: ['.jsx']` と
設定しておくと `import {SimpleCloud} from './components/WordCloud.jsx'` と書かずに `.jsx`を省略して `import {SimpleCloud} from './components/WordCloud'` と書くことができます。 `module.rules` は 最新版のJavaScriptの記述に変換するためにBabelLoaderを設定しています。[React の環境構築（セットアップ）](https://www.webdesignleaves.com/pr/jquery/react_basic_01.html) を丸パクリして設定してます:sweat_smile:。 ([webpackでbabel-loaderを使う方法を紹介](https://solomaker.club/how-to-use-babel-loader-in-webpack/)を参照)

#####  `package.json` にwebpackの実行コマンドを追加

`package.json` の `scripts` に `build` のコマンドを追加します。

```package.json
{
  ...
  "scripts": {
    "start": "echo 'Hello! package.json'",
    "build": "webpack --mode=production"
  }
  ...
}
```



##### 出力先フォルダを作成

出力先のフォルダを作成します。

```sh
mkdir dst
```

これで `npm run build` すれば `dst` フォルダにjsファイルが出力できると思います。

# Folder Structure
フォルダ構成は下記の通りとなります。

```
frontend（プロジェクトのディレクトリ）
├── dst  //出力先（output）フォルダ
│   └── react_index.js
└── src
    ├── components
    │       └── WordCloud.jsx
    ├── App.js
    └── index.js  //エントリポイント
```

# Development

詳しいReactの開発については割愛します。 コードのみを掲載します。

```index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

let dom = document.querySelector("#root");
ReactDOM.render(<App />, dom);

```

```App.js
import React from 'react'
import {SimpleCloud} from './components/WordCloud.jsx'

const App = () => {
  return (
    <>
      <div className="App">
        <h1>
          Hello, React!!!
        </h1>
      </div>
      <div>
        <SimpleCloud />
      </div>
    </>
  )
}

export default App;
```

```components/WordCloud.jsx
import React from 'react'
import { TagCloud } from 'react-tagcloud'

const data = [
  { value: 'JavaScript', count: 38 },
  { value: 'React', count: 30 },
  { value: 'Nodejs', count: 28 },
  { value: 'Express.js', count: 25 },
  { value: 'HTML5', count: 33 },
  { value: 'MongoDB', count: 18 },
  { value: 'CSS3', count: 20 },
  { value: 'Django', count: 40 },
  { value: 'Python', count: 55 },
]

const SimpleCloud = () => (
  <TagCloud
    minSize={12}
    maxSize={35}
    tags={data}
    onClick={tag => alert(`'${tag.value}' was selected!`)}
  />
)

export {SimpleCloud};

```

# Launcher

プロジェクト直下で下記のコマンドで実行します。成功すれば `dst`フォルダにjsファイルが出力されます。

```sh
$ npm run build

$ ls dst
react_index.js
```

# Preview

あとは表示したいページに`script`タグを追加すれば完了です。
Djangoベースで書いています。出力したjsファイルはどこかに格納してください。
`<div id="root"></div>` はないと表示されません。

```index.html
...
<div id="root"></div>
<script type="text/javascript" src="{% static 'js/react_frontend/react_index.js' %}"></script>
...
```

# Consequence

![スクリーンショット 2022-07-03 12.55.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/288206/6d56aa1e-4de7-2468-f809-11cfd57cc188.png)


# PostScript
忘れそうなので書いてみたった。
グラフ表示ライブラリは何を使えばいいか悩む。

# Reference
- [CDNオンリーでReactを動かしてみた](https://qiita.com/satsukiya/items/c079537852bea01f0b50)
- [React × TypeScript で手を動かながら学ぶ！モダンなフロントエンド開発入門 : npm でプロジェクトを作成する](https://www.techpit.jp/courses/111/curriculums/114/sections/855/parts/3150)
- [React × TypeScript で手を動かながら学ぶ！モダンなフロントエンド開発入門 : webpack を導入してビルドができるようにする](https://www.techpit.jp/courses/111/curriculums/114/sections/855/parts/3151)
- [react-tagcloud](https://github.com/madox2/react-tagcloud)
- [脱 create-react-app! webpackでReact ×TypeScrip開発環境構築からHello World!まで](https://zenn.dev/hrkmtsmt/articles/93653309e2a13d)
- [React の環境構築（セットアップ）](https://www.webdesignleaves.com/pr/jquery/react_basic_01.html)
- [webpack ＋ TypeScript／Babel（JavaScript）の環境でReactを導入する](https://designsupply-web.com/media/programming/6902/)
- [【React】Webpack を使って実行可能htmlを作成する](https://noitalog.tokyo/react-webpack/)
- [React & Webpack](https://js.studio-kingdom.com/typescript/tutorials/react_and_webpack)
- [React+Typescript+Webpackの環境構築](https://www.appliot.co.jp/blog/reacttypescriptwebpack%E3%81%AE%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89/)
- [webpackでbabel-loaderを使う方法を紹介](https://solomaker.club/how-to-use-babel-loader-in-webpack/)