前言
前段时间为了绩效个人提升,研究了下SSR服务端渲染。加载速度快,还有 SEO,解决了之前公司CSR的一些通病。 所以就自己造了个轮子用 nextjs + mobx + antd + ts实现 SSR 多页签服务端渲染脚手架。
什么是SSR
最初听说有单页面的服务端渲染的时候,就理解为类似传统的服务端路由+模板渲染,只是需要用单页面应用的框架写。后面寻思这样好像有点傻,再一了解,原来只是在首次加载的时候,后端进行当前路径页面的组件渲染和数据请求,组装成HTML返回给前端,用户就能很快看到看到页面,当 HTML 中的 JS 资源加载完成后,剩下执行和运行的就是一般的单页面应用。
所以SSR是后端模板渲染和单页面的组合。 SSR有两种模式,单页面和非单页面模式,第一种是后端首次渲染的单页面应用,第二种是完全使用后端路由的后端模版渲染模式。他们区别在于使用后端路由的程度。
优势
SSR的两个明显的优势:首次加载快和 SEO。 为什么说首次加载快呢。 一个普通的单页面应用,首次加载的时候需要把所有相关的静态资源加载完毕,然后核心JS才会开始执行,这个过程就会消耗一定的时间,接着还会请求网络接口,最终才能完全渲染完成。
SSR模式下,后端拦截到路由,找到对应组件,准备渲染组件,所有的 JS 资源在本地,排除了JS资源的网络加载时间,接着只需要对当前路由的组件进行渲染,而页面的 ajax 请求,可能在同一台服务器上,如果是的话速度也会快很多。最后后端把渲染好的页面反回给前端。
注意:页面能很快的展示出来,但是由于当前返回的只是单纯展示的 DOM、CSS,其中的 JS 相关的事件等在客户端其实并没有绑定,所以最终还是需要 JS 加载完以后,对当前的页面再进行一次渲染,称为同构。 所以SSR就是更快的先展示出页面的内容,先让用户能够看到。
为什么SEO友好呢,因为搜索引擎爬虫在爬取页面信息的时候,会发送 HTTP 请求来获取网页内容,而我们服务端渲染首次的数据是后端返回的,返回的时候已经是渲染好了 title,内容等信息,便于爬虫抓取内容。
如何实现
大致对SSR有了一个了解,我们现在需要对实现整理一下大致实现思路和流程。
1.选择一个单页面框架
2.选择node服务端框架
3.实现核心逻辑,让node服务端能够路由和渲染单页面组件
4.优化开发和发布环境自动化构建工具(webpack)
综合以上的几点,我们选择nextjs作为我们的基础框架,我们在上面二开就行了。不然得话我们既要熟悉node框架类似koa,也要熟悉前端框架react之类的,费时费力。既然社区已经有了成熟的方案,我们直接拿过来,真香🐶。
自定义入口
基础的nextjs使用这里我就不再多说了,大家可以去看官方网站。用nextjs创建项目后,第一步我们修改入口app.tsx,因为我们要的是多页签的,所以呢自定义layout:
看到这里有个判断,如果有Layout就直接渲染Component,这是为登录页面等一些不需要多页签的页面准备的,login:
如果没有Layout,我们就把Component传入多页签组件BasicLayout:
其实很简单就是个左右分开的传统B端样式,TabPanes里面会有 Tabs保存不同路由的页面。
getInitialProps
getiInitialProps 是 Next.js 的核心,它确定了一个规范,一个页面组件只要把访问 API 外部资源的代码放在 getInitialProps 中就足够,其余的不用管,Next.js 自然会在服务器端或者浏览器端调用 getInitialProps 来获取外部资源,并把外部资源以 props 的方式传递给页面组件。
不过在我的实践中,如果在getiInitialProps中直接返回外部资源,在初始渲染页面时,服务端和客户端都会调用接口,个人感觉是冗余的。所以大家也看到,此处判断了是否是服务端,如果是客户端,返回false,走CSR的逻辑,个人感觉会更有效率。
mbox, 使用useStaticRendering进行服务器端渲染
基本的mbox使用这边就不过多的介绍了,主要介绍下如何区分服务端和客户端如何使用,看代码:
使用服务器端呈现时,不会触发React组件的正常生命周期钩子,因为组件只渲染一次。由于组件从不卸载,observer组件在这种情况下在呈现服务器端时会泄漏内存。为了避免内存泄漏,在使用服务器端呈现时调用useStaticRendering(true)。
还有就是在初始化state时也要区分服务端和客户端,这边再注意下就不会有其他问题了。
API层
从代码上看我在API层做了服务端和客户端的,两端的处理方式是不同的。在这里服务端调用的请求是通过Node直接调用后端代码,当然也可以直接调用数据库。而在客户端的请求通过node服务产生的接口,这里还是有不同的。
尾声
主要的关键点已经在上面都提到了,有需要的可以去w-nextjs-app关注下,当然里面还有很多bug,我会慢慢完善。