You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js ESM环境下Knex执行迁移遇mysql2语法错误求助

Node.js ESM环境下Knex迁移报错的解决办法

问题概述

在Node.js ESM环境(package.json已设置type: "module")中使用Knex CLI执行MySQL迁移时,运行命令knex migrate:latest --knexfile database/knexfile.js --esm出现两个异常:

  • 明明已安装mysql2,却仍提示需安装该依赖
  • 触发SyntaxError: Invalid or unexpected token,错误溯源到mysql2依赖的lru-cache文件
    CommonJS环境下无此问题,多次重装node_modules无效。

相关配置文件

knexfile.js

import { DB_NAME, DB_PASSWORD, DB_USER } from "../config/env.js";

/**
 * @type { Object.<string, import("knex").Knex.Config> }
 */
export default {
  development: {
    client: "mysql2",
    connection: {
      database: DB_NAME,
      user: DB_USER,
      password: DB_PASSWORD,
    },
    pool: {
      min: 2,
      max: 10,
    },
    migrations: {
      tableName: "knex_migrations",
    },
  },
};

迁移文件

/**
 * @param { import("knex").Knex } knex
 * @returns { Promise<void> }
 */
exports.up = function (knex) {
  return knex.schema.createTable("user", (table) => {
    table.increments("id").primary().unsigned().notNullable();
    table.string("profilname", 255).unique().notNullable();
    table.string("username", 255).unique().notNullable();
    table.string("password", 511).notNullable();
    table.timestamp("createdAt").notNullable().defaultTo(knex.fn.now());
    table
      .timestamp("updatedAt")
      .notNullable()
      .defaultTo(knex.raw("NOW() ON UPDATE NOW()"));
    table.datetime("lastLogin");
    table
      .enum("role", ["admin", "writer", "user"])
      .notNullable()
      .defaultTo("user");
  });
};

/**
 * @param { import("knex").Knex } knex
 * @returns { Promise<void> }
 */
exports.down = function (knex) {
  return knex.schema.dropTableIfExists("user");
};

package.json依赖片段

{
  "main": "index.js",
  "type": "module",
  "dependencies": {
    "knex": "^3.0.1",
    "mysql2": "^3.6.3",
    // 其他依赖省略
  }
}

解决方案

1. 修正mysql2的客户端配置

Knex在ESM环境下可能无法自动解析CommonJS格式的mysql2,将knexfile.js中的client配置改为完整的模块解析路径:

// 修改knexfile.js的development配置
development: {
  client: require.resolve('mysql2'), // 替换原有的"mysql2"
  // 其余配置保持不变
}

2. 调整CLI命令参数顺序

部分Knex版本中--esm参数需放在命令最前端,尝试修改命令为:

knex --esm migrate:latest --knexfile database/knexfile.js

3. 降级mysql2到兼容版本

mysql2@3.6.x部分版本在ESM环境存在依赖解析问题,可降级到稳定兼容的3.5.x版本:

npm uninstall mysql2 && npm install mysql2@3.5.2

4. 统一迁移文件为ESM格式

当前迁移文件是CommonJS格式,改为ESM格式可避免潜在的格式冲突:

// 修改迁移文件为ESM规范
/**
 * @param { import("knex").Knex } knex
 * @returns { Promise<void> }
 */
export async function up(knex) {
  // 原有表创建逻辑不变
}

/**
 * @param { import("knex").Knex } knex
 * @returns { Promise<void> }
 */
export async function down(knex) {
  // 原有表删除逻辑不变
}

验证步骤

  1. 执行修改后的迁移命令
  2. 确认不再出现mysql2未安装的提示
  3. 检查数据库中是否成功创建目标表

内容的提问来源于stack exchange,提问作者Suleyman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:57:43