美文网首页Python Web 开发
Django 和 ReactJS 集成开发环境

Django 和 ReactJS 集成开发环境

作者: xiez12 | 来源:发表于2018-03-19 17:46 被阅读0次

    layout: post
    title: Develop with React.js and Django
    categories: django reactjs web-dev


    这篇文章记录了从零搭建 Django 和 React.js 开发环境,并配置 Webpack 模块热替换的步骤。

    注意:本文所记录的方式并不是目前主流的前后端完全分离结构。主要针对一些早期的集中式(monolithic) Django 项目转向前后端分离开发,所以 html 模板还是由服务器渲染。

    OK, 进入正题~

    准备环境

    前端:

    nodejs & npm

    参照这里下载安装。完成后,运行命令查看相应版本。

    $ node -v
    v9.6.1
    
    $ npm -v
    5.7.1
    

    webpack

    前端项目模块(css,js,img)管理工具,把项目所有依赖的库打包到一个或多个bundle文件(例如,bundle.js)。

    babel

    Javascript 编译器,能把新的 ES6 语法转换成 ES5 语法,兼容现有的浏览器。

    webpack-bundle-tracker

    把 webpack 编译过程记录到文件(webpack-stats.json),供 django-webpack-loader 使用。

    后端:

    Django V1.11

    pip install Django==1.11
    

    django-webpack-loader

    pip install django-webpack-loader
    

    开始流程

    创建 Django 项目

    $ django-admin startproject django_react_proj
    $ tree django_react_proj
    django_react_proj
    ├── django_react_proj
    │   ├── __init__.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py
    
    1 directory, 5 files
    

    启动开发服务器:

    $ python manage.py runserver
    
    runserver.img

    增加 index 页面

    django_react_proj/urls.py

    from django.conf import settings
    from django.conf.urls import url
    from django.contrib import admin
    from django.views.generic import TemplateView
    
    urlpatterns = [
       url(r'^admin/', admin.site.urls),
       url(r'^$', TemplateView.as_view(template_name="index.html")),
    ]
    
    if settings.DEBUG:
       from django.contrib.staticfiles import views
       urlpatterns += [
           url(r'^static/(?P<path>.*)$', views.serve),
       ]
    

    django_react_proj/settings.py

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'django_react_proj/templates'), ],
            'APP_DIRS': True,
            'OPTIONS': {
            ...
            },
        },
    ]
    

    django_react_proj/templates/index.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            <title>Example</title>
        </head>
    
        <body>
            <div><p>Hello Django</p></div>
        </body>
    </html>
    

    刷新页面

    hellodjango.jpg

    创建 React 项目

    1. 在项目根目录下,新建 frontend 目录,使用 npm init 创建前端项目。

    $ mkdir frontend && cd frontend && npm init
    

    完成后,会创建package.json文件。

    2. 安装 React 开发相关的依赖

    $ npm install --save-dev babel-cli babel-loader babel-preset-env babel-preset-react babel-preset-stage-0 react react-dom react-hot-loader webpack webpack-cli webpack-bundle-tracker webpack-dev-server
    

    其中,--save-dev 会把依赖写入package.json。这些第三方库位于当前项目下node_modules目录。如果有些库需要全局使用,安装时需要用-g选项。如果需要重装依赖库,只需要执行npm instal

    3. 创建 webpack 配置文件

    $ mkdir -p assets/js
    $ touch webpack.config.js
    $ touch assets/js/index.js
    

    其中,assets/js目录为我们代码所在目录。webpack.config.jswebpack的配置文件。assets/js/index.js是项目的入口文件。webpack 从该文件开始加载所有项目依赖模块。Webpack 官方配置手册

    4.修改 webpack.config.js

    var path = require("path")
    var webpack = require('webpack')
    var BundleTracker = require('webpack-bundle-tracker')
    
    module.exports = {
      entry: [
        './assets/js/index'
      ],
    
      resolve: {
        extensions: ['.js', '.jsx']
      },
    
      output: {
        path: path.resolve('./assets/bundles/'),
        filename: "bundle.js",
        sourceMapFilename: 'bundle.map',
      },
    
      devtool: '#source-map',
    
      module: {
        rules: [
          {
            test: /\.jsx?$/,
            exclude: /(node_modules)/,
            loader: 'babel-loader',
            query: {
              presets: ['env', 'stage-0', 'react']
            }
          }
        ]
      },
    
      context: __dirname,
    
      plugins: [
        new BundleTracker({filename: './webpack-stats.json'})
      ],
    
      mode: 'development'
    }
    

    现在的目录结构:

    $ tree -L 2
    .
    ├── db.sqlite3
    ├── django_react_proj
    │   ├── __init__.py
    │   ├── __init__.pyc
    │   ├── settings.py
    │   ├── settings.pyc
    │   ├── urls.py
    │   ├── urls.pyc
    │   ├── wsgi.py
    │   └── wsgi.pyc
    ├── frontend
    │   ├── assets
    │   ├── node_modules
    │   ├── package-lock.json
    │   ├── package.json
    │   └── webpack.config.js
    └── manage.py
    

    5. 编译项目

    使用 webpack 编译前端项目

    $ ./node_modules/.bin/webpack-cli --config webpack.config.js
    

    完成后生成的文件位于 assets/bundles/bundle.js

    修改 Django settings,增加 webpack_loader 配置

    settings.py

    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'frontend/assets'),  # We do this so that django's collectstatic copies or our bundles to the STATIC_ROOT or syncs them to whatever storage we use.
    )
    
    WEBPACK_LOADER = {
        'DEFAULT': {
            'BUNDLE_DIR_NAME': 'bundles/',
            'STATS_FILE': os.path.join(BASE_DIR, 'frontend/webpack-stats.json'),
        }
    }
    
    # Application definition
    
    INSTALLED_APPS = [
        ...
        'webpack_loader',
    ]
    

    templates/index.html

    {% load render_bundle from webpack_loader %}
    <!DOCTYPE html>
    <html>
       <head>
         <meta charset="UTF-8">
         <title>Example</title>
       </head>
    
       <body>
           <div><p>Hello Django</p></div>
           <div id="react-app"></div>
           {% render_bundle 'main' %}
       </body>
    </html>
    

    刷新页面后,浏览器会去加载frontend/asserts/bundles/bundle.js。说明 Django 已经可以把正确的bundle.js路径传给模板。

    bundlejs.jpg

    修改 React App,增加 App 组件

    frontend/assets/js/index.js

    import React from 'react';
    window.React = React;
    import ReactDOM from 'react-dom';
    import App from './App';
    
    ReactDOM.render(<App/>,
                    document.getElementById('react-app'))
    

    frontend/assets/js/App.jsx

    const App = () =>
              <p>Hello ReactJS</p>;
    
    export default App;
    

    重新编译

    $ ./node_modules/.bin/webpack-cli --config webpack.config.js
    

    成功后,刷新页面。此时,Django 和 ReactJS 已经调通。后续前端JS的改动,重新编译后,Django 会自动使用最新的 assets/bundles/bundle.js

    reactjs.jpg

    webpack 增加watch选项,自动编译

    ./node_modules/.bin/webpack-cli --config webpack.config.js --watch
    

    每次手工编译比较耗时,增加 --watch 选项后,webpack 会监听 assets 目录下所有文件,任何 React 模块的改动,webpack 都会自动编译,刷新浏览器页面即可看到改动效果,加快开发效率。

    webpack 模块热替换 HMR

    使用 webpack HMR 功能,可以在不刷新浏览器页面的情况下,将 React 模块的改动自动应用到浏览器页面上,进一步加快开发效率。

    安装 babel-preset-react-hot

    $ npm install babel-preset-react-hot --save-dev
    

    修改 webpack.config.js

    var path = require("path")
    var webpack = require('webpack')
    var BundleTracker = require('webpack-bundle-tracker')
     
    module.exports = {
      entry: [
        'webpack-dev-server/client?http://localhost:8080',
        'webpack/hot/only-dev-server',
        './assets/js/index'
      ],
     
      resolve: {
        extensions: ['.js', '.jsx']
      },
     
      output: {
        path: path.resolve('./assets/bundles/'),
        filename: "bundle.js",
        sourceMapFilename: 'bundle.map',
        publicPath: 'http://localhost:8080/assets/bundles/', // Tell django to use this URL to load packages and not use STATIC_URL + bundle_name
     
      },
     
      devtool: '#source-map',
     
      module: {
        rules: [
          {
            test: /\.jsx?$/,
            exclude: /(node_modules)/,
            loader: 'babel-loader',
            query: {
              presets: ['env', 'stage-0', 'react', 'react-hot']
            }
          }
        ]
      },
     
      context: __dirname,
     
      plugins: [
        new BundleTracker({filename: './webpack-stats.json'})
      ],
     
      devServer: {
        headers: {
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
          "Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
        }
      },
     
      mode: 'development'
    }
    

    启动 webpack-dev-server

    $ ./node_modules/.bin/webpack-dev-server --inline --progress --hot
    

    使用 --hot 参数取代之前的 --watch 参数。

    最终效果

    hotreload.gif

    示例代码

    https://github.com/xiez/django_react_proj/

    参考链接

    http://owaislone.org/blog/webpack-plus-reactjs-and-django/

    http://matthewlehner.net/react-hot-module-replacement-with-webpack/

    相关文章

      网友评论

        本文标题:Django 和 ReactJS 集成开发环境

        本文链接:https://www.haomeiwen.com/subject/ssbpqftx.html