使用ESM模块的.sequelizerc搭配@babel/register及preset-env时Sequelize CLI失效
解决Sequelize CLI迁移时ESM导入与@babel/register兼容问题
问题根源
Sequelize CLI本身运行在CommonJS(CJS)环境中,升级到@babel/register后,它默认不会自动将ES模块(ESM)的import/export语法转换为CJS的require/module.exports,导致加载ESM格式的迁移文件时触发模块加载错误。
解决方案
1. 配置Babel强制转换ESM为CJS
在项目根目录的babel.config.js(或.babelrc)中,给@babel/preset-env添加modules: 'commonjs'选项,强制将所有ESM语法转译为CJS,适配Sequelize CLI的运行环境:
module.exports = { presets: [ ['@babel/preset-env', { targets: { node: 'current' }, modules: 'commonjs' // 关键:把ESM转为CJS }] ] };
2. 修改.sequelizerc的@babel/register配置
确保@babel/register能处理所有需要转换的文件扩展名,包括ESM格式的.js文件(如果项目设置了"type": "module"):
require('@babel/register')({ extensions: ['.js', '.mjs', '.ts'], // 覆盖默认扩展名,确保处理ESM文件 ignore: [/node_modules/], presets: [['@babel/preset-env', { targets: { node: 'current' } }]] }); const path = require('path'); module.exports = { config: path.resolve('./config', 'config.js'), 'models-path': path.resolve('./models'), 'seeders-path': path.resolve('./seeders'), 'migrations-path': path.resolve('./migrations') };
3. 迁移文件改用动态导入(可选,保留ESM语法)
如果不想将ESM转译为CJS,可在迁移文件中使用动态import()替代静态import,并配合async/await(Sequelize迁移函数支持异步):
'use strict'; module.exports = { async up(queryInterface, Sequelize) { // 动态导入模型或ESM模块 const { User } = await import('../models/user.js'); // 执行迁移逻辑,比如创建表、插入数据等 await queryInterface.createTable('Users', User.rawAttributes); }, async down(queryInterface, Sequelize) { const { User } = await import('../models/user.js'); // 回滚逻辑 await queryInterface.dropTable('Users'); } };
4. 处理package.json的"type": "module"配置
如果项目package.json中设置了"type": "module",需要给Sequelize CLI单独启用CJS兼容,可在.sequelizerc开头添加以下代码(需先安装esm包:npm install esm --save-dev):
// 强制当前文件使用CJS模块加载逻辑 require = require('esm')(module);
内容的提问来源于stack exchange,提问作者digitalniweb
相关产品推荐
相关产品推荐

