前陣子剛換工作時,剛好部門內使用的後端為 django
,前端為 react
,然後使用 webpack 做編譯、打包及壓縮等佈署的動作。
但在開發前端 react 時必須要重複以下流程,更改程式碼 => 儲存 => 重新整理
想說既然有用 webpack ,就試著利用 webpack 所提供的 HMR(Hot Module Replacement) 來做 hot reload,開發會更快一點。
以下是當初設定的步驟~
dajngo 設定部分:
-
安裝 django-webpack-loader
pip install django-webpack-loader
-
設定 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/bundles
與asset/static
這裡個位置的靜態檔案, webpackBUNDLE_DIR_NAME
設為''
,讓webpack-loader
也至以上兩個路徑抓取靜態檔。 -
在 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 設定部分:
-
安裝 webpack-dev-server 與 react-hot-loader
npm install --save-dev webpack-dev-server react-hot-loader
-
設定 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
打包後的檔案資訊,以便正確塞對應的標籤. -
新增 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-redux
與 react-router
的範例(若無使用以上兩者,可以直接把 AppContainer 包住 root component 即可:
-
將 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(
… if (module.hot) { module.hot.accept(); }
renderApp(); [/javascript]
在 react-redux 的 Provider 上面包一層 react-hot-loader 的 AppContainer,並且加上
module.hot.accept();
設定到這步就完成了~ 我們就可以執行 node server.js
用 webpack watch 程式碼改變並即時更新至瀏覽器。
參考資料: