Skip to content

常用模块

为什么要用模块而不是手动配置?

手动集成第三方库通常需要:安装依赖、修改构建配置、注册插件/组件、配置自动导入等,步骤繁琐且容易遗漏。模块把这些封装成一行配置,还能确保与 Nuxt 的 SSR、自动导入等特性正确配合。

模块选择指南

需求场景推荐模块说明
样式系统TailwindCSS原子化 CSS,开发效率高
状态管理PiniaVue 官方推荐,TypeScript 友好
图片优化@nuxt/image自动格式转换、懒加载、CDN 适配
内容管理@nuxt/content基于 Markdown 的 CMS
国际化@nuxtjs/i18n路由级多语言支持
UI 组件库@nuxt/ui官方出品,110+ 组件
图标@nuxt/icon20 万+ 图标,按需加载
SEO@nuxtjs/sitemap + @nuxtjs/robots站点地图和爬虫控制
认证@sidebase/nuxt-auth本地/ OAuth 认证方案
字体@nuxt/fonts自动优化字体加载

TailwindCSS

为什么用它?

手动配置 Tailwind 需要修改 postcss 配置、创建 tailwind.config.ts、配置内容路径等。模块一键完成,还自动扫描 Nuxt 组件路径。

bash
npm install -D @nuxtjs/tailwindcss
ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/tailwindcss'],
})

安装后在项目根目录创建 tailwind.config.ts

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 Config

Pinia

为什么用它?

Vue 3 官方推荐的状态管理方案。模块自动注册 Pinia、提供 useStore 组合式函数的自动导入、SSR 兼容性处理。

bash
npm install @pinia/nuxt pinia
ts
export default defineNuxtConfig({
  modules: ['@pinia/nuxt'],
})

定义 Store

ts
// 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 }
})

在组件中使用

vue
<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,大幅减少图片体积。

bash
npm install @nuxt/image
ts
export default defineNuxtConfig({
  modules: ['@nuxt/image'],
  image: {
    quality: 80,
    formats: ['webp'],
    domains: ['cdn.example.com'],
  },
})

实际使用

vue
<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 中声明外部图片域名,否则图片无法加载。这是安全策略,防止被用作开放代理

始终设置 widthheight

这能防止布局偏移(CLS),是 Core Web Vitals 的重要指标。


Nuxt Content

为什么用它?

需要博客、文档站、知识库等基于 Markdown 的内容站点时,Content 模块提供文件系统驱动的 CMS,无需数据库。

bash
npm install @nuxt/content
ts
export default defineNuxtConfig({
  modules: ['@nuxt/content'],
})

内容文件

将 Markdown 文件放在 content/ 目录下:

markdown
<!-- content/blog/my-first-post.md -->
---
title: 我的第一篇博客
date: 2025-01-01
---

# 你好世界

这是我的第一篇博客文章。

渲染内容

vue
<!-- 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

为什么用它?

自动发现项目中的字体引用、优化字体加载(预加载、格式转换)、避免布局偏移。手动配置字体加载既繁琐又容易遗漏。

bash
npm install @nuxt/fonts
ts
export default defineNuxtConfig({
  modules: ['@nuxt/fonts'],
  fonts: {
    families: [
      { name: 'Inter', provider: 'google' },
    ],
  },
})

在 CSS 中直接使用即可,模块自动处理加载优化:

css
body {
  font-family: 'Inter', sans-serif;
}

Nuxt Icon

为什么用它?

内置 20 万+ 图标(Iconify),按需加载,不需要手动下载 SVG 文件或安装图标字体包。

bash
npm install @nuxt/icon
vue
<template>
  <Icon name="mdi:home" />
  <Icon name="carbon:logo-github" size="24" />
</template>

TIP

图标名格式为 集合名:图标名 可在 Icônes 搜索可用图标


Nuxt UI

为什么用它?

官方出品的完整组件库,基于 TailwindCSS 和 Reka UI(无头组件库),提供 110+ 组件。适合不想自己搭组件体系的项目,开箱即用。

bash
npm install @nuxt/ui
ts
export default defineNuxtConfig({
  modules: ['@nuxt/ui'],
})
vue
<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 标签)、懒加载语言包等。模块自动处理这些。

bash
npm install @nuxtjs/i18n
ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: ['zh', 'en'],
    defaultLocale: 'zh',
    lazy: true,
    langDir: 'locales',  // 翻译文件目录
  },
})

INFO

️ **最佳实践:使用独立翻译文件 ** 不要把翻译内容写在 nuxt.config.ts 中(配置文件示例仅为演示),应使用 locales/ 目录存放 JSON/YAML 文件,并开启 lazy: true 按需加载

json
// locales/zh.json
{
  "hello": "你好",
  "welcome": "欢迎来到 {name}"
}
json
// locales/en.json
{
  "hello": "Hello",
  "welcome": "Welcome to {name}"
}
vue
<template>
  <p>{{ $t('hello') }}</p>
  <p>{{ $t('welcome', { name: 'Nuxt' }) }}</p>
</template>

Nuxt Sitemap

为什么用它?

搜索引擎爬虫需要站点地图来发现你的页面。手动维护 sitemap.xml 容易遗漏新页面,模块自动从路由生成。

bash
npm install @nuxtjs/sitemap
ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/sitemap'],
  site: {
    url: 'https://example.com',
  },
})

Nuxt Robots

bash
npm install @nuxtjs/robots
ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/robots'],
  robots: {
    UserAgent: '*',
    Allow: '/',
    Disallow: ['/admin/', '/api/'],
  },
})

Sitemap + Robots 通常一起使用

前者告诉搜索引擎有哪些页面,后者告诉它哪些不能访问。


Nuxt Auth

为什么用它?

认证涉及登录/登出、Token 管理、路由守卫、SSR Cookie 传递等复杂逻辑。模块把这些统一封装,避免手写时遗漏安全细节。

bash
npm install @sidebase/nuxt-auth
ts
export 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' },
      },
    },
  },
})

在组件中使用

vue
<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.tsmodules 包含该模块
外部图片加载失败未在 @nuxt/image 中配置 domainsimage.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

基于 Nuxt 4 官方文档整理编写