# 正文
上一节,我们实现了一个react ssr版的hello world,让我们对服务端组件直出有了一个基本的了解。
单纯的ssr也没啥意义,也只能把组件当做一个模板来用,连个最基本的交互都没有。
比如:我想点击页面某个元素的时候给我一个反馈提示。

ok ,这不就是增加一个事件么,这个太简单了吧,代码信手拈来。
//组件
export default class Index extends React.Component {
constructor(props) {
super(props);
}
handlerClick(){
alert('一起来玩 react ssr 啊');
}
render() {
return <h1 onClick={this.handlerClick}>click here!</h1>
}
}
其实结果可想而知,这个事件根本不会执行的。
这是为什么呢?
我们都知道元素事件是基于浏览器执行的,只有在浏览器端执行了相应的 js 代码才能绑定事件。
在上一节我们实现的这是一个 ssr 直出效果,也就是说只是一个静态页面。
所以我们需要让代码在浏览器端也执行一次,组件在浏览器端挂载完后react会自动完成事件绑定。
浏览器也执行一次代码,组件不会重复渲染吗?
浏览器接管页面后,react-dom在渲染组件前会先和页面中的节点做对比,只有对比失败的时候才会采用客户端的内容进行渲染,且react会尽量多的复用已有的节点。
# 初识同构
那需要写两套代码?
既然客户端和服务端都要执行,那是不是就要写两份代码,供双端使用?
当然不需要,也完全不合理。
这正是我们本节的重点 - 同构。
基于同构,浏览器和服务端可以运行同一份代码,服务端直出组件后,浏览器接管页面,然后剩下的工作由浏览器来完成。
# 客户端代码执行
经过上面一些理论的分析,我们已经清楚的了解到我们应该做什么。
现在回到正题,来实现元素事件的绑定。
# 如何实现?
大家应该都做过react spa项目,大部分情况都是 请求页面后服务器返回了一个页面的基本框架,同时包括 js css 等静态资源。
所以这里我们第一步要先把js代码打包,在服务端ssr 时,同时将这个 js 资源输出就可以了。
如图

# 实现思路说明
为了方便开发我们从这里开始使用 koa2来构建 http 服务。
另外统一双端的模块化方式,在 node 端也使用 es6 module 方式进行模块的引入,但是在node 端不能运行,所以需要使用 babel 进行编译。
npx babel xxx.js
整体实现思路
- 使用
koa创建一个基础http服务,可以直出Index组件。 - 然后编写客户端代码,增加
Index组件的渲染入口,使用react-dom库渲染Index组件。 - 然后使用
webpack将js代码打包到一个文件内index.js内。 - 服务端直出的时候输出这个
js资源到浏览器。 - 在运行前,需要使用
webpack将客户端代码编译打包,使用babel cli打包编译服务端代码。
# 安装插件、工具、库
react react-dom //react 基础库
@babel/core @babel/cli //babel 基础库
@babel/preset-react //编译 react 代码
@babel/preset-env //配置 babel 编译的一些选项
babel-loader //编译 js 代码
webpack webpack-cli //webpack 两个核心库
koa2 //web 开发框架
koa-static //实现静态资源的访问
ps:@babel/preset-env 是一个预设集合,代替了以往的 stage-* babel-preset-es2015等包,可以根据开发者的配置,
