从Serverless 3迁移至SST时GraphqlLoaderPlugin报错,求正确加载语法
Serverless 3迁移至SST时esbuild插件加载错误解决方法
问题背景
正在将基于Serverless 3的应用迁移到SST,原Serverless配置中的esbuild自定义段如下:
custom: esbuild: bundle: true minify: false plugins: ./esbuild-plugins.js sourcemap: true target: es2022
对应的esbuild-plugins.js插件文件内容:
const { default: graphqlLoaderPlugin } = require("@luckycatfactory/esbuild-graphql-loader"); const { nodeExternalsPlugin } = require("esbuild-node-externals"); const fs = require("fs-extra"); const path = require("path"); const copyPlugin = ({ from, to }) => { return { name: "copy", setup(build) { const target = build.initialOptions.outfile ? path.dirname(build.initialOptions.outfile) : path.resolve(build.initialOptions.outdir); build.onEnd(() => fs.copySync(from, path.join(target, to), { overwrite: true })); }, }; }; module.exports = [ graphqlLoaderPlugin(), nodeExternalsPlugin(), copyPlugin({ from: "src/type-defs", to: "./type-defs", }), ];
迁移到SST后,函数栈配置片段如下:
import * as graphqlLoaderPlugin from "@luckycatfactory/esbuild-graphql-loader"; export function API({ stack }: StackContext) { const { stackName, stage } = stack; console.log(`Deploying ${stackName} to stage: ${stage}`); const function = new Function(stack, "function", { handler: "./src/lambda.handler", runtime: "nodejs20.x", memorySize: 768, copyFiles: [{ from: "./src/type-defs" }], nodejs: { esbuild: { plugins: [graphqlLoaderPlugin.default()], }, }, environment: { /* ...*/ }, }); const api = new ApiGatewayV1Api(stack, "api", { routes: { "ANY /graphql": { function: function, cdk: { method: { apiKeyRequired: true, }, }, }, }, }); /* 省略usageplans、apikeys等配置 */ }
触发错误:
TypeError: graphqlLoaderPlugin.default is not a function
即使改为import graphqlLoaderPlugin from "@luckycatfactory/esbuild-graphql-loader";并调用graphqlLoaderPlugin(),错误依然存在。
解决方案
1. 正确导入graphqlLoaderPlugin
该插件的ES模块导出存在兼容问题,直接使用require语法导入即可解决:
const graphqlLoaderPlugin = require("@luckycatfactory/esbuild-graphql-loader").default;
2. 完整迁移所有esbuild插件
将原插件文件中的逻辑整合到SST的TypeScript代码中,完整配置如下:
import { StackContext, Function, ApiGatewayV1Api } from "sst/constructs"; const { nodeExternalsPlugin } = require("esbuild-node-externals"); const graphqlLoaderPlugin = require("@luckycatfactory/esbuild-graphql-loader").default; const fs = require("fs-extra"); const path = require("path"); // 定义copy插件 const copyPlugin = ({ from, to }) => { return { name: "copy", setup(build) { const target = build.initialOptions.outfile ? path.dirname(build.initialOptions.outfile) : path.resolve(build.initialOptions.outdir); build.onEnd(() => fs.copySync(from, path.join(target, to), { overwrite: true })); }, }; }; export function API({ stack }: StackContext) { const { stackName, stage } = stack; console.log(`Deploying ${stackName} to stage: ${stage}`); // 避免使用保留字function作为变量名 const lambdaFunction = new Function(stack, "function", { handler: "./src/lambda.handler", runtime: "nodejs20.x", memorySize: 768, nodejs: { esbuild: { bundle: true, minify: false, sourcemap: true, target: "es2022", plugins: [ graphqlLoaderPlugin(), nodeExternalsPlugin(), copyPlugin({ from: "src/type-defs", to: "./type-defs", }) ], }, }, environment: { /* ...*/ }, }); const api = new ApiGatewayV1Api(stack, "api", { routes: { "ANY /graphql": { function: lambdaFunction, cdk: { method: { apiKeyRequired: true, }, }, }, }, }); /* 省略usageplans、apikeys等配置 */ }
3. 关键注意事项
- 不要使用JavaScript保留字
function作为变量名,替换为lambdaFunction这类合法名称 - 若仅需简单复制文件,可使用SST自带的
copyFiles配置;如果需要自定义复制路径或逻辑,保留自定义copyPlugin更合适 - 确保所有依赖包(
@luckycatfactory/esbuild-graphql-loader、esbuild-node-externals、fs-extra)已正确安装
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

