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

如何构建支持按需安装适配器的模块化npm查询包?

问题:实现轻量多数据库支持的npm包结构设计

我正在开发一款类查询工具的npm包easy-query,目标是支持MySQL、MSSQL等多种数据库并发布到npm仓库。目前的问题是必须预装所有数据库依赖(如mysql2、mssql、tedious、pgsql),造成了大量不必要的资源占用。

同时安装easy-query和easy-query-mysql后,主包无法导入适配器,推测是Node.js模块隔离机制导致。尝试动态导入easy-query-mysql时出现ERR_MODULE_NOT_FOUND错误,相关代码及目录结构如下:

app
|- node_modules
|  |- easy-query
|  |  |- index.js
|  |- easy-query-mysql
|- index.js

/app/index.js

const query = await EasyQuery.connect('mysql://user:pass@localhost/database');

/app/node_modules/easy-query/index.js

const adapter = await import('easy-query-mysql')

需求:实现用户仅安装所需模块的功能——主包easy-query不含任何数据库适配器,用户安装easy-query及对应适配器(如npm i easy-query easy-query-mysql)后,主包可通过mysql://类连接字符串建立连接;安装easy-query-mssql则支持mssql://连接。


解决方案设计

1. 适配器包命名规范

统一适配器包命名为easy-query-[db-type],比如easy-query-mysql、easy-query-mssql,方便主包根据连接字符串前缀自动拼接包名。

2. 动态导入+错误捕获优化

在主包中解析连接字符串的数据库类型前缀,动态导入对应适配器,并捕获模块未找到的错误,给出明确的安装提示:

// easy-query/index.js
export class EasyQuery {
  static async connect(connectionString) {
    const dbType = connectionString.split('://')[0];
    const adapterPackage = `easy-query-${dbType}`;
    try {
      const adapter = await import(adapterPackage);
      return adapter.connect(connectionString);
    } catch (err) {
      if (err.code === 'ERR_MODULE_NOT_FOUND') {
        throw new Error(`请安装对应数据库适配器:npm install ${adapterPackage}`);
      }
      throw err;
    }
  }
}

3. 适配器接口标准化

要求所有适配器包导出统一的接口,确保主包能无缝调用。例如必须包含connect方法,返回封装好的查询实例:

// easy-query-mysql/index.js
import mysql2 from 'mysql2/promise';

export async function connect(connectionString) {
  const connection = await mysql2.createConnection(connectionString);
  return {
    query: async (sql, params) => connection.execute(sql, params),
    // 其他通用查询方法...
  };
}

4. 主包peerDependencies配置

在easy-query的package.json中配置可选的peer依赖,声明适配器的兼容版本范围但不强制安装:

{
  "peerDependencies": {
    "easy-query-mysql": "^1.0.0",
    "easy-query-mssql": "^1.0.0"
  },
  "peerDependenciesMeta": {
    "easy-query-mysql": {
      "optional": true
    },
    "easy-query-mssql": {
      "optional": true
    }
  }
}

这样npm会在用户安装时提示缺失的可选依赖,但不会强制安装所有适配器。

5. 独立包目录结构

主包和适配器包分开维护为独立npm包:

# 主包仓库
easy-query/
|- index.js
|- package.json
|- README.md

# MySQL适配器仓库
easy-query-mysql/
|- index.js
|- package.json
|- README.md
# 依赖mysql2

参考思路

可以参考现有成熟工具的实现模式:

  • Sequelize:主包+对应数据库驱动(如mysql2、pg),主包根据配置自动加载驱动
  • Knex:采用主包+数据库驱动的分离模式,用户按需安装驱动

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 09:10:05