DjangoのページをReactで作る - Webpack4

Djangoは認証やセッションなどが簡単に実装できて便利です。DjangoとReactでWebアプリを構築するときに、ReactでSPAアプリを作れば、Djangoのこのような利点を利用するのが難しくなります。SPAでの認証にはJWTなどを使うのが一般的で少し複雑になります。結論的に言えば、基本的なところはDjangoに全て任せるとして、特定のDjango のページ（Template）をリッチにするためだけに使うのが現実的だと思われます。本記事はこのような考えを実装するための最小限の知識をまとめたものです。以下の記事を参考にしつつ自分なりに再構築しました。


[Tutorial: Django REST with React (Django 2.0 and a sprinkle of testing)](https://www.valentinog.com/blog/drf/)
[Webpack 4 Tutorial: from 0 Conf to Production Mode](https://www.valentinog.com/blog/webpack/)


**【追記 2019/07/28】**DjangoとReactをまずは独立した環境で開発し、最後に結合する方法を試した記事です。==> [「Reactアプリから Django Rest API を叩いてみる - Qiita」](https://qiita.com/sand/items/80a67da0a44b042f0bc3)


#１．ReactプロジェクトとDjangoプロジェクトのディレクトリ構成

まずwebpack4（名前は任意）ディレクトリを作成しトップディレクトリとします。
webpack4ディレクトリには**Reactアプリ構築環境**を... つまりnpmプロジェクトやwebpack、babelの環境を構築します。またdjangoreactwebpack4という**Djangoプロジェクト**を作成します。

つまりトップディレクトリには以下の２つのファイル／ディレクトリが置かれます。

* Reactアプリの環境
* Djangoプロジェクト


treeで表示すると以下のようなディレクトリ構成になります。

```:webpack4ディレクトリ
├── bin
├── djangoreactwebpack4(Djangoプロジェクト)
├── include
├── lib
├── lib64 -> lib
├── node_modules
├── package-lock.json
├── package.json
├── pyvenv.cfg
└── webpack.config.js
```


```:djangoreactwebpack4(Djangoプロジェクト)
├── db.sqlite3
├── djangoreactwebpack4
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-36.pyc
│   │   ├── settings.cpython-36.pyc
│   │   ├── urls.cpython-36.pyc
│   │   └── wsgi.cpython-36.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── frontend
│   ├── __pycache__
│   │   ├── urls.cpython-36.pyc
│   │   └── views.cpython-36.pyc
│   ├── src
│   │   ├── components
│   │   └── index.js
│   ├── static
│   │   └── frontend ( ── main.js)
│   ├── templates
│   │   └── frontend
│   ├── urls.py
│   └── views.py
└── manage.py
```



#２．Djangoプロジェクト

それではPythonの環境を作ります。


```
python -m venv webpack4
source webpack4/bin/activate
```

作業領域を作成しdjangoをインストールします。

```
cd webpack4  # 作業領域のトップに移行
pip freeze   # インストール済みは空であることを確認
pip install django  # Djangoをインストール
```


Djangoプロジェクトを作成します

```
django-admin startproject djangoreactwebpack4
cd djangoreactwebpack4/
```

私の環境は、DjangoはRemoteサーバに構築していますので、サーバのドメイン名を入力してアクセスを許可します。


```python:djangoreactwebpack4/settings.py
---
ALLOWED_HOSTS = ["www.mypress.jp"]
---
```

DBを初期化します。

```
python manage.py migrate
```

ここまででDjangoのアプリを立ち上げます。


```
python manage.py runserver 0:8080
```

http://www.mypress.jp:8080/ で、以下のような画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/6ed87aa4-91c5-1f20-8b88-19162d7c30c1.png)





#３．Django templates と React components


frontend という名前で Django Appを作成し、この template に React App を貼り付けます。

それではfrontendを作成します。

```
django-admin startapp frontend
```

frontendディレクトリ配下を以下のように使用します。

* **frontend/src**ディレクトリにReact Appのソースを作ります。
* **frontend/templates**はDjangoのテンプレートディレクトリです。
* **frontend/static**はDjangoの静的ファイルのディレクトリです。


```
mkdir -p ./frontend/src/components
mkdir -p ./frontend/{static,templates}/frontend
```


INSTALLED_APPSにfrontendを追加します。


```python:djangoreactwebpack4/settings.py
---
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'frontend',  # 追加
]
---
```



DjangoのURLとviewsを定義します。


```python:djangoreactwebpack4/urls.py
from django.urls import path, include
urlpatterns = [
    path('', include('frontend.urls')),
]
```


```python:frontend/urls.py.
from django.urls import path
from . import views
urlpatterns = [
    path('', views.index ),
]
```




```python:frontend/views.py
from django.shortcuts import render
def index(request):
    return render(request, 'frontend/index.html')
```


以上のURLとviewsの定義で、http://www.mypress.jp:8080/ のアクセスで、以下のindex.htmlが呼び出されることになります。



```html:frontend/templates/frontend/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">
  <title>Django DRF - React : Quickstart - Valentino G. - www.valentinog.com</title>
</head>
<body>
  <section class="section">
    <div class="container">
          <div id="app" class="columns"><!-- React --></div>
    </div>
  </section>
</body>
{% load static %}
<script src="{% static "frontend/main.js" %}"></script>
</html>
```

{% static %} テンプレートタグは、静的ファイルの完全 URL を生成します。{% static "frontend/main.js" %} はmain.jsを指すURLです。後で説明しますが、webpack (babel)がindex.jsをコンパイルしてmain.jsをstaticファイルとして生成します。それをこのindex.htmlが読み込んで、id="app"にマウントされることになるわけです。**ここがDjangoとReactの接点になります。**




```python:frontend/src/components/App.js
import React from "react";
import ReactDOM from "react-dom";
const App = () => {
  return (
    <div>
      <p>React here!</p>
    </div>
  );
};
export default App;
ReactDOM.render(<App />, document.getElementById("app"));
```


```python:frontend/src/index.js
import App from "./components/App";
```


#４．Reactプロジェクト

最後にReactプロジェクトの環境を構築していきます。

webpack4ディレクトリ直下にて作業を行います。


```
npm init -y
npm i webpack --save-dev
npm i webpack-cli --save-dev
```

npm run build や npm run dev でReactのindex.jsをコンパイルしてmain.jsを吐き出すようにします。index.jsとmain.jsのディレクトリに注意してください。


```:package.json
---
  "scripts": {
    "dev": "webpack --mode development ./djangoreactwebpack4/frontend/src/index.js --output ./djangoreactwebpack4/frontend/static/frontend/main.js",
    "build": "webpack --mode production ./djangoreactwebpack4/frontend/src/index.js --output ./djangoreactwebpack4/frontend/static/frontend/main.js"
  },
---
```

npm run devは開発時に使います。吐き出されるmain.jsがデバッグに備えて見やすいものになっています。npm run buildは本番deploy時に使います。main.jsは圧縮された形です。


必要なパッケージをインストールします。

```
npm i @babel/core babel-loader @babel/preset-env @babel/preset-react babel-plugin-transform-class-properties --save-dev
npm i react react-dom prop-types --save-dev
```

babelの設定です。

```:.babelrc
{
    "presets": [
        "@babel/preset-env", "@babel/preset-react"
    ],
    "plugins": [
        "transform-class-properties"
    ]
}
```


webapackの設定です。

```:webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};
```


Reactアプリをコンパイルします。

```
npm run build
```

それではDjangoプロジェクトを起動しましょう。

```
cd djangoreactwebpack4
python manage.py runserver 0:8080
```


http://www.mypress.jp:8080/ で、以下のような画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61915/edde5a95-03cd-41a7-ca2c-760f0c598f2a.png)



以上です。