什么是同构:
- 客户端渲染:页面在 JavaScript,CSS 等资源文件加载完毕后开始渲染,路由为客户端路由,也就是我们经常谈到的 SPA(Single Page Application)。
- 服务端渲染:页面由服务端直接返回给浏览器,路由为服务端路由,URL 的变更会刷新页面,原理与 ASP,PHP 等传统后端框架类似。
- 同构:英文表述为 Isomorphic 或 Universal,即编写的 JavaScript 代码可同时运行于浏览器及 Node.js 两套环境中,用服务端渲染来提升首屏的加载速度,首屏之后的路由由客户端控制,即在用户到达首屏后,整个应用仍是一个 SPA。
简而言之,同构是服务端直出和客户端渲染的结合
同构的优点:
- SEO 更友好。
- 整个页面级别的应用会使得浏览器在解析 DOM 完成之后马上有东西可以渲染,减少渲染等待时间(首屏优化)。
- 服务端和客户端仅需要维护一份代码。
- 开源福利:React v16 的发布,通过重写了用于服务端渲染的 renderToString 函数,将渲染速度提升至 v15 的 3 倍。
当然,同构也不是银弹,具体的选择还是看业务,权衡开发(迁移)成本,性能影响等等诸多因素。
那么问题来了:)
如果,我想尝试一下 React 服务端渲染,但又不想一开始就纠结于较繁琐的配置呢?
很多人的开发都会选用一个现有的脚手架开始,那么如何选用一个脚手架呢?
关于一个框架的脚手架,在网上经常看到开发者这样说:
I'm looking for a very simple starter pack... I don't need all the hoopla.
的确,对一个脚手架项目而言,它需要有所有你想要的,不需要有你不想要的。
react官方的脚手架create-react-app的README中提到 现阶段不支持直接提供服务端渲染。
那么有哪些支持同构渲染的脚手架呢?
比如这些:
这些脚手架各有各的特点,有的依赖多,有的依赖少,有的性能好,有的针对某一个痛点解决...
下面隆重介绍今天的主角 ———— razzle
razzle 是一个把所有于服务端渲染相关的繁琐配置抽象成了单独的一个依赖,给你类似于 create-react-app 的开发体验,但是把剩下的架构决策权,比如框架选用,路由系统的选择、数据获取方式全都交给了开发者自己,充分符合上面说的 have everything you need and nothing you don't.
razzle 和上述提到的其他支持同构渲染的框架的最大不同在于它能够将依赖抽象化,可以提供类似 create-react-app 的开发体验,这就意味了给了开发者很大的自由度去选择自己顺手的,自己看得上眼的 React 生态里的库,razzle 提供丰富的 examples,帮助开发者能够快速的结合一些流行的成熟的库,比如用 TypeScript 进行开发,结合 react-redux 做状态管理,结合 react-router 做路由系统,结合 react-loadable 做到组件级别的代码分割和懒加载等等很多。
razzle 的理念决定了它不只只支持 React,还支持 Reason, Elm, Vue, Angular 和未来的新框架:)
总结一下,razzle 的主要的优点有:
- 开发环境支持模块热替换,无需重启服务就可以看到效果
- ES6 支持
- 与create-react-app 相同的 CSS 设置
- 很多其它框架的支持
- 默认支持 Jest
- 零配置即可上手服务端渲染
关于同构有一些误区,列几个熟悉的:
同构性能没有客户端渲染好?网络流量高峰的时候,转到客户端渲染并不会起很大作用。ssr 在服务端的渲染其实是非常快的,尽管这里提供不了精确的数据支持,但是看了很多博客上都提到过这种观点。
同构容易引起内存泄漏?其实并不是,只要注意不要盲目的在定时的函数体中向全局的数组 push 东西;注意组件生命周期,不要在
componentDidMount
中放置服务端执行不了的代码,并且注意在用一些如window
变量前先进行判断就好,并不是很容易导致内存泄漏。
理解还不是很成熟,希望能与大家交流讨论。
笔者是 razzle 的项目使用者,受益者,希望能让更多的人看到这个项目,未来一起让他变得更好。
关于同构的一些其他文章:
What is an isomorphic application?