一些关于Nuxt框架需要注意的问题
将Thalamus重构成Nuxt的需要注意的点
- 在 Nuxt.js 中,大部分代码都会在服务器端和客户端都执行,但有一些特定的生命周期钩子只会在客户端执行。以下是一些常见的 Vue.js 生命周期钩子和它们在 Nuxt.js 中的行为:
beforeCreate和created:这两个钩子在服务器端和客户端都会执行。beforeMount和mounted:这两个钩子只会在客户端执行。因此,你可以在这两个钩子中安全地使用window、document和其他只存在于浏览器环境的全局对象。beforeDestroy和destroyed:这两个钩子只会在客户端执行。beforeUpdate和updated:这两个钩子只会在客户端执行。
此外,Nuxt.js 还提供了两个特殊的方法,它们在服务器端渲染时会被调用:
asyncData:这个方法在服务器端和客户端都会被调用。它用于在渲染组件之前获取数据。fetch:这个方法在服务器端和客户端都会被调用。它用于填充 Vuex 存储。
因此,如果你的代码需要使用 window、document 或其他只存在于浏览器环境的全局对象,你应该将它们放在 mounted、beforeMount、beforeDestroy、destroyed、beforeUpdate 或 updated 这些钩子中。
- 在 Nuxt.js 中,服务器端渲染(SSR)是默认启用的,所以你不需要做额外的配置。但是,你需要确保你的代码在服务器端和客户端都能正确运行。以下是一些优化你的 Nuxt.js 应用程序的建议:
-
避免在服务器端使用客户端特定的对象:例如
window或document。你可以在使用这些对象之前检查它们是否存在,或者将这些代码移动到客户端特定的生命周期钩子中,如mounted。 -
优化数据获取:在 Nuxt.js 中,你可以在
asyncData或fetch方法中获取数据。这些方法在服务器端渲染时会被调用,你可以在这里获取你的页面需要的数据。 -
使用 Vuex 来管理状态:Vuex 可以帮助你在服务器端和客户端之间共享状态。你可以在
nuxtServerInit动作中获取服务器端的状态。 -
优化静态资源:你可以使用 Nuxt.js 的
head方法来优化你的静态资源,例如添加预加载和预获取链接。
以下是一个使用 asyncData 获取数据的例子:
export default {
async asyncData({ params }) {
const res = await fetch(`https://api.example.com/data/${params.id}`);
const data = await res.json();
return { data };
},
}
在这个例子中,asyncData 方法在服务器端渲染时会被调用,获取的数据会被合并到组件的数据中。
- 迁移到服务器端渲染(Server Side Rendering,SSR)可以带来以下好处:
-
更好的搜索引擎优化(SEO):搜索引擎可以更好地索引服务器渲染的页面,因为服务器会返回完整的页面内容。这对于需要搜索引擎优化的应用(如博客、电商网站等)非常重要。
-
更快的首屏加载时间:服务器渲染的页面在浏览器接收到第一个 HTML 响应后就可以开始渲染,而不需要等待所有的 JavaScript 都下载和执行完毕。这可以使用户更快地看到页面内容。
-
更好的性能:在服务器上预渲染页面可以减少浏览器的工作量,特别是对于性能较差的设备和网络环境,这可以带来更好的用户体验。
-
更好的社交分享预览:许多社交平台(如 Facebook、Twitter)在显示链接预览时,会抓取页面的 HTML。如果是客户端渲染的页面,可能无法正确显示预览。
然而,服务器端渲染也有一些缺点,例如开发复杂性增加、服务器负载增加等。因此,是否使用服务器端渲染,需要根据具体的项目需求和团队能力来决定.
-
nuxt生产环境报错:Failed to execute 'appendChild' on 'Node': This node type does not support this method...
初次用nuxt,发现它的坑还真不少,一个坑能坑你很久,这里我给大家做一个汇总
今天在打包测试环境的时候发现启动项目,浏览器里报标题所示的错误,乍一看,不知所措,就开始找原因,你会发现,在本地开发的时候同样也有报错

这里还给你列出了出问题的父级和子级元素,看起来还挺人性化,然后找到自己错误所在的问题,挨个儿去注释代码,发现代码执行到v-if语句所在的html块的时候就会出现这个错误,后来我把该页面所有用到v-if的地方都换成了v-show,结果不报错,打包测试环境也一切正常~~
个人针对问题感觉虽然好了,但是丈二的和尚摸不着头脑,不知道为什么会这样,并且我其他页面也有定义v-if,它就可以正常执行,但是我发现一个现象,就是出错的部分是在layouts模板文件中引入的,而不是动态渲染nuxt部分,所以可以猜测应该是模板中的除了动态渲染的部分以外,其余都得用v-show所控制的css样式去让它显示隐藏,而不能用v-if,应该是模板内不支持动态生成元素方法,就如报错的appendChild
还有一种现象就是在服务端打包后在线上访问一个页面,第一次打开正常,第二次刷新也会报这个错误,于是我看官方有解决方法,链接如下:
https://nuxtjs.org/docs/features/nuxt-components/#the-client-only-component
在引入组件的地方,根据nuxt版本去加上no-srr或者client-only即可
If you are using a version of Nuxt < v2.9.0, use
<no-ssr>instead of<client-only>
遇到的问题:
build之后start遇到的问题:
- 初始进入页面正常,一刷新,swiper的样式就没了,所有幻灯片排在一行,解决办法:把swiper包在client-only标签中, 但是箭头和pagination这些不要包进去,就可以解决问题
- 使用v-if会出问题,报错:Failed to execute 'appendChild' on 'Node': This node type does not support this method. 这个时候把所有出现v-if的地方都换成v-show就可以了,因为v-if实际上就是在动态创建元素
- 在template中判断数组的length时会出问题,比如初始传入一个组件给它一个空数组,然后在模板中判断空数组的length是否为0,这个时候会报错Can not read undefined of Length,解决办法:在判断数组长度之前, 先判断一下数组是否存在即可,比如 list && list.length !== 0 这样,先判断list是否存在即可
- 出现window和document的地方要用if(process.client)包起来,不然服务端和客户端不一致也会报错,即使是在mounted和destroyed这些生命周期中使用也要包起来,不然服务器和客户端解析的组件html不一致也会报错导致页面无法运行
一般问题:
- 无需写路由文件,直接放到pages文件夹里就行,nuxt自动生成路由,路由的名字就是文件的名字,注意大小写
- store的写法和过去也有区别,具体见项目,无需导入vuex
- 使用插件plugins的时候,需要放到一个js文件中,然后在nuxt.config.js中进行配置,具体见文件
- 比如说一个img标签使用了vuex中的一个图片,当vuex的图片更新的时候这个img标签显示的确实旧的图片,解决办法:用client-only包裹住这个img标签即可