Nuxt3通过API获取的SEO元数据分享社交媒体不显示问题
问题:Nuxt3博客分享至社交媒体时动态元数据不生效
我基于Nuxt3搭建了博客平台,所有博客内容及对应的SEO元数据均通过API接口响应渲染。目前遇到的问题是:将博客链接分享至社交媒体时,仅能显示app.vue文件中声明的静态元数据,API返回的动态元数据无法正常展示;但在浏览器开发者工具的元素审查面板中,可以查看到所有需要的元数据标签。
相关代码
pages/blog/[slug].vue
<script setup> import { onMounted, ref, defineProps } from 'vue'; import { useBlogStore } from '~/stores/blog'; import config from '~/app.config.ts' const route = useRoute() const blogStore = useBlogStore(); // Create an instance of the blog store const blog = ref([]); const { currentRoute } = useRouter(); onMounted(async () => { try { await blogStore.getBlog(route.params.slug); // Call the getBlogs action blog.value = blogStore.$state.blog; // Update the local ref with the fetched data } catch (error) { console.log(error); } useHead({ title: blog.value.title, meta: [ { name: 'description', content: blog.value.meta_description }, { name: 'keywords', content: blog.value.keywords }, { name: 'og:image', content: blog.value.image_url }, { name: 'og:title', content: blog.value.title }, { name: 'og:description', content: blog.value.meta_description }, { name: 'og:type', content: 'article' }, { name: 'og:url', content: config.web.baseURL + currentRoute.value.fullPath }, { name: 'twitter:card', content: 'summary_large_image' }, { name: 'twitter:url', content: config.web.baseURL + currentRoute.value.fullPath }, { name: 'twitter:title', content: blog.value.title }, { name: 'twitter:description', content: blog.value.meta_description }, { name: 'twitter:image', content: blog.value.image_url }, ], }) }); </script>
app.vue
<script setup> definePageMeta({ colorMode: 'dark', }) useHead({ title: 'My Title', meta: [ { name: 'description', content: 'Nuxt app meta description for SEO!' }, { name: 'theme-color', content: '#000000' }, ], }) </script>
原因分析
社交媒体爬虫只会抓取服务器渲染的初始HTML内容,不会执行客户端JavaScript代码。你将useHead放在onMounted钩子中,这是客户端页面挂载后才会执行的逻辑,爬虫无法获取这部分动态生成的元数据,因此只会读取app.vue中的静态元数据。
解决方案
1. 改用服务端预获取数据的钩子
在Nuxt3中,使用useAsyncData在服务器端预获取博客数据,确保元数据在服务器渲染阶段就已生成,爬虫能直接读取。
修改pages/blog/[slug].vue代码如下:
<script setup> import { useBlogStore } from '~/stores/blog'; import config from '~/app.config.ts' const route = useRoute() const blogStore = useBlogStore(); const { currentRoute } = useRouter(); // 服务端预获取博客数据 const { data: blog } = await useAsyncData('blog', async () => { await blogStore.getBlog(route.params.slug); return blogStore.$state.blog; }); // 直接在setup中调用useHead,无需放在onMounted useHead({ title: blog.value?.title || '默认博客标题', meta: [ { name: 'description', content: blog.value?.meta_description || '默认博客描述' }, { name: 'keywords', content: blog.value?.keywords || '' }, // OG标签规范使用property属性而非name { property: 'og:image', content: blog.value?.image_url || '' }, { property: 'og:title', content: blog.value?.title || '默认博客标题' }, { property: 'og:description', content: blog.value?.meta_description || '默认博客描述' }, { property: 'og:type', content: 'article' }, { property: 'og:url', content: config.web.baseURL + currentRoute.value.fullPath }, { name: 'twitter:card', content: 'summary_large_image' }, { name: 'twitter:url', content: config.web.baseURL + currentRoute.value.fullPath }, { name: 'twitter:title', content: blog.value?.title || '默认博客标题' }, { name: 'twitter:description', content: blog.value?.meta_description || '默认博客描述' }, { name: 'twitter:image', content: blog.value?.image_url || '' }, ], }) </script>
2. 修正OG标签属性名
遵循Open Graph规范,OG标签应使用property属性而非name,否则部分社交媒体平台可能无法识别标签内容。
3. 添加默认值兜底
为所有元数据字段添加默认值,避免数据获取失败时元数据为空,保证页面基础SEO表现。
4. 验证服务器渲染结果
部署后,可通过curl命令直接请求页面,查看返回的HTML是否包含动态生成的元数据:
curl https://你的博客域名/blog/具体文章slug
若返回的HTML中能看到对应博客的标题、描述等元数据,说明配置生效。
内容的提问来源于stack exchange,提问作者Sourav Dutt
相关产品推荐
相关产品推荐

