1. 文件上傳
// server/api/upload.post.ts
export default defineEventHandler(async (event) => {
const files = await readMultipartFormData(event)
if (!files || files.length === 0) {
throw createError({ statusCode: 400, message: 'No file uploaded' })
}
const file = files[0]
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp']
if (!allowedTypes.includes(file.type || '')) {
throw createError({ statusCode: 400, message: 'Invalid file type' })
}
if (file.data.length > 5 * 1024 * 1024) {
throw createError({ statusCode: 400, message: 'File too large (max 5MB)' })
}
const filename = `${Date.now()}-${file.filename}`
// NuxtHub Blob (Cloudflare R2)
const blob = await hubBlob().put(filename, file.data, {
contentType: file.type,
})
return { url: blob.pathname }
})
2.@nuxt/圖片
<template>
<!-- Basic -->
<NuxtImg
src="/images/hero.jpg"
alt="Hero"
width="800"
height="400"
loading="lazy"
format="webp"
/>
<!-- Responsive sizes -->
<NuxtImg
src="/images/banner.jpg"
sizes="sm:100vw md:50vw lg:400px"
quality="80"
placeholder
/>
<!-- Picture element with multiple formats -->
<NuxtPicture
src="/images/photo.jpg"
format="avif,webp"
sizes="sm:100vw md:50vw"
quality="80"
/>
</template>
3. 使用 useSeoMeta 進行 SEO
<script setup lang="ts">
// Static SEO
useSeoMeta({
title: 'Trang chủ | xDev',
ogTitle: 'xDev - Nền tảng học lập trình',
description: 'Học lập trình miễn phí với các khóa học chất lượng',
ogDescription: 'Học lập trình miễn phí',
ogImage: '/images/og-default.jpg',
twitterCard: 'summary_large_image',
})
</script>
<!-- Dynamic SEO -->
<script setup lang="ts">
const { data: post } = await useFetch(`/api/posts/${slug}`)
useSeoMeta({
title: () => post.value?.title,
ogTitle: () => post.value?.title,
description: () => post.value?.description,
ogImage: () => post.value?.image,
ogType: 'article',
articlePublishedTime: () => post.value?.createdAt,
})
// useHead for full control
useHead({
script: [
{
type: 'application/ld+json',
textContent: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.value?.title,
image: post.value?.image,
datePublished: post.value?.createdAt,
}),
},
],
})
</script>
4. 網站地圖生成
npx nuxi module add @nuxtjs/sitemap
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/sitemap'],
sitemap: {
sources: ['/api/__sitemap__/urls'],
},
site: {
url: 'https://blog.xdev.asia',
},
})
// server/api/__sitemap__/urls.ts
export default defineSitemapEventHandler(async () => {
const posts = await db.select({ slug: schema.posts.slug, updatedAt: schema.posts.updatedAt })
.from(schema.posts)
.where(eq(schema.posts.published, true))
return posts.map(post => ({
loc: `/blog/${post.slug}`,
lastmod: post.updatedAt,
priority: 0.7,
}))
})
下一篇: 實時、WebSocket 和 i18n — 即時互動與多語言。