react服务器渲染下,hot reload解决方案

原文链接 前言 hot reload分析 react静态资源热加载分析 react服务器配置分

原文链接

  • 前言

  • hot reload分析

    • react静态资源热加载分析

    • react服务器配置分析

  • 待解决

  • 总结

react 客户端渲染的前端界面配合 webpack-dev-server , react-hot-loader 很容易实现前端开发过程中的局部刷新。然而配合node服务器的 react-isomorphic 实现局部刷新,同时更新 client , server 端的代码并非易事。

如下介绍一种可行的实施方案:

适用于 koa2 , react-hot-loader3 , react-router 可有可无。

Demo代码地址: https://github.com/lanjingling0510/blog/tree/master/react-isomorphic-hot-example

hot reload分析

react服务器渲染下,hot reload解决方案

react静态资源热加载分析

react静态资源的热加载配置并不复杂。 webpack-dev-server 负责重新编译代码, react-hot-loader 负责热加载。

Note: webpack-dev-server 也可以用开一个 express 服务器配合 webpack-dev-middlewarewebpack-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"

]

  1. 修改入口文件

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)

);

}

react服务器配置分析

开发模式下,server端的配置比较复杂,需要考虑的事情如下:

  • 监听server代码的变动。

  • 需要重新编译server代码

  • 重新开启server服务器,并保证require最新的server代码

  • 保证server端口按需开关,不冲突

  1. 监听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);

});

  1. 关闭所有与客户端的连接,关闭server服务器,重新编译server代码

// 关闭所有连接,关闭服务器,重新编译

function compileHotServer() {

compiling ++;

// listenerManager实例包含当前web服务器对象和客户端连接的socket集合

if (listenerManager) {

listenerManager.dispose(true).then(runCompiler);

} else {

runCompiler();

}

}

// webpack重新编译

function runCompiler() {

compiler.run(() => undefined);

}

  1. 重新开启server服务器

// server代码编译完成

// 开启server服务器

compiler.plugin('done', stats => {

compiling --;

if (compiling !== 0) return;

if (stats.hasErrors()) {

console.log(stats.toString());

return;

}

console.log(':rocket: :stuck_out_tongue_closed_eyes: 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 服务器渲染热加载的解决方案,欢迎大家积极贡献 :grin:

未登录用户
全部评论0
到底啦