Nuxt 3 最佳实践与常见问题

最近比较忙,也有些犯懒,所以博客视频都没怎么更新。今天一看,竟然断更将尽一个月,那无论如何得攒点东西。就把前阶段的笔记贴出来吧,是我使用 Nuxt3 的一些经验心得,希望对大家有所帮助。

如果大家在使用 Nuxt3 期间有经验可以分享,或者问题需要讨论,欢迎留言。

Nuxt 3 简介

Nuxt.js 是一个基于 Vue.js 的服务端渲染应用框架,可以帮助开发者快速构建出高性能、SEO 友好的 Web 应用。Nuxt.js 3 是该框架的最新版本,它具有更快的启动时间、更快的构建时间和更先进的开箱即用功能。

然而,在使用 Nuxt.js 3 进行项目开发时,我遇到了不少问题。本文会记录这些问题,以及我的经验。

最佳实践

下面是我从之前的问题里找到的最佳实践,应该问题不大,可以照搬。

部署

Nuxt 3 可以直接部署在 Vercel,兼具 SEO 与高用户体验。

Serverless function

默认情况下 Nuxt3 /api 和渲染都走 serverless function,理论上要弱于 Edge Function。我曾试着切换到 Edge Function,服务立刻就挂了,回头找个小服务摸索一下试试看。

目前来看效能还可以,暂时没有体感延迟。我建议大家不要强求,把切换功能留给 Nuxt 核心团队来处理吧。

加载远程数据

SSR

使用 useFetchuseAsyncData,Nuxt 会先加载远程数据,然后渲染页面,再进行页面的跳转。

注意:SSR 阶段,组件发出的请求不会携带 cookie,这个设计是有意为之,避免个性化数据错误的出现在缓存层里面。如果希望 SSR 中包含个性化数据,可以手动操作,但请务必小心,不要泄漏不必要的请求头,因为可能带来安全隐患。

具体做法可以参考官方文档:Passing Headers and cookies

先跳转,再加载

使用 useLazyFetchuseLazyAsyncData,Nuxt 不会等待请求完成,它会先渲染页面并跳转,然后在数据加载完成之后,更新视图。

平时加载数据

如果我们要像平时使用 Vue 那样加载数据并渲染,最好使用 $fetch

使用 pendingrefresh 等复用请求代码

比如页面里我们远程加载了一个对象,然后接下来,我们要重新加载这个对象,或者我们要根据某个参数加载别的对象,就可以利用 useFetchuseAsyncData 等返回的 pending 来渲染状态,或者用 refresh 重新发起请求,复用请求代码。

尽量使用 default() 返回默认值

很多时候我们远程加载的数据不是简单对象(文本、数字等),而是某个比较复杂的对象,比如一篇文章、一组人员数据。通常来说组件里的模版就负责渲染这组数据,如果不返回默认值,渲染可能会出错,可能导致页面跳转失败。

所以我建议大家尽量返回默认值。

配置 routes

Nuxt 默认会对每个页面进行服务器端渲染,但很多时候我们并不需要,比如各种后台页面。所以我建议项目起始阶段就把各页面的渲染策略制定好。

参考文档:Rendering Modes · Nuxt Concepts对首页、关于我们之类的纯静态页面,可以启用预渲染(preredering);对后台页面,就禁用 ssr;等。

但是,大家也要小心错误的缓存机制,可能会把不应该缓存的页面缓存下来,造成渲染出错。

使用 localStorage

我们知道,Nuxt3 最大的特性就是 SSR,它会在服务器端渲染完页面,再返回给客户端。而 localStorage 顾名思义,只存在于用户本地,服务器端并不知道它的存在,也无法使用。所以如果我们要像平时那样使用 localStorage,我们必须控制好只在用户本地使用。如果要在 Nuxt3 里读取 localStorage 里的数据,我建议在 layout 里进行。经我测试,这是我们最初能插入 JS 的位置。

// <script setup>
import useStore from '~/store';

const store = useStore();
// 只有在客户端的时候才执行
if (process.client) {
  store.init();
}

已有解,寻求最优解

接下来的问题,我的方案能解决,但我不确定是否是最好的方案。所以我也在寻找更好的做法。

1. useAsyncData 难以打断点

问题

useAsyncData 会在服务器端执行,所以在 Devtools 里打断点可能拦截不到。

解法

我目前的解法是在里面插入 console.log() ,利用热更新,切换页面,让断点生效。

2. onBeforeMount 读取 localStorage 会丢失响应式

版本

v3.4(新版本待测试)

问题

非常诡异。

我有一个变量 myRate ,因为一些理由,所以要把数据存在 localStorage 。我们知道 nuxt 在服务器端渲染的时候没有 window 对象,所以我就把它放在 onBeforeMount 。

但是这样就会导致 myRate 丢失响应式,且只在 input className 丢失,非常诡异。

解决

我暂时放在 onMounted,虽然会造成页面抖动,但是工作正常。

问题

页面中有一个 nuxt-link 生成的 <a> ,点击无效,没有报错,浏览器和开发环境均无报错。

解决

实际上是 Vue 模版中某个变量名拼错了,渲染失败。但是不知道为何没有错误信息。找到并修正后,使用正常。

暂时无解

使用 route.hash 加载数据的话,SSR 会缺少数据

当我们请求包含 hash 的地址,route.hash 在服务器端可能为空,导致无法正常启动服务器端渲染。请求会在渲染后再发出,造成界面抖动 CLS。

解决方案就是不要用 hash 作为数据标记。

@nuxtjs/i18n no_prefix 策略下,无法 SSR

版本

Nuxt@3.5 + @nuxtjs/i18n@8.0.0-beta.12

问题

  1. 使用 no_prefix 策略
  2. detectBrowserLanguage: false
  3. 没有 SSR,渲染出来的是 key,然后变成目标语言

Tips

GET 请求里不能包含 body,否则可能 405

如果用 useFetch 发起的 GET 请求包含 body/server/api 的接口会报告 405 Method Not Allowed 错误。

这个问题主要不好排查。


总结

开始用 Nuxt 的时候,我没想到会有这么多问题:不就是提前渲染一下模版嘛,能麻烦到哪儿去?实际操作之后,发现很多熟悉的操作都不好处理,比如从 localStorage 里面取数据然后渲染到页面去,就要区分函数执行环境,否则就会报错;要渲染用户相关数据,得考虑服务器运行环境的复杂性,包括网络和多层缓存,不能想当然的使用 cookie 与 token。

总之,心怀敬畏,持续学习,多看文档。有问题,欢迎提问;有建议,欢迎指教。大家一起进步。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

来自

标签:

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据