Vite 配置文件为何无法引入未转译的 ts 文件

👁 68 次阅读

Vite 配置文件为何无法引入未转译的 ts 文件

来源链接:https://github.com/vitejs/vite/issues/5370

现象描述

在 Vite 项目中,当 vite.config.ts 通过软链接(symlink)引入一个 TypeScript 文件时,启动开发服务器会直接失败,报出与默认加载器相关的类型错误。issue #5370 的提交者给出了完整的错误日志:
failed to load config from /Users/zheeeng/Workspace/foo/bar/baz/vite.config.ts
error when starting dev server:
TypeError: defaultLoader is not a function
    at Object.require.extensions.<computed> [as .ts] (/Users/zheeeng/Workspace/foo/node_modules/.pnpm/vite@2.6.5_less@4.1.2/node_modules/vite/dist/node/chunks/dep-55830a1a.js:68633:13)
    at Module.load (internal/modules/cjs/loader.js:933:32)
    at Function.Module._load (internal/modules/cjs/loader.js:774:14)
    at Module.require (internal/modules/cjs/loader.js:957:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/Users/zheeeng/Workspace/foo/web/studio/vite.config.ts:37:32)
提交者同时给出了两个可行的绕行办法:把 ts 文件编译成 common js 文件,或在配置里直接写被引入文件的真实路径而不是软链接路径。问题在于,这两种方式都不是理想的长期方案。提交者使用的环境为 Node 14.17.0、Yarn 1.22.11、pnpm,Vite 版本为 2.6.5。 复现仓库:https://github.com/zheeeng/test-symlink-vite-config

背景原因

维护者 haoqunjiang 在 2021-10-25 的团队会议讨论后给出了框架层面的解释,核心结论可以归纳为:
  • 找不到高效支持该特性的方式。外部包被 esbuild 作为 external 排除,不会参与打包转译。
  • vite.config.* 使用的外部包大多不需要、也不应该被转译。
  • 这已经是一个配置文件,不希望再引入一个选项来配置加载行为。
也就是说,Vite 在加载 vite.config.ts 时依赖 esbuild 将配置打包成临时文件,而通过软链接引入的 ts 文件在解析路径与加载器匹配上出现了偏差,导致 defaultLoader 无法按预期调用。这一行为并非简单的 bug,而是加载策略与外部依赖处理方式共同作用的结果。 提交者随后询问是否可以增加一个环境变量来控制这一行为,维护者明确回复:环境变量同样属于一种配置,因此不应通过这种方式解决。这一轮讨论基本锁定了框架层不引入新配置项的态度。

排查或量化方法

issue 中出现的报错信息本身提供了定位线索,可以按以下顺序观察:
  • 报错发生在 vite.config.ts 的 require 调用栈中,指向 Object.require.extensions.<computed> [as .ts],说明自定义的 .ts 扩展加载器被触发。
  • 触发点是 dep-55830a1a.js 中的 defaultLoader 调用,栈帧显示该调用处取不到可用的加载器引用,因此抛出 TypeError: defaultLoader is not a function。
  • 路径出现软链接特征:/Users/zheeeng/Workspace/foo/bar/baz/vite.config.ts 与 node_modules/.pnpm 下的实际安装路径不一致。
判断是否命中该问题的量化方式,据 issue 讨论可以简化为:
  • 将配置中的软链接路径替换为真实路径,若错误消失,则问题与软链接解析有关。
  • 将引入的 ts 文件先编译为 common js 文件,若错误消失,则问题与未转译 ts 的加载路径有关。

完整解决方案

issue 在 2025 年出现了新的进展。据 issue 讨论,bluwy 在 2025-01-24 提到: > With Vite 6.1 beta, there’s now a vite --configLoader runner option (experimental) that should make this case work. 随后 nktnet1 在 2025-02-19 补充该能力已进入稳定版,并给出文档位置: > Now in stable release – docs here: > – https://vite.dev/config/#configuring-vite 文档中的相关描述为: > ## CONFIG LOADING > By default, Vite uses esbuild to bundle the config into a temporary file and load it. This may cause issues when importing TypeScript files in a monorepo. If you encounter any issues with this approach, you can specify --configLoader runner to use the module runner. 按 issue 讨论,可行的处理路径为:
vite --configLoader runner
据 issue 讨论,该选项使用 module runner 加载配置,可绕开 esbuild 打包临时文件带来的路径与加载器问题。 需要如实说明的局限:timmypidashev 在 2025-05-08 反馈,使用 --configLoader 时,外部 vite config 的自动重启无法被检测到,并询问这是技术限制还是团队为避免性能开销而做出的取舍。这一点在 issue 中没有得到维护者的明确答复。 issue 当前状态为 open,最后一条实质评论日期为 2025-09-07。dkkb 在该日回复: > With Vite 6.1 beta, there’s now a vite --configLoader runner option (experimental) that should make this case work. > It works ! 同一问题下也有用户反馈仍不可用。mxvsh 在 2025-01-22 提到,使用 tsx/esm/api 的 tsImport 方式(参考 https://tsx.is/dev-api/ts-import)作为绕行方案时遇到报错,并追问是否有人找到解决办法。这说明不同路径的可用性存在分歧,具体效果依环境而异。

参数或对比表格

处理方式来源适用场景局限
编译 ts 为 common jsissue 提交者给出的绕行办法配置引入的 ts 文件可预先编译需要额外的构建步骤
使用真实文件路径替代软链接issue 提交者给出的绕行办法软链接结构可绕开破坏了 monorepo 中的符号链接组织方式
vite --configLoader runner据 issue 讨论,bluwy、nktnet1导入 TypeScript 文件的 monorepo外部 config 自动重启检测存在问题(据 issue 讨论)
tsImport(tsx)据 issue 讨论,mxvsh希望用外部工具加载 ts 配置有用户反馈仍不可用

常见错误排查

  • TypeError: defaultLoader is not a function:这是 issue 中报告的原始错误,出现在通过软链接引入 ts 文件时,栈帧指向 Object.require.extensions.<computed> [as .ts] 与 dep-55830a1a.js。据 issue 讨论,切换 --configLoader runner 可解决该情形。
  • ERR_UNKNOWN_FILE_EXTENSION:himself65 在 2024-12-03 的评论中引用了一段社区反馈,使用 import 动态加载 .ts 文件时报出 TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for <FILEPATH>.ts。该信息来自第三方转述,issue 中未给出根因结论。
  • 自动重启失效:timmypidashev 报告使用 --configLoader 后,外部 vite config 的变更无法被检测到,触发自动重启失效。据 issue 讨论,这一问题尚未有明确答复。
  • tsImport 方案在个别环境下不可用:mxvsh 反馈按 tsx 文档方式使用仍报错,属社区结论的分歧点。
  • 使用软链接路径且未指定加载器:据 issue 提交者的验证,这一组合会稳定复现原始错误。

实践建议

  • 若项目位于 monorepo 且 vite.config.ts 通过软链接引入其它 ts 包,可以优先尝试 --configLoader runner,这是 issue 讨论中被多位参与者确认可用的路径。
  • 若依赖配置文件的自动重启,需要先验证 --configLoader 下外部模块变更的监测是否满足需求,据 issue 讨论这一方面存在已知问题。
  • 在使用任何社区绕行方案(如 tsImport)前,应在当前 Vite 版本上实测,因为 issue 中有用户反馈同一方式仍不可用。
  • 保留“编译为 common js”与“使用真实路径”两种兜底手段,在加载器方案不可用时可快速切回。
  • 由于该 issue 仍为 open,官方尚未合入新的配置项或环境变量,环境变量方案已被维护者明确否定。

FAQ

问:为什么 Vite 不允许在 vite.config.ts 中引入未转译的 ts 文件? 答:据维护者 haoqunjiang 的说明,外部包被 esbuild 作为 external 排除,不做转译;配置文件本身已属配置层,团队不希望再增加用于配置加载方式的选项。 问:可以通过环境变量开启该能力吗? 答:维护者明确回复环境变量同样属于一种配置,因此不应通过环境变量解决。 问:当前有没有官方支持的解决方式? 答:据 issue 讨论,Vite 提供了 vite --configLoader runner 选项,nktnet1 指出该能力已在稳定版提供,文档见 https://vite.dev/config/#configuring-vite。该 issue 本身仍为 open。 问:--configLoader runner 有什么副作用? 答:据 issue 讨论,有用户反馈外部 vite config 的自动重启无法被检测到,维护者尚未就此给出明确答复。 问:issue 是否已经关闭? 答:该 issue 当前状态为 open,最后一条实质评论日期为 2025-09-07,评论中确认 --configLoader runner 可用。

订阅 AI 百事知

每周精选 AI 工具评测、行业资讯与使用教程,第一时间送达。

🔗 相关阅读(你可能还想看)

📄 Outlook 节点创建草稿添加附件为何报 UnableToDeserializePostBody?
📄 Flowise 点击市场或聊天页为何整页白屏?
📄 如何解决 Azure AI Search 向量存储的 $filter 递归深度超限错误?
📄 如何解决 shadcn/ui Sidebar 与 Header 重叠的问题?
📄 Next.js 开发服务器为何会 JavaScript heap out of memory?
📄 Nuxt 偶发 Cannot read properties of undefined 报错是怎么回事
📄 如何解决「Visual Studio Code for ipad」相关的问题?
📄 如何在AutoGen中实现企业级代理治理的加密行动收据(AAR)?
📄 记忆内容未清洗直接注入系统提示词,如何防范间接提示注入?
crewAI LiteAgent 将记忆内容直接拼接到系统提示词,存在间接提示注入风险。社区提出分层防御方案,但 iss
🤖 想直接和 AI 对话?
免费体验 DeepSeek V4 等顶级模型,无需注册,随问随答
🎯 立即体验 AI 工具

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

🤖 嘟嘟客服
滚动至顶部
🤖 嘟嘟客服
🤖 嘟嘟客服
';i.value='';m.innerHTML+='
...
';fetch('/dify-chat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({query:q,user:'w'+Date.now()})}).then(function(r){return r.json()}).then(function(d){var a=d.answer||'暂时无法回复';m.removeChild(m.lastChild);m.innerHTML+='
'+a+'
'}).catch(function(){m.removeChild(m.lastChild);m.innerHTML+='
网络异常
'})">发送