引入@vinejs/vine遇CommonJS与ES模块兼容问题求助
问题背景
现有一个包含20个业务文件的Node.js+TypeScript项目,通过yarn add @vinejs/vine安装校验库后,引入时触发模块兼容错误。在package.json中添加"type": "module"后初始错误消失,但修改所有文件扩展名后,启动server.ts又出现新的加载错误,即使移除业务逻辑、使用import语法也无法解决。
错误信息
初始引入错误
The current file is a CommonJS module whose imports will produce 'require' calls; however, the referenced file is an ECMAScript module and cannot be imported with 'require'. Consider writing a dynamic 'import("@vinejs/vine")' call instead.
To convert this file to an ECMAScript module, change its file extension to '.mts', or add the field"type": "module"to 'c:/Users/xxxx/Desktop/xxx/backend/package.json'.ts(1479)
修改后启动错误
Error: Must use import to load ES Module: C:\Users\rambo\Desktop\psm-solution\backend\src\server.ts
现有配置
package.json
{ "name": "app", "version": "1.0.0", "description": "", "main": "server.ts", "scripts": { "start": "ts-node-dev ./src/server.ts --watch", "start:prod": "yarn run build && node ./dist/src/server.js", "build": "rimraf ./build && tsc" }, "keywords": [], "type": "module", "author": "", "license": "ISC", .... }
tsconfig.json
{ "compilerOptions": { "lib": [ "ESNext" /* ESNext includes new Level-4 features that were recently added to the ECMA-262 JS spec */ ], "module": "NodeNext",/* (1 of 2) TS v4.7 settings you need to change */ "moduleResolution": "NodeNext", /* This is the one that will specifically solve the error you're getting. Without the internal changes made by this, your project will not resolve modules correctly. */ "esModuleInterop": true, /* This is properly configured. FYI you cannot change this, it must be set to true. */ /* THE REST OF THE SETTINGS DO NOT AFFECT THE MODULE TYPE OR HOW TSC RESOLVES OTHER MODULES */ "allowJs": true, "target": "ES2021", "rootDir": "src", "outDir": "build", "forceConsistentCasingInFileNames": true }, "include": [ "src/**/*" ] }
server.ts
import * as Sentry from '@sentry/node'; import express from 'express'; import { ProfilingIntegration } from '@sentry/profiling-node'; import helmet from 'helmet'; import { errorHandler } from './middleware/errorHandler.js'; import { rateLimiter } from './rateLimit/rateLimit.js'; import { createClient } from '@supabase/supabase-js'; import { Database } from './config/database.types.js'; import { router_auth } from './routes/auth/auth.js'; import { verifyJWT } from './middleware/verifyJWT.js'; const app = express(); app.listen(3000, () => { console.log('SERVER LISTEN ON PORT 3000'); });
解决方案
1. 调整ts-node-dev启动脚本
ts-node-dev需要明确启用ES模块加载器,修改package.json中的start命令:
"start": "ts-node-dev --loader ts-node/esm ./src/server.ts --watch"
添加--loader ts-node/esm参数,让工具以ES模块模式解析TypeScript文件。
2. 移除模块引用的.js后缀
TypeScript编译时会自动处理文件扩展名,无需在TS文件中手动添加.js。修改server.ts及所有业务文件中的引用:
// 修改前 import { errorHandler } from './middleware/errorHandler.js'; // 修改后 import { errorHandler } from './middleware/errorHandler';
3. 保持模块配置一致性
保留package.json中的"type": "module",以及tsconfig.json中的"module": "NodeNext"和"moduleResolution": "NodeNext",确保TypeScript编译输出符合ES模块规范。
4. 验证生产构建流程
运行yarn build后,检查build目录下的输出文件是否使用import语法,再执行yarn start:prod确认生产环境启动正常。
核心原因说明
- 当package.json设置
"type": "module"后,Node.js会将所有.js文件视为ES模块,但TypeScript源文件是.ts格式,需要ts-node-dev通过专属加载器才能正确解析。 - 在TS文件中添加.js后缀会导致Node.js在加载时找不到对应文件,因为编译后的JS文件路径会由TypeScript自动生成。
内容的提问来源于stack exchange,提问作者lambdamaster

