我正在尝试使用 Nuxt 3 构建一个静态站点,我希望该站点 100% 静态,无需任何 API 调用。
为了实现这一目标,我创建了我的
nuxt.config.ts
文件,如下所示。
// only showing relevant configs
export default defineNuxtConfig({
target: 'static',
ssr: true,
hooks: {
async 'nitro:config'(nitroConfig) {
if (!nitroConfig || nitroConfig.dev) {
return
}
const token = process.env.STORYBLOK_API_TOKEN;
let cache_version = 0
// other routes that are not in Storyblok with their slug.
let routes = ['/'] // adds home directly but with / instead of /home
try {
const result = await fetch(`https://api-us.storyblok.com/v2/cdn/spaces/me?token=${token}`)
if (!result.ok) {
throw new Error('Could not fetch Storyblok data')
}
// timestamp of latest publish
const space = await result.json()
cache_version = space.space.version
// Recursively fetch all routes and set them to the routes array
await fetchStories(routes, cache_version)
// Adds the routes to the prerenderer
nitroConfig.prerender.routes.push(...routes)
} catch (error) {
console.error(error)
}
},
},
})
async function fetchStories(routes: string[], cacheVersion: number, page: number = 1) {
const token = process.env.STORYBLOK_API_TOKEN
const version = 'published'
const perPage = 100
try {
const response = await fetch(
`https://api-us.storyblok.com/v2/cdn/links?token=${token}&version=${version}&per_page=${perPage}&page=${page}&cv=${cacheVersion}`,
)
const data = await response.json()
const toIgnore = ['home']
// Add routes to the array
Object.values(data.links).forEach(link => {
if (!toIgnore.includes(link.slug)) {
routes.push('/' + link.slug)
}
})
// Check if there are more pages with links
const total = response.headers.get('total')
const maxPage = Math.ceil(total / perPage)
if (maxPage > page) {
await fetchStories(routes, cacheVersion, ++page)
}
} catch (error) {
console.error(error)
}
}
我在 Netlify 上的构建状态是
npm run generate
,发布目录为 dist
。
在我的组件中,我只使用
useAsyncStoryblok
const resp = await useAsyncStoryblok(`home`, {
version: "draft",
resolve_relations: 'FeaturedProjects.projects',
});
projects = resp?.value?.content?.body[0]['projects']
当我这样做时
npm run generate && npm run preview
每次第一次加载任何数据时,都会调用我不想要的 API。虽然第一次获取后没有 API 调用,但我正在尝试实现 0 API 调用来获取内容。
我正在努力实现以下目标。
.html
文件应具有所有静态数据,以实现更好的 SEO。我还担心如果 api 不断被调用,我的 API 请求限制就会达到。
我在这里做错了什么?
如果你想确保你的 Nuxt 3 静态站点是真正静态的,并且在运行时不会进行任何 API 调用,你需要避免在客户端使用动态数据获取方法,如 useAsyncStoryblok。
以下是一些帮助您实现目标的建议:
1-静态内容生成: 确保您正确使用 Nuxt 3 的静态站点生成 (SSG)。这可确保您的页面在构建阶段进行预渲染,并且生成的 HTML 文件应包含所有必要的数据。
确保您的
nuxt.config.js
已配置为 SSG:
export default {
ssg: true,
// Other Nuxt config options...
}
此外,请确保在构建过程中获取数据的组件/页面正在使用
fetch
或 asyncData
。
2-避免客户端数据获取: 如果您在组件中使用
useAsyncStoryblok
或任何其他动态数据获取方法,它可能会在客户端水合作用期间进行 API 调用。为了避免这种情况,您应该仅在构建过程中有条件地获取数据。
使用
asyncData
的示例:
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script setup>
export default {
async asyncData({ params }) {
// Fetch data during build
const response = await fetchData(params.id);
return { title: response.title };
}
}
</script>
3-在构建期间检查 API 调用: 在构建过程中,您可以检查是否正在进行API调用。使用
nuxt generate
命令并监视输出是否有任何意外的 API 调用。如果发现任何情况,请检查您的组件并确保仅在构建期间获取数据。
4-静态数据导入: 如果您的数据相对静态并且不经常更改,请考虑将数据直接导入到组件中,而不是在运行时获取数据。这样,数据就成为静态构建的一部分。
示例:
<script setup>
import myData from '~/static/data/myData.json';
export default {
data() {
return {
title: myData.title,
// Other data...
};
}
}
</script>
通过遵循这些建议,您应该能够创建一个 Nuxt 3 静态站点,该站点在运行时不进行任何 API 调用,并且在构建阶段预渲染所有必要的数据。