使用AWS CDK仅用mssql却遇knex相关打包错误,求解决
解决AWS CDK打包Knex仅依赖MSSQL时的缺失依赖错误
我仅使用mssql客户端,但执行cdk synth时出现如下打包错误:
环境版本信息
- Node.js - v18.16.0
- CDK - 2.95.1
- knex - 2.5.1
错误日志
dirname /.../my-repo/cdk/my-app/lib/lambda Bundling asset api---app/get-last-sales-no/Code/Stage... ✘ [ERROR] Could not resolve "sqlite3" node_modules/knex/lib/dialects/sqlite3/index.js:42:19: 42 │ return require('sqlite3'); ╵ ~~~~~~~~~ You can mark the path "sqlite3" as external to exclude it from the bundle, which will remove this error. You can also surround this "require" call with a try/catch block to handle this failure at run-time instead of bundle-time. ✘ [ERROR] Could not resolve "pg" node_modules/knex/lib/dialects/pgnative/index.js:13:19: 13 │ return require('pg').native; ╵ ~~~~ You can mark the path "pg" as external to exclude it from the bundle, which will remove this error. You can also surround this "require" call with a try/catch block to handle this failure at run-time instead of bundle-time. ✘ [ERROR] Could not resolve "mysql2" node_modules/knex/lib/dialects/mysql2/index.js:15:19: 15 │ return require('mysql2'); ╵ ~~~~~~~~ You can mark the path "mysql2" as external to exclude it from the bundle, which will remove this error. You can also surround this "require" call with a try/catch block to handle this failure at run-time instead of bundle-time. ✘ [ERROR] Could not resolve "pg" node_modules/knex/lib/dialects/redshift/index.js:44:19: 44 │ return require('pg'); ╵ ~~~~ You can mark the path "pg" as external to exclude it from the bundle, which will remove this error. You can also surround this "require" call with a try/catch block to handle this failure at run-time instead of bundle-time.
查阅资料发现,部分用户通过为esbuild标记knex或客户端依赖为外部依赖解决了问题,但并未直接使用esbuild,推测AWS CDK在底层使用它,请问有什么解决办法?
解决办法
AWS CDK的NodejsFunction默认使用esbuild进行打包,你可以通过以下方式配置打包选项,将未使用的数据库驱动标记为外部依赖,让esbuild跳过它们的解析和打包:
方法1:在NodejsFunction中配置externalModules
直接在Lambda函数定义里添加打包配置,指定不需要打包的依赖:
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; new NodejsFunction(this, 'GetLastSalesNoFunction', { entry: './lib/lambda/get-last-sales-no.ts', bundling: { // 将未安装的数据库驱动以及knex本身标记为外部依赖 externalModules: ['sqlite3', 'pg', 'mysql2', 'knex'] } });
方法2:通过esbuild配置文件全局设置
在项目根目录创建esbuild.config.js,添加外部依赖配置,CDK的NodejsFunction会自动读取该文件:
module.exports = { external: ['sqlite3', 'pg', 'mysql2'] };
方法3:自定义Bundling配置(适用于非NodejsFunction场景)
如果使用的是基础的Function类配合资产打包,可在BundlingOptions中通过命令传递esbuild参数:
import { Function, Code, Runtime } from 'aws-cdk-lib/aws-lambda'; new Function(this, 'GetLastSalesNoFunction', { runtime: Runtime.NODEJS_18_X, code: Code.fromAsset('./lib/lambda', { bundling: { image: Runtime.NODEJS_18_X.bundlingImage, command: [ 'bash', '-c', 'npm install && npx esbuild index.ts --bundle --external:sqlite3 --external:pg --external:mysql2 --outfile=/asset-output/index.js' ] } }), handler: 'index.handler' });
原理说明
Knex在源码中包含了所有数据库驱动的导入逻辑,即使你只使用MSSQL,esbuild打包时会扫描所有require语句并尝试解析依赖。将未安装的驱动标记为外部依赖后,esbuild会跳过这些依赖的打包,运行时Knex会动态加载你实际使用的MSSQL驱动,不会影响功能。
内容的提问来源于stack exchange,提问作者Shanika Ediriweera
相关产品推荐
相关产品推荐

