django manage SPA
アプリを作成する
djangoのstartappの代わりに、create-react-appでアプリを作成します。
nodeをインストール後、npm install -g create-react-appを実行することで使用できます。
django-admin startproject my-projectcd my-projectcreate-react-app my-react-appcd my-react-app
ルーティングの設定
urls.pyを次のように設定させます
from django.conf import settings
...
url_patterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
submodules = ["my-react-app"]
for name in submodules:
route = name if name != "core" else ""
temp = 'static/%s/index.html' % name
view = TemplateView.as_view(template_name=temp)
urlpatterns += [re_path(route, view, name=name)]
staticのディレクトリを設定する
ビルド結果のフォルダを次のようにsettings.pyで指定させます。
submodules = ["my-react-app"]
STATICFILES_DIRS = []
for s in submodules:
STATICFILES_DIRS += [
os.path.join(BASE_DIR, "%s/build/%s/static" % (s, s)),
os.path.join(BASE_DIR, "%s/build" % (s))
]
ここで二重に設定 させたのは、複数のReactアプリが存在する場合、 static内のファイルを同じ場所で管理できるようにするためです。 このとき、staticディレクトリが重複してしまうため、 ignoreを指定してファイルを集める必要があります。
CRAのbuild先を上書きする
npm install -D react-app-rewiredを実行後、config-overrides.jsを次のようにします
const fs = require('fs');
const path = require('path');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
paths: (paths, env) => {
const basename = path.basename(__dirname)
paths.appBuild = resolveApp(`build/${basename}`);
return paths;
}
}
npx react-app-rewired buildpython manage.py collectstatic --ignore=static/
Rest APIを作る
先ほど作成したmy-react-appでAPIを使用します。
python manage.py startapp my-react-appを実行すると、
ディレクトリ内にPythonファイルが作成されます。
settings.pyを編集します。
INSTALLED_APPS += ['my-react-app']
my-project/urls.pyに次のように追加します
from django.conf import settings
# ...
url_patterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
submodules = ["my-react-app"]
for name in submodules:
route = name if name != "core" else ""
temp = 'static/%s/index.html' % name
view = TemplateView.as_view(template_name=temp)
urlpatterns += [re_path(route, view, name=name)]
開発用にサーバーを立てるコマンドを作成する
DjangoとNode.jsのサーバ ーを同時に用意する際のコマンドを用意しておきます。
my-react-app/management
│ __init__.py
│
└─commands
│ npm_start_runserver.py
└─ __init__.py
npm_start_runserver.pyを次のように編集します。
import sys
import subprocess
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = "npm start and runserver"
def handle(self, *args, **options):
proc = subprocess.Popen(["npm", "start"], shell=True, cwd='./note')
cmds = [sys.executable, sys.argv[0], 'runserver', '0.0.0.0:8000']
subprocess.run(cmds, shell=True, cwd=".")
proc.close()
python manage.py npm_start_runserver で立ち上げることができます。