这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战
简介
Nuxt 是支持 Vue SSR 的一个框架,底层需要运行 Node 服务。大概描述一下 Vue 的渲染过程,首先每个组件都会被编译生成一个渲染函数(这部分基本 webpack 打包已经做掉),然后渲染函数生成虚拟 dom,最后虚拟 dom 通过 patch 方法将真实 dom 渲染到页面上。Nuxt 其实就是将这部分放到了服务端去做,在服务端拿到渲染页面所需要的 html,从而使得 html 能够直出,而客户端其实还是会运行整个 Vue 的生命周期
,这就带来了一个问题,这部分操作放在了服务端其实是非常耗 cpu 的
,创建组件实例和虚拟 DOM 节点的开销,无法与纯基于字符串拼接的模版的性能相当,如果是不加优化的 Nuxt 项目,高并发下是很脆弱的,毕竟 Node 运行在单线程下,不适合 cpu 操作密集型的场景
使用 Nuxt 的项目无非看中了它的两大优点,一是服务端渲染满足 SEO 的需求,二是首屏直出比 SPA 快,再加上如果如果公司是 Vue 系,使用 Nuxt 就更顺理成章。但是不要忘了性能,高并发下 Nuxt 性能确实不乐观,就算是最简的 Nuxt 项目,吞吐量也就 300+,这就说明如果项目不做缓存,300+ 已经是最大的吞吐量了,而最小 express demo 可以轻松到 3000,这就决定了高流量项目并不会轻易去使用 Nuxt
优化方向
缓存
缓存是最重要的方案,针对 Nuxt 项目可以做三级缓存,页面缓存、组件缓存以及 API 缓存。页面缓存是最重量级的缓存方案,能不能做页面缓存可以从以下两个点判断:
- 同一个 URL,对于 登录 / 非登录 用户,服务端渲染的内容是相同的(注意是服务端渲染内容,而非前端)
- 同一个 URL,对于不同的登录用户,服务端渲染的内容是相同的,即没有一些个性化的渲染(常见的个性化渲染,比如针对不同用户渲染不同的猜你喜欢内容等)
其实也就是返回的 html 代码相同就好,主要关注下返回的全局 store 是否一致,另外也不能做一些服务端才能做的操作,比如 set-cookie 等
控制好首屏模块个数
对返回的结果进行精简,最小化,保证吐出到浏览器的内容足够小。这就是前面说的并不要对所有模块都做 ssr,需要首屏呈现的/需要爬虫爬的,我们直出
不必要的渲染开销
服务端渲染最主要的作用是 seo,但并不是所有的页面都需要进行 seo。整站式的 ssr 意味着将消耗巨大服务器 cpu 资源,如果只从后端渲染需要 seo 的页面,将极大的节省 cpu 资源,空余出来的 cpu 资源则作用于更大的并发量。例如:掘金 就仅仅是在文章的详情页做 ssr 。
在不需要的组件外括上使用client-only 标签
踩坑
问题原因:当我们用SSR模式中,组件用v-if="API取得的值"的话,这个组件在一开始在服务器端(SSR)是不会被创建的,然后客户端(CSR)激活的时候由于拿到API数据导致这个组件为true,就产生了错误。(然后还被重复请求了三次,导致之后所有的界面都受牵连)所以用v-show的话,会在服务器端生成一个空的组件来占位,然后等客户端渲染的时候就自然而然出现了。
解决方法:用的v-if="API取得的值"改成了v-show就可以了。