I am new to AWS and trying to deploy a GraphQL API written in NodeJS as an AWS Lambda using Serverless. I have followed several tutorials that are close to what I am doing but cannot get the handler to work. The closest tutorial to what I am doing was using JavaScript, where I am using TypeScript. I followed closely but using TypeScript. I am getting errors that it cannot find the handler module (Error: Cannot find module 'lambda').
My handler file is named lambda.ts looks like this `
import {app} from './app';
import {serverless} from 'serverless-http';
export const handler = serverless(app);
`
My serverless.yml looks like this `
service: graphql-api
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs12.x
region: us-east-1
functions:
serverlessApi:
handler: lambda.handler
app.ts
import express from 'express';
import cors from 'cors';
import { graphqlHTTP } from 'express-graphql';
import { schema, resolvers } from './api-schema/';
import { loginMiddleware } from './login-middleware';
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(loginMiddleware);
app.use(
'/graphql',
graphqlHTTP({
schema: schema,
graphiql: true,
rootValue: resolvers,
})
);
export default app;
` The lambda.js, app.ts, and serverless.yml files are all in the same root directory.
I have tried to convert the code to JavaScript and get errors that it cannot find the 'app' module. (Cannot find module './app')
lambda.js and looks like this `
const app = require('./app');
const serverless = require('serverless-http');
module.exports.handler = serverless(app);
`
I have also tried to export 'app' as default or named getting the same result. I am out of ideas. Any help is much appreciated.
CodePudding user response:
The problem likely stems from the fact that you're mixing JS and TS here. I don't see you using TypeScript really in app.ts
, so to keep things simple, I would recommend switching to pure js
for now to make things work, and then switching to TS.
You're also using ESM, that is not supported in nodejs12.x
runtime, and mixing ESM and CommonJS (your lambda.js
is using CommonJS) can cause some troubles, so I would suggest to switch the app.js
implementation to use require
s instead of import
s and export in CommonJS style, at least in initial iteration.
You can also safely upgrade to nodejs16.x
runtime, as nodejs12.x
is going to be deprecated soon.
If you'd like to stick to TypeScript and/or ESModules, you'll need a plugin like https://www.npmjs.com/package/serverless-esbuild and I would recommend to do so, after successfully deploying the initial version.
CodePudding user response:
The solution to the issue was several changes. I did upgrade to Node16, but more importantly, I followed the documentation here: https://www.prisma.io/docs/guides/deployment/deployment-guides/deploying-to-aws-lambda#deployment-using-serverless-webpack The npm package serverless-esbuild started me in the right direction, but it had issues with prisma. I don't like having to use webpack, and I am still getting a CORS error, but the original issue of not finding the module is fixed. Also changed my handler file to look like this:
import app from './app';
import serverless from 'serverless-http';
const handler = () => {
return serverless(app);
}
export { handler };
It is very shocking to see the difference in the webpack build and the esbuild. esbuild is 1.2 MB, where the webpack build is 96 MB! It also takes at least 2x as long to complete. This has been a very frustrating journey. I guess when I get it all working it will be worth it, but this is not fun dev time!