那些年我踩过的Nuxt坑

3,579 阅读8分钟

Nuxt 相关踩坑说明

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

为了满足公司(老板)的seo需求,我开始了从0到1的Nuxt探索之旅,路上遇到过很多问题,有些很难解决也找不到原因,有些是误打误撞找到了解决方案(都是辛酸血泪史),目前公司所有需要seo的项目都从Nuxt1升级到了Nuxt2,是时候总结我的踩坑历史了!

nuxt 实现 ssr 服务端渲染原理: nuxt.js 在客户端和服务端之间搭建了一个 node 服务器,当浏览器发起请求时,会在中间的 node 服务器渲染 html 页面,并同时将 asyncData 中需要的数据向服务器进行请求,并渲染在 html 页面上,然后将这个 html 页面返回给浏览器。浏览器就可以进行展示,之后浏览器会向服务器发起 js 文件的请求,返回后用户可以进行其他操作和交互。

nuxt 解决了 seo 和首屏渲染白屏问题,但同时也有很多问题,时不时就会出现一个坑,在经过 Nuxt1 到 Nuxt2 两个框架的实践和升级迭代后,把现有的疑难杂症进行记录: (以下所指 Nuxt1 都为 Nuxt1.0.0 版本,Nuxt2 都为 Nuxt2.15.8 版本)

1、node 版本问题

问题说明:项目打包时依赖找不到或无法安装,域名强校验 TTLSocket 有问题。

问题原因:由于 Nuxt 框架所需依赖的兼容问题,对 node 的版本要求比较苛刻,较新版本会导致测试环境的不稳定,无法正常安装依赖进行打包部署,导致部署失败,页面直接崩溃

解决方案:实践后发现 node:14.17.1 的版本最为稳定。

2、core-js 依赖

问题说明:项目打包时core-js依赖找不到或无法安装

问题原因:Nuxt 框架版本所需依赖的兼容问题

解决方案:Nuxt1升级到Nuxt2时需要额外安装此依赖。

3、cookies 问题

问题说明:用户登录情况下,在 asyncData 中获取用户信息,接口会返回用户未登录。

问题原因:从原理可以看出,我们要把 需要 seo 渲染的数据 放在 asyncData 中进行获取,但是 asyncData 是在服务器上进行请求的,所以无法获取浏览器层级的 cookies,当我们在 asyncData 中需要获取和用户账号相关的信息时,接口没有获取到 cookies,就无法返回正确的数据给到前端,所以在 asyncData 中的请求涉及到用户信息时,需要手动传递 cookies。

解决方案

  • 理论:Nuxt 官方提供了浏览器请求的 req 和 res 对象 www.nuxtjs.cn/guide/async… 我们可以在req对象中获取到headers和里面的cookies,将获取到的cookies等信息手动添加到axios的请求头参数中即可。

  • 实践:到手动添加 cookies 这最后一步开始出现各种各样的问题。MDN 官方说明不能在代码中通过编程的方式进行修改 HTTP 协议消息首部的一些属性,包括 cookies 和 host(具体属性请查看 MDN:developer.mozilla.org/zh-CN/docs/…

注意

  • 做好属性是否存在的确认和兼容。
  • 若测试库出现间隔性的 server error 或者正式库部署后页面崩溃无法访问,大概率是 headers 传递时出现问题,可能传了空值,及时排查,正式上线时最好部署一个 User-Agent 版本进行查看
  • 传递 headers 时注意对象嵌套的层级,具体可参考下方写法
//具体页面:
export default {
  asyncData({ req, res }) {
    // 请检查您是否在服务器端
    if (process.server) {
      //?.为ES6可选链写法,需要安装"@babel/plugin-proposal-optional-chaining": "^7.14.5"依赖
      return { headers: req?.headers || {} };
    }
    return {};
  },
};
// axios请求配置
let instance = axios.create({
  baseURL: "https://ac.cingta.com/",
  withCredentials: true,
  headers: {
    "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
  },
});
function postState(path, data, config = {}) {
  let params = [path, qs.stringify(data)];
  if (Object.keys(config).length) {
    config["Content-Type"] = "application/x-www-form-urlencoded;charset=UTF-8";
    params.push({ headers: config });
  }
  return instance.post(...params).then(stateData);
}
export default { postState };

4、CDN 资源管理问题

问题说明:打包后的项目有许多 js 文件,这些 js 文件中有一些体积比较大,会占据一部分带宽。项目中需要将这些文件放在 CDN 路径下,并在项目中配置 CDN 前缀的访问路径。但出现配置不生效的问题。

问题原因:在 nuxt.config.js 文件中 bulid 属性下的 publicPath 进行配置,Nuxt 进行 build 打包时会读取 nuxt.config.js 文件中我们自定义的配置项,不生效是因为没有读取到。

解决方案:Nuxt2 中部署时需要上传 nuxt.config.js 这份配置文件,否则在打包时项目无法读取到该文件中的配置属性,则该配置不生效,Nuxt1 版本中不需要

//nuxt.config.js文件中
export default {
  ……
  build:{
    // 配置cdn路径
    publicPath: 'https://static.cingta.com/……',
  }
}

5、process.env 中写入的属性不生效

问题说明:项目部署时,会在 env 文件中写入 port、baseUrl 等属性添加到 process.env 对象中,项目中将根据 env 对象中的这些属性来判断项目运行环境,从而使用不一样的资源和请求路径。当写入的属性不生效时,项目中会采用默认的值进行判断,导致线上环境的图片请求路径前缀为测试库路径,图片资源无法显示。

问题原因:因为在启动项目时才将属性写入 env 文件,而项目文件是在项目打包生成的,打包时 env 文件中并没有这些写入的属性,所以项目启动时自然访问的是默认的值。

解决方案:将修改 env 文件的时间提前到打包之前,提前将属性写入 env 文件即可。

6、Post 请求变为 Get 请求

问题说明:在 asyncData 中发出的 Post 请求被强制改为 Get 请求,导致请求中传递的参数失效,导致页面渲染错误

问题原因

  • 在 axios 发出的请求中 baseURL(请求前缀链接)为 http 开头(而不是 https 开头)
  • nginx 收到 post 请求
  • 返回 301 状态码,并指定新的访问连接,且该连接就是原连接+/
  • 发送方收到 301 状态码,将请求方式改为 get,并请求新连接
  • 服务收到 get 请求,body 参数全部失效

解决方案

✔ 将 axios 发出的请求的 baseURL 改为 https 开头(可以在后端打包页面进行配置)

?nginx 转发配置文件中将 301 状态码改为 307 或 308(未实践,不确定)

7、部分报错导致整个页面崩溃问题

问题说明:当页面组件中的 asyncData 中有一个模块出现错误时,Nuxt 捕获到该错误并停止进行后续的代码运行,直接返回默认的错误页面,之前成功处理好的数据也不会被返回进行模板渲染,导致页面所有模块都无法展现,无法交互。

问题原因:Nuxt框架不会主动将错误信息返回,只会提示500并返回报错页面

解决方案:可以在layout文件夹下配置自定义的500页面,但整个页面崩溃问题目前基于Nuxt2还是不能得到很好解决。目前Nuxt3版本已发布,后续升级框架时可以关注一下

8、页面 server error 的排查

问题说明:当页面组件中的 asyncData 出错时,页面会直接报错 500,但报错中没有具体信息提示是哪里出了问题或是哪个接口出现问题。

问题原因:Nuxt框架不会主动将错误信息返回,只会提示500并返回报错页面

解决方案:本地的问题联调时会直接在页面中显示,其他的问题可以在node_modules/@nuxt/server/dist/server.js文件里的errorMiddleware方法中打印_error参数,但也比较笼统,并不是特别精细。我看到server.js文件中Nuxt会将这些报错在服务端调接口上传,但具体上传链接还未查明。

9、本地调试缓慢

问题说明:本地调试时,接口加载缓慢,经常要等几分钟才能等到一个接口的返回(但apifox上就比较快)。且前端开发时有一些逻辑代码修改后,通常需要刷新两遍才能在本地项目中出现,非常影响联调效率。

问题原因:暂无

解决方案:暂无

这个问题目前不知道原因,可能和网络情况也有关系,或者是联调时前/后端同学的电脑设置出了什么问题?有知道的大佬行个方便在评论区踢踢我。

以上的这些问题都是在进行Nuxt开发时出现的各种各样的坑,熬了不少时间才找到解决方案,但是这些问题的具体原因啥的其实我也并不清楚,只是有一个入门的理解,如果有大佬了解的话希望有机会一起探讨下,踩坑实在是太难受了。如果大家有遇到过其他Nuxt框架上的问题,欢迎发出来我们一起看!