Webpackerを使わずにRails,React,Typescriptアプリのベースを作る

# はじめに

仕事でReactを使うようになったので勉強がてら自分でReact,Typescript,Railsを使ったアプリを勉強していましたが

意外と最初の設定でつまずいたのでまとめます。

# Rails new

```
bundle init
#Gemfileにてrailsのコメントアウトを外す
bundle install --path vendor/bundle
bundle exec rails new .
bundle install
bundle update
```

# Webpackerを除く
Gemfileからwebpackerを除きます。

# React表示用のviewを作成

```
bundle exec rails g controller react-ui::home index
```


# tsconfigを作成
typescriptを使うためにはtsconfigを作成しなくてはいけない

railsのルートディレクトリにtsconfig.jsonファイルを作成して中身を以下の様にする

```json
{
  "compilerOptions": {
    "strictNullChecks": true,
    "noUnusedLocals": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "outDir": "./dist/",
    "sourceMap": true,
    "noImplicitAny": false,
    "lib": ["dom", "ES2017"],
    "module": "commonjs",
    "target": "es5",
    "jsx": "react",
    "baseUrl": ".",
    "paths": { "import-png": ["types/import-jpg"] },
    "typeRoots": ["types", "node_modules/@types"]
  }
}

```


# npm install webpack -D

webpackを使える様にする

```
npm install webpack -D
npm install webpack-cli -D
npm isntall webpack-dev-server -D
```


# webpack記載

railsのルートディレクトリにwebpack.config.jsファイルを作成する。

webpack.config.jsを以下の様に記載する

```
npm install typescript
npm install html-webpack-plugin -D
npm install webpack-manifest-plugin -D
npm install ts-loader style-loader css-loader file-loader url-loader -D
```

不要なエラーが発生するので　vendor/bundle/ruby/2.6.0/gems 以下のwebpackerのフォルダを削除します。

```javascript
const HtmlWebpackPlugin = require("html-webpack-plugin")
const ManifestPlugin = require("webpack-manifest-plugin")
const path = require('path');

module.exports = {
    mode: "development",
    entry: {
        home: `${__dirname}/app/webpack/entry/home`
    },

    output: {
        path: `${__dirname}/public/packs`,
        publicPath: `${__dirname}/app/webpack`,
        filename: "[name].js"
    },

    module: {
        rules: [{
                test: /\.(tsx|ts)$/,
                loader: "ts-loader"
            },
            {
                test: /\.css/,
                use: [
                    "style-loader",
                    {
                        loader: "css-loader",
                        options: { url: true }
                    }
                ]
            },
            {
                test: /\.(jpg|png)$/,
                loader: "file-loader?name=/public/[name].[ext]"
            },
            { test: /\.(eot|svg|woff|ttf|gif)$/, loader: "url-loader" }
        ]
    },

    watchOptions: {
        poll: 500
    },

    resolve: {
        extensions: [".ts", ".tsx", ".js"]
    },

    plugins: [
        new HtmlWebpackPlugin({
            template: `${__dirname}/app/webpack/index.html`,
            filename: "index.html"
        }),
        new ManifestPlugin({
            fileName: "manifest.json",
            publicPath: "/packs/",
            writeToFileEmit: true
        })
    ],
    devServer: {
        publicPath: "/packs/",
        historyApiFallback: true,
        inline: true,
        hot: true,
        port: 3035,
        contentBase: "/packs/"
    }
};
```

app/webpack以下にindex.htmlを作成して以下の様に記載します。

```html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

</body>

</html>
```



# package.jsonにscriptを追加

package.jsonが作成されているはずなのでそのファイルを開きscriptを以下の様に設定する

```javascript
"scripts": {
    "start": "webpack-dev-server --hot --inline --contentbase public/packs/  --mode development"
},
```

これで npm start をコマンドを打ったときにwebpack-dev-serverが起動してくれる

# reactを使えるようにする

```
npm install react -D
npm install react-dom -D
```

webpack.config.jsのentryからjavascriptを読み込むので

```
${__dirname}/app/webpack/entry/home
```

のフォルダにindex.tsxを作成します。

そして中身を以下の様にします。

```tsx
import * as React from "react";
import { render } from "react-dom";

render(<div>Home</div>, document.getElementById("root"));
```


# Rails側で読み込むロジック追加

webpackerを使わないのでjavascript_pack_tagは使えません。

ですので

react_ui/home/index.html.erbを以下の様にします。

```erb
<div id="root"></div>

<% if Rails.env == "development" %>
<script src="http://localhost:3035/packs/home.js"></script>
<% else %>
<script src="/packs/home.js"></script>
<% end %>
```

config/routes.rbに

```
root to: "react_ui/home#index"
```

を追加

layouts/application.html.erbの

```
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

を削除します。

# 動作確認

```
bundle exec rails s
npm start
```

を実行してlocalhost:3000にアクセスすれはHomeが表示されるはずです。

あとは好きにreactを書いていけばOKです。