同构应用能够实现的基础是虚拟DOM,基于虚拟DOM我们可以生成真实的DOM,并由浏览器渲染;也可以调用不同框架的API,将虚拟DOM生成字符串,由服务器端传输给客户端。
1.打包环境区分
同构应用实现了客户端代码和服务器端代码的基本统一,我们只需要编写一种组件,就能生成适用于服务器端和客户端的组件。大多数情况下还是需要单独处理的,差别决定了代码复用难易程度。
-
路由代码差别
服务器端需要根据请求路径匹配页面组件,客户端需要通过浏览器中的地址匹配页面组件。
const App = () => { return ( <Provider store={store}> <BrowserRouter> <div> <Route path='/' component={Home} /> </div> </BrowserRouter> </Provider> ) } ReactDom.render(<App />, document.querySelector('#root'))
客户端BrowserRouter组件根据window.location及history API实现页面切换。
const App = () => { return ( <Provider store={store}> <StaticRouter location={req.path} context={context}> <div> <Route path='/' component={Home} /> </div> </StaticRouter> </Provider> ) } return ReactDom.renderToString(<App />)
服务器端肯定无法获取到window.location,需要使用StaticRoute组件,并将请求地址与上下文信息作为location和context传入。
-
打包差别
由于路由代码的差异,webpack配置文件的entry也会不同。
2.注水和脱水
在服务器端渲染时,服务器端会请求接口获取数据,并处理准备好的数据状态,为了减少客户端的请求,需要保留这个状态。一般做法是在服务器端返回HTML字符串的时候,将JSON.stringify一并返回,这个过程叫脱水。
客户端不需要请求获取数据,因为它可以直接使用服务器端下发的数据,这个过程叫注水。
3.请求认证处理
服务器端发出请求时需要保留客户端页面请求的信息,并在API请求获取信息时携带并透传这个信息。
headers: {
cookie: req.header('Cookie'),
}
它使服务器端发出的请求完整地的还原了客户端信息。
4.性能优化
- 使用缓存:服务器端优化的一个最重要手段,目前的措施可以实现组件级缓存。
- 采用HSF代替HTTP:分布式的远程服务调用框架,在对外提供服务上,性能远远高于HTTP。
- 对于服务器端压力过大的场景,可以将服务器端渲染动态切换为客户端渲染。
- 升级Node.js、升级React。