原文連接javascript
前言前端
hot reload分析java
react靜態資源熱加載分析node
react服務器配置分析react
待解決webpack
總結git
由react
客戶端渲染的前端界面配合webpack-dev-server
, react-hot-loader
很容易實現前端開發過程當中的局部刷新。然而配合node服務器的react-isomorphic
實現局部刷新,同時更新client
, server
端的代碼並不是易事。
以下介紹一種可行的實施方案:github
適用於
koa2
,react-hot-loader3
,react-router
無關緊要。webDemo代碼地址:https://github.com/lanjingling0510/blog/tree/master/react-isomorphic-hot-exampleexpress
react靜態資源的熱加載配置並不複雜。webpack-dev-server
負責從新編譯代碼,react-hot-loader
負責熱加載。
Note:
webpack-dev-server
也能夠用開一個express
服務器配合webpack-dev-middleware
和webpack-hot-middleware
中間件實現
配置webpack.client-dev.js
:
plugins: [ new webpack.HotModuleReplacementPlugin() ] // ... entry: [ 'react-hot-loader/patch', 'webpack-dev-server/client?http://127.0.0.1:8080', 'webpack/hot/only-dev-server', './src/client/home', // 入口路徑 ]
修改babel
配置文件
"plugins": [ "react-hot-loader/babel" ]
修改入口文件
import React from 'react'; import ReactDOM from 'react-dom'; // 共享的組件頁面 import Home from '../shared/page/Home'; // 熱加載組件 import ReactHotLoader from '../shared/component/ReactHotLoader'; const container = document.getElementById('react-container'); function renderApp(TheApp) { ReactDOM.render( <ReactHotLoader> <TheApp /> </ReactHotLoader>, container ); } renderApp(Home); // 下面的代碼用來支持咱們熱加載應用 if (__DEV__ && module.hot) { // 接受這個文件的修改用來熱加載 module.hot.accept('./home.js'); // 應用任何的改變將形成熱加載,從新渲染。 module.hot.accept( '../shared/page/Home', () => renderApp(require('../shared/page/Home').default) ); }
開發模式下,server端的配置比較複雜,須要考慮的事情以下:
監聽server代碼的變更。
須要從新編譯server代碼
從新開啓server服務器,並保證require最新的server代碼
保證server端口按需開關,不衝突
監聽server代碼
// 監聽server文件的變化,若是被修改則調用compileHotServer const watcher = chokidar.watch([ path.resolve(__dirname, '../src'), path.resolve(__dirname), ], {ignored: path.resolve(__dirname, '../src/client')}); watcher.on('ready', () => { watcher .on('add', compileHotServer) .on('addDir', compileHotServer) .on('change', compileHotServer) .on('unlink', compileHotServer) .on('unlinkDir', compileHotServer); });
關閉全部與客戶端的鏈接,關閉server服務器,從新編譯server代碼
// 關閉全部鏈接,關閉服務器,從新編譯 function compileHotServer() { compiling ++; // listenerManager實例包含當前web服務器對象和客戶端鏈接的socket集合 if (listenerManager) { listenerManager.dispose(true).then(runCompiler); } else { runCompiler(); } } // webpack從新編譯 function runCompiler() { compiler.run(() => undefined); }
從新開啓server服務器
// server代碼編譯完成 // 開啓server服務器 compiler.plugin('done', stats => { compiling --; if (compiling !== 0) return; if (stats.hasErrors()) { console.log(stats.toString()); return; } console.log('? ? Build server bundle done.'); // 確保新的server bundles 代碼不在module cache當中 Object.keys(require.cache).forEach((modulePath) => { if (modulePath.indexOf(compiler.options.output.path) !== -1) { delete require.cache[modulePath]; } }); try { const listener = require(compiledOutputPath).default; listenerManager = new ListenerManager(listener, 'server'); } catch (err) { console.log(err); } });
. react-router
包含的頁面組件更新後,提示[react-router] You cannot change <Router routes>; it will be ignored
,但不影響刷新
經過以上配置,能夠實現修改代碼後,實現server和client代碼的更新以及hot reload。
代碼開發過程當中,須要開啓兩個端口,分別用來提供client端靜態資源的編譯和後臺的server。
若是在開發模式下,有更完善的react isomoriphic
服務器渲染熱加載的解決方案,歡迎你們積極貢獻 ?