常用模块
为什么要用模块而不是手动配置?
手动集成第三方库通常需要:安装依赖、修改构建配置、注册插件/组件、配置自动导入等,步骤繁琐且容易遗漏。模块把这些封装成一行配置,还能确保与 Nuxt 的 SSR、自动导入等特性正确配合。
模块选择指南
| 需求场景 | 推荐模块 | 说明 |
|---|---|---|
| 样式系统 | TailwindCSS | 原子化 CSS,开发效率高 |
| 状态管理 | Pinia | Vue 官方推荐,TypeScript 友好 |
| 图片优化 | @nuxt/image | 自动格式转换、懒加载、CDN 适配 |
| 内容管理 | @nuxt/content | 基于 Markdown 的 CMS |
| 国际化 | @nuxtjs/i18n | 路由级多语言支持 |
| UI 组件库 | @nuxt/ui | 官方出品,110+ 组件 |
| 图标 | @nuxt/icon | 20 万+ 图标,按需加载 |
| SEO | @nuxtjs/sitemap + @nuxtjs/robots | 站点地图和爬虫控制 |
| 认证 | @sidebase/nuxt-auth | 本地/ OAuth 认证方案 |
| 字体 | @nuxt/fonts | 自动优化字体加载 |
TailwindCSS
为什么用它?
手动配置 Tailwind 需要修改 postcss 配置、创建 tailwind.config.ts、配置内容路径等。模块一键完成,还自动扫描 Nuxt 组件路径。
npm install -D @nuxtjs/tailwindcssexport default defineNuxtConfig({
modules: ['@nuxtjs/tailwindcss'],
})安装后在项目根目录创建 tailwind.config.ts:
import type { Config } from 'tailwindcss'
export default {
content: [
'./app/components/**/*.{js,vue,ts}',
'./app/layouts/**/*.vue',
'./app/pages/**/*.vue',
'./app/app.vue',
],
theme: {
extend: {},
},
} satisfies ConfigPinia
为什么用它?
Vue 3 官方推荐的状态管理方案。模块自动注册 Pinia、提供 useStore 组合式函数的自动导入、SSR 兼容性处理。
npm install @pinia/nuxt piniaexport default defineNuxtConfig({
modules: ['@pinia/nuxt'],
})定义 Store
// stores/user.ts
export const useUserStore = defineStore('user', () => {
const user = ref<{ name: string; email: string } | null>(null)
const isLoggedIn = computed(() => !!user.value)
function login(userData: { name: string; email: string }) {
user.value = userData
}
function logout() {
user.value = null
}
return { user, isLoggedIn, login, logout }
})在组件中使用
<script setup>
const userStore = useUserStore()
// 响应式访问
console.log(userStore.isLoggedIn)
// 调用方法
userStore.login({ name: 'Alice', email: 'alice@example.com' })
</script>推荐使用 Setup Store 语法
(如上所示),相比 Options Store 更灵活,TypeScript 类型推导更好。
Nuxt Image
为什么用它?
原生 <img> 标签没有懒加载、格式转换、响应式尺寸适配。<NuxtImg> 自动处理这些,还能对接图片 CDN,大幅减少图片体积。
npm install @nuxt/imageexport default defineNuxtConfig({
modules: ['@nuxt/image'],
image: {
quality: 80,
formats: ['webp'],
domains: ['cdn.example.com'],
},
})实际使用
<template>
<!-- 自动转换为 WebP 格式 -->
<NuxtImg src="/photo.jpg" format="webp" width="600" height="400" alt="描述" />
<!-- 外部图片需要配置 domains -->
<NuxtImg src="https://cdn.example.com/photo.jpg" width="800" alt="描述" />
<!-- 响应式图片 -->
<NuxtImg src="/hero.jpg" widths="400 800 1200" sizes="sm:100vw md:50vw" alt="描述" />
<!-- 懒加载(默认开启) -->
<NuxtImg src="/below-fold.jpg" loading="lazy" alt="描述" />
</template>INFO
️ **常见错误:外部图片 404 ** 必须在 image.domains 中声明外部图片域名,否则图片无法加载。这是安全策略,防止被用作开放代理
始终设置 width 和 height
这能防止布局偏移(CLS),是 Core Web Vitals 的重要指标。
Nuxt Content
为什么用它?
需要博客、文档站、知识库等基于 Markdown 的内容站点时,Content 模块提供文件系统驱动的 CMS,无需数据库。
npm install @nuxt/contentexport default defineNuxtConfig({
modules: ['@nuxt/content'],
})内容文件
将 Markdown 文件放在 content/ 目录下:
<!-- content/blog/my-first-post.md -->
---
title: 我的第一篇博客
date: 2025-01-01
---
# 你好世界
这是我的第一篇博客文章。渲染内容
<!-- app/pages/blog/[slug].vue -->
<script setup>
const route = useRoute()
const { data: post } = await useAsyncData(`blog-${route.params.slug}`, () =>
queryContent(`/blog/${route.params.slug}`).findOne()
)
</script>
<template>
<div v-if="post">
<h1>{{ post.title }}</h1>
<ContentRenderer :value="post" />
</div>
</template>Nuxt Fonts
为什么用它?
自动发现项目中的字体引用、优化字体加载(预加载、格式转换)、避免布局偏移。手动配置字体加载既繁琐又容易遗漏。
npm install @nuxt/fontsexport default defineNuxtConfig({
modules: ['@nuxt/fonts'],
fonts: {
families: [
{ name: 'Inter', provider: 'google' },
],
},
})在 CSS 中直接使用即可,模块自动处理加载优化:
body {
font-family: 'Inter', sans-serif;
}Nuxt Icon
为什么用它?
内置 20 万+ 图标(Iconify),按需加载,不需要手动下载 SVG 文件或安装图标字体包。
npm install @nuxt/icon<template>
<Icon name="mdi:home" />
<Icon name="carbon:logo-github" size="24" />
</template>TIP
图标名格式为 集合名:图标名 可在 Icônes 搜索可用图标
Nuxt UI
为什么用它?
官方出品的完整组件库,基于 TailwindCSS 和 Reka UI(无头组件库),提供 110+ 组件。适合不想自己搭组件体系的项目,开箱即用。
npm install @nuxt/uiexport default defineNuxtConfig({
modules: ['@nuxt/ui'],
})<template>
<UButton label="点击我" />
<UInput v-model="name" placeholder="请输入" />
<UModal v-model="open">弹窗内容</UModal>
</template>TIP
Nuxt UI 适合快速搭建管理后台、SaaS 应用等 如果你需要高度自定义的 UI,可以只使用 TailwindCSS + 无头组件库(如 Headless UI、Radix Vue)
Nuxt I18n
为什么用它?
多语言不仅是翻译文字,还涉及路由策略(/zh/about vs /en/about)、SEO(hreflang 标签)、懒加载语言包等。模块自动处理这些。
npm install @nuxtjs/i18nexport default defineNuxtConfig({
modules: ['@nuxtjs/i18n'],
i18n: {
locales: ['zh', 'en'],
defaultLocale: 'zh',
lazy: true,
langDir: 'locales', // 翻译文件目录
},
})INFO
️ **最佳实践:使用独立翻译文件 ** 不要把翻译内容写在 nuxt.config.ts 中(配置文件示例仅为演示),应使用 locales/ 目录存放 JSON/YAML 文件,并开启 lazy: true 按需加载
// locales/zh.json
{
"hello": "你好",
"welcome": "欢迎来到 {name}"
}// locales/en.json
{
"hello": "Hello",
"welcome": "Welcome to {name}"
}<template>
<p>{{ $t('hello') }}</p>
<p>{{ $t('welcome', { name: 'Nuxt' }) }}</p>
</template>Nuxt Sitemap
为什么用它?
搜索引擎爬虫需要站点地图来发现你的页面。手动维护 sitemap.xml 容易遗漏新页面,模块自动从路由生成。
npm install @nuxtjs/sitemapexport default defineNuxtConfig({
modules: ['@nuxtjs/sitemap'],
site: {
url: 'https://example.com',
},
})Nuxt Robots
npm install @nuxtjs/robotsexport default defineNuxtConfig({
modules: ['@nuxtjs/robots'],
robots: {
UserAgent: '*',
Allow: '/',
Disallow: ['/admin/', '/api/'],
},
})Sitemap + Robots 通常一起使用
前者告诉搜索引擎有哪些页面,后者告诉它哪些不能访问。
Nuxt Auth
为什么用它?
认证涉及登录/登出、Token 管理、路由守卫、SSR Cookie 传递等复杂逻辑。模块把这些统一封装,避免手写时遗漏安全细节。
npm install @sidebase/nuxt-authexport default defineNuxtConfig({
modules: ['@sidebase/nuxt-auth'],
auth: {
provider: {
type: 'local',
endpoints: {
signIn: { path: '/api/auth/login', method: 'post' },
signOut: { path: '/api/auth/logout', method: 'post' },
signUp: { path: '/api/auth/register', method: 'post' },
},
},
},
})在组件中使用
<script setup>
const { signIn, signOut, status, data } = useAuth()
// status: 'unauthenticated' | 'authenticated' | 'loading'
// data: 用户信息对象
</script>
<template>
<div v-if="status === 'authenticated'">
<p>欢迎, {{ data?.user?.name }}</p>
<UButton @click="signOut()">退出</UButton>
</div>
<UButton v-else @click="signIn()">登录</UButton>
</template>常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 模块安装后不生效 | 只 npm install 但没加到 modules 数组 | 确认 nuxt.config.ts 中 modules 包含该模块 |
| 外部图片加载失败 | 未在 @nuxt/image 中配置 domains | 在 image.domains 中添加图片域名 |
| I18n 路由策略导致 SEO 问题 | 默认 prefix_except_default 策略 | 根据项目选择合适的 strategy,参考官方文档 |
| Pinia store 在 SSR 中状态串扰 | 直接用 ref 而非 useState | 在 Store 中使用 useState 或确保每次请求创建新实例 |
| Nuxt Icon 图标不显示 | 图标名拼写错误或集合未安装 | 在 Icônes 确认图标名 |
快速安装模块的命令
npx nuxi module add <模块名> 会自动安装依赖并添加到 modules 配置,例如 npx nuxi module add tailwindcss。