Nuxt 配置实践:nuxt.config 文件、defineNuxtConfig 辅助函数与配置加载管线解析
Nuxt 用一个根目录下的 nuxt.config 文件承载整个应用的配置,是官方文档中"目录结构"板块的核心组成部分。本文以该配置文件为主题,从文件扩展名与 defineNuxtConfig 辅助函数讲起,梳理最常用的配置项与默认值,并结合当前仓库的源码,深入剖析 loadNuxtConfig 配置加载管线、schema 默认值填充与"配置变更触发全量重启"的机制。读完后,你既能写出可运行的 nuxt.config.ts,也能理解配置在 Nuxt 内部的真实流转路径。
1. nuxt.config 文件:扩展名与基本形态
nuxt.config 文件的扩展名可以是 .js、.ts 或 .mjs,文件放置于项目根目录(rootDir)。最小化示例如下:
export default defineNuxtConfig({
// My Nuxt config
})
defineNuxtConfig 辅助函数全局可用,无需导入——这是官方文档明确给出的提示。如果你希望代码更显式,也可以从 nuxt/config 显式导入:
import { defineNuxtConfig } from 'nuxt/config'
export default defineNuxtConfig({
// My Nuxt config
})
源码视角:defineNuxtConfig 到底做了什么
在 nuxt/config 入口 中,它的实现只有三行:
function defineNuxtConfig (config) {
return config
}
export { defineNuxtConfig }
也就是说,defineNuxtConfig 本质上是一个恒等函数,它的价值在于:为编辑器提供 NuxtConfig 类型的智能提示、以及保证返回值类型不被 Object.assign、条件展开等操作"污染"。其 TypeScript 契约定义在 NuxtConfigInput / DefineNuxtConfig:
export type NuxtConfigInput<Config extends Record<string, any> = NuxtConfig> = Config & {
$test?: Config
$development?: Config
$production?: Config
$env?: Record<string, Config>
$meta?: NuxtConfigLayerMeta
}
export interface DefineNuxtConfig<Config extends Record<string, any> = NuxtConfig> {
(input: NuxtConfigInput<Config>): NuxtConfigInput<Config>
}
从类型定义可以看出,配置对象除了常规字段外,还支持 $development / $production / $test 三种运行环境的整体覆写,以及 $env 按环境名选择覆写层——这解释了为什么 nuxi 支持 --envName 参数来选择不同的配置分支。
仓库里的真实示例
当前仓库根目录的 nuxt.config.ts 展示了更完整的用法:内联模块函数(function (_options, nuxt) { ... } 接收 nuxt 实例直接修改 nuxt.options)、pages 按环境变量启停、dir.app 重定向应用目录、vite.define 注入编译期常量、typescript.hoist 配置等:
export default defineNuxtConfig({
modules: [
function (_options, nuxt) {
nuxt.options.optimization.treeShake.composables.client ||= {}
// ...
},
],
pages: process.env.DOCS_TYPECHECK === 'true',
dir: { app: fileURLToPath(new URL('./test/runtime/app', import.meta.url)) },
})
而 playground/nuxt.config.ts 则是最简形态:
export default defineNuxtConfig({
devtools: { enabled: true },
compatibilityDate: '2025-07-15',
})
其中 compatibilityDate 用于固定 Nitro、Nuxt Image 等模块预设的行为基线,避免在不升级大版本的情况下行为漂移。
2. 配置变更与全量重启
官方文档对开发体验有一条重要约定:
为了确保配置保持最新,当检测到主配置文件、
.env、.nuxtignore或.nuxtrc这些点文件发生变更时,Nuxt 会执行一次全量重启(full restart)。
这三个点文件分别对应仓库中的 .env 文档、.nuxtignore 文档 和 .nuxtrc 文档。其底层支撑可以从源码中找到两条证据线:
-
配置文件身份可追踪:加载管线会把解析到的配置文件路径写入内部字段
_nuxtConfigFile/_nuxtConfigFiles(见 loadNuxtConfig 中的赋值 与 内部默认值定义),工具链据此知道"监控哪个文件"。 -
配置快照可对比:加载器提供
onConfigResolved回调,暴露跨所有层合并后、未应用 schema 默认值的rawConfig快照,并配套 diffNuxtConfig 函数(基于microdiff逐路径对比),供自行监控配置文件的外部工具(如测试框架、IDE)精确判断"哪个 key 变了、值从什么变成什么",从而决定是重启还是热更。
export function diffNuxtConfig (oldConfig: NuxtConfig, newConfig: NuxtConfig): NuxtConfigDiffEntry[] {
// 基于 microdiff(oldConfig, newConfig) 输出 added / removed / changed 三类差异
}
3. 常用配置项速览(类型、默认值与示例)
nuxt.config 的完整字段清单见 Nuxt Configuration API 参考(该文档覆盖全部选项,此处只精选高频项并给出类型与默认值)。
3.1 应用基础:app、srcDir、rootDir、ssr
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
app.baseURL |
string |
"/" |
应用基础路径,可用 NUXT_APP_BASE_URL 运行时覆写 |
app.cdnURL |
string |
"" |
生产环境静态资源 CDN 地址 |
app.head |
object |
含 viewport/charset 的 meta | 所有页面 <head> 默认值 |
srcDir |
string |
"app"(Nuxt 4) |
源码目录,相对 rootDir |
rootDir |
string |
项目根目录 | 一般无需手动设置,nuxt ./my-app/ 可覆写 |
ssr |
boolean |
true |
是否渲染 HTML,false 时为纯 SPA |
app.baseURL 支持环境变量运行时覆写:
NUXT_APP_BASE_URL=/prefix/ node .output/server/index.mjs
注意一个已知限制:受 Nitro 限制,baseURL 不支持 ./ 相对路径直接写在 nuxt.config.ts 中,相对路径需通过构建期环境变量或 Nitro runtimeConfig 的 app.baseURL 间接实现。
3.2 路径别名:alias
alias 允许为自定义目录定义 JS/CSS 访问别名。默认别名(从 API 参考 继承):
{
"~": "/<rootDir>/app",
"@": "/<rootDir>/app",
"~~": "/<rootDir>",
"@@": "/<rootDir>",
"#shared": "/<rootDir>/shared",
"#server": "/<rootDir>/server",
"assets": "/<rootDir>/app/assets",
"public": "/<rootDir>/public",
"#build": "/<rootDir>/.nuxt",
"#internal/nuxt/paths": "/<rootDir>/.nuxt/paths.mjs"
}
import { fileURLToPath } from 'node:url'
export default defineNuxtConfig({
alias: {
'images': fileURLToPath(new URL('./assets/images', import.meta.url)),
'style': fileURLToPath(new URL('./assets/style', import.meta.url)),
'data': fileURLToPath(new URL('./assets/data', import.meta.url)),
},
})
两点注意:在 CSS/图片等非 JS 上下文中访问别名必须加 ~ 前缀(如 url('~images/main-bg.jpg'));这些别名会自动写入生成的 .nuxt/tsconfig.app.json 等文件,因此天然获得类型提示与路径补全。
3.3 目录结构:dir 与 modulesDir
dir 用于自定义 Nuxt 的默认目录约定(不建议随意改动):
| 字段 | 默认值 | 用途 |
|---|---|---|
dir.app |
"app" |
应用目录 |
dir.assets |
"app/assets" |
资源目录(别名 ~assets) |
dir.layouts |
"app/layouts" |
布局目录,自动注册布局 |
dir.middleware |
"app/middleware" |
中间件目录,自动注册 |
dir.modules |
"modules" |
模块目录,自动注册 |
dir.pages |
"app/pages" |
页面目录,自动生成路由 |
dir.plugins |
"app/plugins" |
插件目录,自动注册 |
dir.public |
"public" |
静态文件目录 |
dir.shared |
"shared" |
前后端共享目录 |
modulesDir 则指定模块解析用的 node_modules 位置,默认 ["/<rootDir>/node_modules"],monorepo 场景可指向 workspace 根:
export default defineNuxtConfig({
modulesDir: ['../../node_modules'],
})
3.4 服务端:runtimeConfig 与 serverDir
runtimeConfig 是向 Nuxt 上下文传递动态配置与环境变量的通道,核心规则(继承自 API 参考):
- 默认仅在服务端可通过
useRuntimeConfig访问,适合存放 API 密钥等私密配置; public与app两个命名空间下的值会暴露到前端;- 值会被匹配的环境变量自动覆写,规则是
NUXT_前缀 + 大写键名。
export default defineNuxtConfig({
runtimeConfig: {
apiKey: '', // 运行时由 NUXT_API_KEY 覆写
public: {
baseURL: '', // 同时暴露给前端,由 NUXT_PUBLIC_BASE_URL 覆写
},
},
})
NUXT_API_KEY=my-api-key NUXT_PUBLIC_BASE_URL=/foo/ node .output/server/index.mjs
serverDir 定义 Nitro 路由/中间件/插件所在目录,默认 "/<rootDir>/server"。serverHandlers 用于显式注册 Nitro 服务端处理器:
export default defineNuxtConfig({
serverHandlers: [
{ route: '/path/foo/**:name', handler: '#server/foohandler.ts' },
],
})
3.5 构建器:builder 与 server.builder
客户端打包器可选 'vite' | 'webpack' | 'rspack',默认 "@nuxt/vite-builder"。使用 webpack 或 rspack 需显式安装对应的 @nuxt/webpack-builder / @nuxt/rspack-builder 包。也可以传入自定义对象:
export default defineNuxtConfig({
builder: 'rspack',
// 或自定义实现
// builder: { async bundle (nuxt) { /* 自行构建 client/server bundle */ } },
})
服务端打包器由 server.builder 控制,默认 "@nuxt/nitro-server"(即独立的 Nitro 集成),也可选择实验性的 "vite"(即 @nuxt/vite-server,纯 Vite 实现,ssr: false 时产出静态 SPA,但服务端路由、route rules 与预渲染不可用)。官方文档明确标注该选项面向内部使用、API 未定型。
3.6 模块、插件与自动导入:modules、plugins、imports
modules 是 Nuxt 的扩展机制,每一项可以是:包名字符串、~~/ 起始的本地路径、[模块, 选项] 元组或内联函数。模块按数组顺序串行执行,顺序很重要;nuxt.config.ts 中声明的模块先加载,随后 modules/ 目录中的模块按字母序加载:
export default defineNuxtConfig({
modules: [
'@nuxt/scripts', // 包名
'~~/custom-modules/awesome.js', // 相对 rootDir 的本地模块
['@nuxtjs/google-analytics', { ua: 'X1234567' }], // 带选项
function () {}, // 内联模块
],
})
plugins 是应用插件数组,以 .client / .server 结尾的文件名自动限定加载上下文:
export default defineNuxtConfig({
plugins: [
'~/custom-plugins/foo.client.js', // 仅客户端
'~/custom-plugins/bar.server.js', // 仅服务端
{ src: '~/custom-plugins/client-only.js', mode: 'client' },
],
})
注意:~/plugins 目录中的插件会自动注册,无需在此列出,除非你要定制加载顺序;所有插件按 src 路径去重。
imports 控制 composable 自动导入,imports.dirs 追加自定义目录(不覆盖默认的 ~/composables、~/utils),imports.scan 可关闭目录扫描:
export default defineNuxtConfig({
imports: { dirs: ['stores'] }, // 自动导入 ~/stores 下的 pinia store
})
3.7 其余高频选项
css:全局 CSS 数组,如['bulma', '~/assets/css/main.scss'],Nuxt 按扩展名推断预处理器;router.options:透传给vue-router(仅限 JSON 可序列化选项,更复杂的定制用router.options.ts文件);其中hashMode: true开启 hash 路由(SPA 下 URL 不发往服务器、不支持 SSR);sourcemap:{ server: true, client: false }为默认,'hidden'表示生成 sourcemap 但不写入最终 bundle 引用;buildDir:默认"/<rootDir>/.nuxt",若隐藏目录对某些工具不友好可改为nuxt-build之类;typescript:strict(默认true)、shim(默认false,官方更推荐 Vue 官方扩展生成.vue精确类型)、typeCheck(true时开发期也做类型检查,需要typescript+vue-tsc作为 devDependencies)、hoist(pnpm monorepo 下生成深别名的模块列表)等;watch/watchers:watch定义触发 dev server 重启的文件模式(字符串相对srcDir,正则相对srcDir匹配);watchers.chokidar透传 chokidar 选项(默认ignoreInitial: true);compatibilityDate:指定兼容性日期,控制 Nitro、Nuxt Image 等预设行为,避免大版本内的静默行为变化;devServer:port(默认3000)、https(提供 key/cert 对象启用 HTTPS)、cors等;spaLoadingTemplate:ssr: false时注入的加载模板,未设置时查找~/spa-loading-template.html,false关闭。
完整选项(含 optimization.treeShake 的默认树摇清单、vite.$client/$server 分环境配置、unhead.legacy 等)请以 docs/4.api/6.nuxt-config.md 为准。
4. 配置加载管线:loadNuxtConfig 源码深读
配置从磁盘到 nuxt.options 的全过程由 loadNuxtConfig 完成,这条管线值得开发者了解,因为模块作者与自定义工具都会与之交互。
4.1 加载入口与 c12
核心调用是 loadConfig(来自 c12):
loadConfig<NuxtConfig>({
name: 'nuxt',
configFile: configFileName, // 默认 'nuxt.config'
rcFile: opts.rcFile ?? '.nuxtrc', // 附带读取的 rc 文件
extend: { extendKey: ['theme', '_extends', 'extends'] },
globalRc: opts.globalRc ?? true, // 同时读取用户级/workspace 级 .nuxtrc
merger, // 定制 defu:数组键做拼接而非覆盖
...
})
这里有两个与文档直接呼应的实现细节:
.nuxtrc是一等公民:rcFile默认为.nuxtrc,且globalRc: true意味着还会加载用户级与 workspace 级的 rc 文件——这解释了为什么文档把.nuxtrc与主配置文件、.env并列为"变更需全量重启"的文件;- 数组型配置是拼接语义:自定义
merger基于createDefu,遇到双方都是数组的键(如plugins、modules)时执行concat,这使得 layers 之间的数组配置可以叠加而非互相覆盖。
扩展键包含 theme、_extends 与 extends 三者。extends 的值可以是本地目录/配置路径,也可以是 github: / gh: / gitlab: / bitbucket: / https: 远程源;源码中 assertRemoteLayerSupport 会在远程源缺少 giget 下载器时提前报错,并提示优先把层以 git URL 形式写入 package.json(可锁定版本、进入 lockfile)。
4.2 环境变量先行、本地层自动扫描
在解析任何配置之前,管线先执行 setupDotenv 把 .env 注入 process.env("populate process.env before the schema imports its env-based defaults")——这是 .env 变更必须重启的机制性原因:schema 默认值本身可能依赖环境变量。
同时,管线自动 glob layers/* 目录并注入 _extends(见 L243-L249),本地层按目录名逆序扫描;若根配置在 extends 中显式列出了某些本地层,reorderLocalLayersByExtends 会按声明顺序重排优先级(首个 = 最高),未声明者保持字母序在后。重复出现的层目录会去重,避免同一层被合并两次。
4.3 配置文件导入:原生 ESM 优先,jiti 兜底
配置文件导入策略(importConfigFile)是:
- 用运行时原生
import()导入,并在 URL 上附加递增计数器(?_=N)以绕过模块缓存,保证 dev 下重复加载能读到最新文件; - 若原生导入失败(如 CJS 全局缺失、特定 loader 错误),回退到 jiti 重新导入;若项目缺少
jiti依赖,会输出带安装命令的结构化诊断(NUXT_B5017/NUXT_B5021),而不是让用户面对裸的ERR_MODULE_NOT_FOUND; - 对同一批 layers,一旦确认某配置文件需要 jiti 才能加载,后续层直接走 jiti,省去重复的失败导入。
这也解释了文档为何说扩展名支持 .js / .ts / .mjs:TS 配置文件走的正是 jiti 路径(或运行时自带的 TS 支持),且该管线支持自定义 import 选项以便测试/工具链提供自己的加载器。
4.4 schema 默认值填充与内部字段
加载末尾,管线通过 applyDefaults(NuxtConfigSchema, nuxtConfig) 将用户配置叠加到 NuxtConfigSchema(由 packages/schema 导出,内部默认值定义在 config/internal.ts)之上,得到最终 nuxt.options。此前还会补上 rootDir、_nuxtConfigFile、alias(含 #layers/<name> 层别名)、typesDir 等内部字段。值得注意的一个默认行为:非 dev 模式下若根目录已存在 .nuxt,构建会改用 node_modules/.cache/nuxt/.nuxt 作为 buildDir,避免污染已存在的类型目录。
加载完成后,若提供了 onConfigResolved,会回调 rawConfig(仅用户层合并结果、未含默认值与 overrides)快照与 layers 列表——这正是第 2 节所述重启判断的基础设施。
5. 端到端示例:一份可复制的 nuxt.config.ts
综合以上内容,一份贴近实战的配置如下(默认值与字段说明均可在 docs/4.api/6.nuxt-config.md 中逐一查证):
// nuxt.config.ts
import { fileURLToPath } from 'node:url'
export default defineNuxtConfig({
compatibilityDate: 'latest',
devtools: { enabled: true },
srcDir: 'app/',
app: {
baseURL: '/',
head: {
meta: [{ name: 'viewport', content: 'width=device-width, initial-scale=1' }],
},
},
alias: {
images: fileURLToPath(new URL('./assets/images', import.meta.url)),
},
css: ['~/assets/css/main.css'],
modules: ['~/modules/feature-a.js', ['@nuxtjs/google-analytics', { ua: 'UA-xxx' }]],
plugins: ['~/plugins/analytics.client.js'],
runtimeConfig: {
apiKey: '', // 私密:服务端可见,NUXT_API_KEY 覆写
public: { siteUrl: '' }, // 公开:NUXT_PUBLIC_SITE_URL 覆写
},
watch: ['shared/**/*.ts'],
typescript: { strict: true },
})
6. 小结
nuxt.config(.js/.ts/.mjs)是 Nuxt 的唯一配置入口;defineNuxtConfig是全局可用的恒等辅助函数,核心作用是类型提示,支持$development/$production/$test/$env环境覆写;- 修改主配置文件、
.env、.nuxtignore、.nuxtrc会触发 Nuxt 全量重启;底层由_nuxtConfigFile追踪与diffNuxtConfig快照对比机制支撑; - 加载管线 = c12 多源合并(含
.nuxtrc与extends/theme层)+ dotenv 先行注入 + ESM/jiti 双通道导入 +NuxtConfigSchema默认值填充,全部集中在 packages/kit/src/loader/config.ts; - 全部字段的类型、默认值与示例以 Nuxt Configuration API 参考 为准,配置文件自身的说明见 nuxt.config.ts 目录文档。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00