DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Next 相对导入失败

从 monorepo 外部目录启动 Next,SWC 加载 next.config.ts 的相对模块可能按 cwd 解析。核对 Module filename、目标项目目录与正式版本边界。

在项目目录里构建正常,从 monorepo 根目录指定同一个项目却报:

Failed to load next.config.ts
Error: Cannot find module './src/headers'

先比较启动目录与 next.config.ts 所在目录。如果错误来自将配置经 SWC 转成 CommonJS 的加载路径,相对导入可能被错误地按 process.cwd() 解析,而不是按配置文件位置解析。

这个表现已出现在 Next.js 15.5.26 和 16.4.0-canary.63。已核对的正式版 16.4.0 也保留对应的缺失 filename 实现;修正随后合入开发分支,不代表它已经进入这份正式发行包。

找到模块,还可能找到错的模块

配置可能按正常方式导入项目内的常量:

import { headers } from './src/headers'

假设配置在 app/next.config.ts,模块在 app/src/headers.ts。从父目录启动时,错误路径可能变成父目录的 src/headers。那里没有文件,就报找不到;那里恰好有同名文件,则可能构建成功却用了另一份配置。

因此,不能只以构建退出成功验收。还要核对实际解析到的文件和生成配置,例如该模块影响的响应头或路由。不要在父目录复制一份同名文件来让错误消失,这会掩盖错误的解析基准。

本文针对 SWC 配置加载分支。原生 TypeScript 或原生 import() 加载配置的路径不同,不能只看到 next.config.ts 就套用。tsconfig 路径别名不受支持、包 exports 拒绝子路径等问题,也需要按各自规则检查。

Module 的 id 不能代替 filename

对应加载器创建了一个 Node Module,为它设置查找包所需的 paths,再调用 _compile 执行编译后的配置。创建时传入的第一个参数是模块 id,并不会自动变成 filename。

当相对请求的父模块没有 filename,Node 的相关查找路径会退到当前工作目录。设置 paths 可以影响裸包查找,却不能替相对导入补上配置文件的基准。

这也解释了为什么“配置文件已经找到了”仍然不够:找到并编译配置,与配置内部相对模块如何解析,是两个阶段。

在目标项目目录运行已有脚本

暂时没有核定到兼容正式修复时,可以在受控环境中先让启动目录与目标项目根目录一致,保留原来的配置与导入。

例如项目已经定义了调用 next build 的 build 脚本时,可以进入该项目后使用原脚本:

cd /absolute/path/to/existing-project
npm run build

路径是占位值,需要替换为已有项目。构建会执行项目脚本,只应按自己的验收流程运行。还要确认原脚本不会再次切到其他目录,也没有指向另一份配置。

部署集成或长期运行的工具,不能随意对整个进程调用 chdir():其他任务也可能依赖原工作目录。应在所拥有的子进程或任务启动配置中设置目标目录,并核对其余相对路径、环境和输出位置。

若选择后续正式版本,需要检查实际发行包是否设置了配置模块 filename,不能仅依据问题关闭、修正合入或 canary 版本变化判断。直接修改 node_modules 中的内部加载器也不是可持续的发行记录。

验收文件身份与构建结果

保留原先从外部目录启动的场景,对照处理后的实际加载路径,确认来自目标项目的模块。随后检查受该配置影响的真实结果,正常项目脚本与其他配置仍能工作。

这与TypeScript Compiler API 的配置路径位置不同。本篇没有要求给 createProgram 增加配置选项;错误出现在 Next 配置模块的相对导入加载阶段。