Skip to content

[webpack] webpack HMR(Hot Hodule Replacement) 應用於 django 搭配 react-hot-loader

Published: at 10:54 AM (4 min read)

前陣子剛換工作時,剛好部門內使用的後端為 django,前端為 react,然後使用 webpack 做編譯、打包及壓縮等佈署的動作。

但在開發前端 react 時必須要重複以下流程,更改程式碼 => 儲存 => 重新整理

想說既然有用 webpack ,就試著利用 webpack 所提供的 HMR(Hot Module Replacement) 來做 hot reload,開發會更快一點。

以下是當初設定的步驟~


dajngo 設定部分:

  1. 安裝 django-webpack-loader pip install django-webpack-loader

  2. 設定 settings.py

    [code] import sys import os

    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    STATICFILES_DIRS = ( os.path.join(BASE_DIR, ‘assets/bundles’), os.path.join(BASE_DIR, ‘assets/static), )

    WEBPACK_LOADER = { ‘DEFAULT’: { ‘BUNDLE_DIR_NAME’: ”, ‘STATS_FILE’: os.path.join(BASE_DIR, ‘webpack-stats.json’), } }

    INSTALLED_APPS = ( … ‘webpack_loader’, )

    [/code]

    讓 django 預設會抓取 assets/bundlesasset/static 這裡個位置的靜態檔案, webpack BUNDLE_DIR_NAME 設為 '',讓 webpack-loader 也至以上兩個路徑抓取靜態檔。

  3. 在 django 使用的 tempalte 中引用 wepack-loader module

    [html] {% load render_bundle from webpack_loader %} Example

    {% render_bundle ‘main’ ‘js’ %}

    [/html]

    上面這段( render_bundle ‘main’ )會幫你注入 script 標籤 (main.js)

webpack 設定部分:

  1. 安裝 webpack-dev-server 與 react-hot-loader npm install --save-dev webpack-dev-server react-hot-loader

  2. 設定  webpack.config.js

    [javascript]

    const path = require(‘path’); const webpack = require(‘webpack’); const BundleTracker = require(‘webpack-bundle-tracker’);

    module.exports = { context: __dirname, entry: { main: [‘react-hot-loader/patch’, ‘webpack-dev-server/client?http://localhost:3000’, ‘webpack/hot/only-dev-server’, ‘./assets/src/main.js’] }, output: { path: path.resolve(‘./assets/bundles/’), filename: ‘[name].js’, publicPath: ‘http://localhost:3000/assets/bundles/’, }, plugins: [ new webpack.HotModuleReplacementPlugin(), new BundleTracker({filename: ‘./webpack-stats.json’}) ], module: { loaders: [ { test: /\.js$/, loaders: [‘react-hot-loader/webpack’, ‘babel’], include: path.resolve(__dirname, “assets/src/”) }, { test: /\.js$/, loaders: [‘babel’], include: [ path.resolve(__dirname, “assets/src/”) } } } [/javascript]

    在上面這段 config,我們將 webpack 的進入點增加 localhost:3000 (為了 HMR 的即時更新畫面),並且設定 django-webpack-loader 的 public path 為 localshot:3000/assets/bundles,這會影響在 webpack_loader template 塞入 script 的 src。

    ps. webpack-bundle-tracker 會產出 webpakc-stats.json,提供 Django 的 webpack_loader 打包後的檔案資訊,以便正確塞對應的標籤.

  3. 新增 webpack-dev-server 的設定檔(server.js)

    [javascript] var webpack = require(‘webpack’); var WebpackDevServer = require(‘webpack-dev-server’); var config = require(‘./webpack.config’);

    new WebpackDevServer(webpack(config), { publicPath: config.output.publicPath, hot: true, headers: { “Access-Control-Allow-Origin”: ”*” }, inline: true, historyApiFallback: true, stats: ‘normal’ }).listen(3000, ‘0.0.0.0’, function (err) { if (err) { console.log(err); }

    console.log(‘Listening at 0.0.0.0:3000’); }); [/javascript]

    上面這個設定檔,設定了一些 HMR 需要的設定,如: CORS…等

react 的設定部分,這邊舉有用 react-reduxreact-router 的範例(若無使用以上兩者,可以直接把 AppContainer 包住 root component 即可:

  1. 將 react-hot-loader 套至所有 component

    [javascript] ‘use strict’; import { Provider } from “react-redux”; import { render } from “react-dom”; import React from ‘react’; import { Router, Route, browserHistory } from ‘react-router’; import configStore from “./redux/store/config”; import { AppContainer } from ‘react-hot-loader’;

    const store = configStore(); const history = syncHistoryWithStore(browserHistory, store); const renderApp = () => { render( , document.getElementById(‘root’) ); };

    if (module.hot) { module.hot.accept(); }

    renderApp(); [/javascript]

    在 react-redux 的 Provider 上面包一層 react-hot-loader 的 AppContainer,並且加上 module.hot.accept();

設定到這步就完成了~ 我們就可以執行 node server.js 用 webpack  watch 程式碼改變並即時更新至瀏覽器。

參考資料:

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

https://github.com/patrikholcak/hot-loader-demo