NextJS中__dirname解析为node_modules路径而非调用方路径如何解决
根因分析
- Node.js 原生规范中
__dirname代表当前代码所属模块文件的所在目录,和调用方无关。你用到的第三方库的设计逻辑是默认自身代码会和调用方代码打包到同一个文件,从而继承调用方的__dirname,但Next.js默认的打包规则没有满足这个前提。 - 你之前配置不生效是因为Webpack5 中
__dirname的配置值不再是简单的布尔值,可选值为true/false/'verbose',同时Next.js默认会把第三方依赖标记为服务端externals,不会打包进业务输出文件,所以库的代码还是独立加载,__dirname自然指向它自己在node_modules中的路径。
解决方案
分两种优先级选择:
优先选择:用
patch-package修改第三方库逻辑,成本最低,兼容性最好- 安装patch-package:
npm i patch-package -D - 手动修改
./node_modules/check_api/lib/index.js的校验逻辑,改成通过调用栈获取调用方路径:
const path = require('path') function checkCurrentFile(){ // 解析调用栈拿到调用方的文件路径 const stackLine = new Error().stack.split('\n')[2] const callerFilePath = stackLine.match(/\((.*):\d+:\d+\)/)[1] const callerDir = path.dirname(callerFilePath) if (!callerDir.endsWith("/api")) { throw new Error("Not api directory"); } }- 执行
npx patch-package check_api生成补丁,后续安装依赖会自动应用修改。 - 调用时不需要改任何代码即可正常运行。
- 安装patch-package:
次选方案:调整Next.js Webpack配置让库代码内联打包
修改next.config.js为以下内容:module.exports = { reactStrictMode: true, webpack: (config, { isServer }) => { if (isServer) { // 配置服务端打包的__dirname规则,true为输出文件相对路径 config.node = { ...config.node, __dirname: true, } // 排除check_api库的external规则,强制打包进业务代码 config.externals = config.externals.map(external => { if (typeof external !== 'function') return external return async ({ context, request, getResolve }) => { if (request === 'check_api') return // 不标记为external return external({ context, request, getResolve }) } }) } return config } }修改后重启服务即可生效,打包后库的代码会和API路由代码合并为同一个文件,
__dirname会自动指向API路由文件所在的目录。
内容的提问来源于stack exchange,提问作者Freddx L.
相关产品推荐
相关产品推荐

