前言
自己的博客当初技术选型,采用的是ssr技术。这样的好处是,一方面可以做一些适量的seo,另一方面,也是为了解决曾经采用SPA方案开发的个人博客在我1M的腾讯云上首屏加载动辄几十秒的白屏时间的痛苦。
技术栈还是Vue,SSR框架选择了Vue官方推荐的Nuxt.js。这个项目打算做一个长期的维护和补充完善,考虑到开发和维护过程中已经有了更多技术层面的需求的思考,以及一些问题的发现和解决,特地开一篇文章,做一个记录,暂时不分结构不分层次,仅是一些随手记录,待总结由点及面形成系统后可以再尝试做一个完成的总结。
正文
部分组件生命周期函数重复执行问题
起因在于使用了一个第三方登录认证,使用登录认证成功后回调传的参数去获取授权的用户资料时,总是返回参数过期获取用户资料失败。
实现这个过程的逻辑是,在 layout 组件的 created 钩子函数中检查用户状态,若未登录就获取URL链接的参数并请求后台接口进行第三方资料获取(这里的链接中的参数仅可使用一次,用后即失效,需要重新进行第三方登录)。bug定位了花了些时间,问题就在于,触发操作的页面由服务端渲染主体结构,返回客户端后再去渲染一些其他数据。因此,created 钩子在服务端渲染时执行一次,而在客户端又会执行一次。而开发时仅能捕捉到客户端执行 created 函数后调用的 xhr请求,而很难定位到服务端渲染时调用的xhr请求。
最后还是在官方文档中找到了相关说明
可以看到,beforeCreate 和 created 这两个方法会在 客户端和服务端被调用。其他生命周期函数仅在客户端被调用。
解决方案是,在 created 中通过 typeof(process) (服务端), typeof(window)(客户端)判断执行环境,然后执行对应逻辑,或在mounted 中执行对应的逻辑。
缓存
通过 lru cache 缓存部分重复使用,更新不频繁的 html 文件及 组件
const LRU = require('lru-cache')
const cachePage= new LRU({
max: 2000,
// 缓存有效期
maxAge: 1*60*1000
})
export default function(req, res, next){
let url = req._parsedOriginalUrl
let pathname = url.pathname
// 缓存首页
if (['/home'].indexOf(pathname) !== -1) {
const existsHtml = cachePage.get('homeData')
if (existsHtml) {
return res.end(existsHtml.html, 'utf-8')
} else {
res.original_end = res.end
// 重写res.end
res.end = function (data) {
if (res.statusCode === 200) {
// 设置缓存
cachePage.set('homeData', { html: data})
}
res.original_end(data, 'utf-8')
}
}
}
next()
}
拆分页面
可拆分不需要 ssr 的页面,只对必要页面做 ssr,能缩短首屏加载时间,优化用户体验,同时能有效减小服务端压力。