Nuxt4 网站配置
Nuxt 的配置散落在三个地方:nuxt.config.ts、app.config.ts、runtimeConfig,新手最容易糊涂的就是「这个值到底该写哪」。
综合对比
三个文件职责不同,先用一句话区分:
nuxt.config.ts管「项目怎么搭、怎么跑」(模块、渲染模式、全局样式、head 等构建配置)。app.config.ts管「部署后基本不变的展示数据」(站点名、主题色、功能开关)。runtimeConfig管「会随环境变、或要保密」的值(密钥、接口地址),写在nuxt.config.ts的runtimeConfig字段里。
下面这张表覆盖更细的维度:
| 维度 | nuxt.config | app.config | runtimeConfig |
|---|---|---|---|
| 写在哪 | nuxt.config.ts |
app.config.ts |
nuxt.config.ts 的 runtimeConfig 字段 |
| 何时确定 | 构建 + 运行 | 构建时打包进产物 | 运行时,可被 .env 覆盖 |
| 能用环境变量改吗 | 部分模块配置可以 | 不能,改了要重新构建 | 能 |
| 适合放什么 | 模块、渲染模式、全局样式、head、各模块参数 | 站点名、主题色等固定展示数据 | API 密钥、会随环境变的接口地址 |
| 怎么读 | 直接写配置项 | useAppConfig() |
useRuntimeConfig() |
拿不准时,按这三步判断:
- 是「项目怎么搭、怎么跑」的开关吗(模块、SSR、全局样式、head)?→
nuxt.config.ts。 - 是「全局共享、部署后基本不变」的展示数据吗(站点名、主题色、功能开关)?→
app.config.ts。 - 是「随环境变化、或不能写进代码库」的敏感 / 可变值吗(密钥、不同环境的 API 地址)?→
runtimeConfig,私密放顶层,前端也要用的放public下。
这里有一个常见疑问:head 为什么写在 nuxt.config 而不是 app.config
初学者常以为「站点名、标题」该统一放进 app.config.ts,但 head 相关配置(页面 <title>、<meta>、<link>)只能写在 nuxt.config.ts 的 app.head 里,原因有两点:
- Nuxt 只认
nuxt.config.ts的app.head来生成 HTML 的<head>。 这是框架约定的机制,构建时 Nuxt 读取它往每个页面注入标题、描述、图标等标签。 app.config.ts只是你自己的全局数据,Nuxt 不会自动拿它填 head。 它导出的对象只有你在组件里主动useAppConfig()读取才有意义(比如页脚显示站点名),并没有「head」这个约定字段,写进去浏览器也不会生成任何<head>标签。
文章里出现两次 title 容易混淆,注意区分:
nuxt.config.ts的app.head.title是真正生成的页面<title>(进 SEO、进浏览器标签)。app.config.ts的title只是你存着在组件里展示用的数据,例如{{ appConfig.title }}渲染到页脚,跟 HTML head 无关。
nuxt.config.ts 常用配置
nuxt.config.ts 是整个项目的配置中枢,所有 Nuxt 配置都写在这个根目录文件里,以下是新手最常用的几个配置项:
// nuxt.config.ts
export default defineNuxtConfig({
// 渲染模式,默认 SSR,设为 false 则纯客户端渲染(SPA)
ssr: true,
// 模块,按需添加,比如 @pinia/nuxt、@nuxt/content
modules: ['@pinia/nuxt'],
// 全局样式,项目里直接可用
css: ['~/assets/css/main.css'],
// 开发工具,浏览器里查看组件树与状态
devtools: { enabled: true },
// 兼容性日期,控制新特性的默认开启范围
compatibilityDate: '2024-10-01',
// 全局 head 配置(页面里用 useHead / useSeoMeta 覆盖,见 SEO 篇)
app: {
head: {
// <html> 标签上的属性,比如语言
htmlAttrs: { lang: 'zh-CN' },
// %s 会被页面自身标题替换,例如页面标题「关于」→ 浏览器标签显示「关于 | 在线工具」
titleTemplate: '%s | 在线工具',
title: '在线工具',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ name: 'theme-color', content: '#2563eb' },
{ name: 'description', content: '网站描述' }
],
// 站点图标,文件放在 public/ 下,用根路径 / 引用
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
// 内联脚本:在 <head> 里首屏渲染前执行,避免暗色模式闪烁
script: [
{
innerHTML:
"(function(){try{var t=localStorage.getItem('theme');var d=t?t==='dark':window.matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.classList.toggle('dark',d);}catch(e){}})();",
tagPosition: 'head'
}
]
}
},
// 构建引擎 Nitro 的配置,比如部署预设
nitro: {
preset: 'node-server'
}
})
上面的 app.head 里每个字段都是真实会写进 HTML <head> 的,逐个说明:
htmlAttrs给<html>标签加属性,这里加了lang="zh-CN",对 SEO 和无障碍都有好处。title是整站的兜底标题,页面没单独设置时会用它。titleTemplate用%s占位,页面自己的标题会填进去,比如某页标题是「关于」,浏览器标签最终显示「关于 | 在线工具」。这样既能统一品牌后缀,又不用每页手写。meta数组里放<meta>标签:charset声明编码、viewport控制移动端缩放、theme-color设置浏览器地址栏颜色、description是给搜索引擎看的站点描述(具体每页的描述在 SEO 篇用useSeoMeta设置)。link数组放<link>标签,这里引用站点图标favicon.ico,文件要放在public/目录下,用根路径/引用(静态资源的用法见静态资源篇)。script数组可以内联或外链脚本,这里用innerHTML内联一段暗色模式初始化代码,并用tagPosition: 'head'让它在<head>里首屏渲染前执行,避免刷新时白底闪一下。
页面内部还可用 useHead / useSeoMeta 覆盖或追加这些配置(见 SEO 篇),nuxt.config 里写的是全站默认值。
除了上面这些,还有 imports(自动导入)、components(组件注册)、dirs(目录别名)、devServer(开发服务器端口)等配置项,需要时可以查阅 Nuxt 配置文档,配置改动后需要重启开发服务器(npm run dev)才会生效。
app.config 与 useAppConfig
app.config.ts 用于存放纯静态的全局数据,比如站点名称、主题色、功能开关。它和 runtimeConfig 的区别见上面的表:构建时确定、不能用环境变量覆盖、改了要重新构建。
// app.config.ts
export default defineAppConfig({
title: '我的网站',
themeColor: '#3b82f6',
features: {
comment: true
}
})
在任意组件里用 useAppConfig 读取,它是响应式的,也支持类型推导:
<script setup>
const appConfig = useAppConfig()
</script>
<template>
<p>{{ appConfig.title }}</p>
</template>
runtimeConfig 与环境变量
敏感信息和环境相关的配置不要硬编码在代码里,用 runtimeConfig:
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
// 服务端专用,不会暴露给浏览器
apiSecret: '超级秘密',
// public 前缀下的内容客户端也能访问
public: {
apiBase: 'https://api.example.com'
}
}
})
代码中通过 useRuntimeConfig 读取:
// 服务端代码(server/api/ 下)
const config = useRuntimeConfig()
console.log(config.apiSecret) // 服务端可用
// 客户端代码
const config = useRuntimeConfig()
console.log(config.public.apiBase) // 客户端读 public 部分
不同环境(本地、线上)用 .env 文件注入,规则是运行时配置名转大写加前缀:
# .env
NUXT_API_SECRET=生产环境的秘密
NUXT_PUBLIC_API_BASE=https://prod-api.example.com
runtimeConfig 中的值只是默认值,同名的环境变量会覆盖它。.env 文件在开发环境自动加载,生产环境通常在部署平台设置,不要提交到 git 仓库。
runtimeConfig 是运行时配置,改值不用重新构建,且敏感值不会暴露给浏览器。