如何在Django中更好的使用React

Django是一个非常成熟稳定的web开发框架, 可以快速搭建产品逻辑, 但是当页面非常复杂, 使用基础的javascript无法满足需要时, 就会考虑使用React, Vue等前端开发框架

如果只是使用CreateReactApp, 或者Next.js时, 开发体验会很好, 但是可能部署起来会比较麻烦, 一般只能完全做成前后端分离的两套代码,

前后端分离的代码自然是很好, 但是在一些情况下, 会增加开发成本

所以能不能像写django模板那样写react代码? 使用后端框架强大稳定的路由处理能力, 以及基础的数据渲染能力, 再加上前端框架的强大的页面交互能力

本文将提供一种可行的参考方案

1. 原理介绍

使用django自定义模板标签, 在HTML中渲染Vite的代码

{% load react_tags %}

{% react_static paper %}

渲染后的结果为

<script type="module">
import RefreshRuntime from "http://localhost:3000/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
<script type="module" src="http://localhost:3000/@vite/client"></script>
<script type="module" src="http://localhost:3000/backend/lexical/components/paper.jsx"></script>

如此以来, 便可在修改paper.jsx文件时, 页面实现实时刷新, 达到create-react-app的开发效果 部署的时候, 配置Vite打包路径在static目录下, 打包后会生成manifest.json, 里面包含了打包后的文件路径信息

在生产环境下, 使用Python读取manifest.json, 并转换为最终的静态文件引入HTML模板

源码地址: https://github.com/ChanMo/django-react

2. 什么是Vite

Vite(法语意为 "快速的",发音 /vit/,发音同 "veet")是一种新型前端构建工具, 能够显著提升前端开发体验。它主要由两部分组成:一个开发服务器, 它基于 原生 ES 模块 提供了 丰富的内建功能,如速度快到惊人的 模块热更新(HMR)。 一套构建指令,它使用 Rollup 打包你的代码,并且它是预配置的, 可输出用于生产环境的高度优化过的静态资源。Vite 意在提供开箱即用的配置, 同时它的 插件 API 和 JavaScript API 带来了高度的可扩展性,并有完整的类型支持。

3. 开始使用

3.1. 下载django-react

$ git clone https://github.com/ChanMo/django-react react

3.2. Update Settings.py

INSTALLED_APPS = [
...
'react',
...
]  

3.3. Setup Vite

Create file package.json

{
  "name": "django-react",
  "version": "1.0.0",
  "description": "use react.js in django templates",
  "main": "index.js",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "ChanMo",
  "license": "ISC",
  "devDependencies": {
    "@vitejs/plugin-react": "^1.2.0",
    "vite": "^2.8.6"
  },
  "dependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}  

Create file vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  build: {
    outDir: 'backend/static/backend/dist/',
    manifest: true,
    rollupOptions: {
      input: [
        'yourreactfile.jsx',
      ]
    }
  }
})  

Install npm package

$ npm install
$ npm run dev

3.4. Create your jsx file

Example backend/components/app.jsx

import React from 'react'
import ReactDOM from 'react-dom'


function App(props) {
  return (
    <h1>{props.title}</h1>
  )
}

ReactDOM.render(
  <React.StrictMode>
    <App {...window.props} />
  </React.StrictMode>,
  document.getElementById("app")
)  

3.5. Use ReactMixin in your ClassView

from django.views.generic import TemplateView
from react.mixins import ReactMixin


class IndexView(ReactMixin, TemplateView):
    app_root = '/backend/components/app.jsx'
    def get_props_data(self):
        return {
            'title': 'Hello'
        }

3.6. Visit url in your brower

3.7. Build JS

Before prepare to deploy, run yarn dev