'NestJS and Serverless - handler 'handler' is not a function
I am trying to implement NestJS as a AWS Serverless function using serverless-framework.
I was following this official documentation and my code is exactly as in the documentation. However when I launch it I get the error Failure: offline: handler 'handler' in [..] is not a function
.
If I go into my compiled source code of main.js
and change the line exports.handler = handler;
to module.exports.handler = handler;
it starts working.
I also tried to do change the code in main.ts
to accommodate this but it does not help since webpack is compiling it differently then.
// main.ts
const handler ...;
module.exports.handler = handler;
Here is my main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Callback, Context, Handler } from 'aws-lambda';
import serverlessExpress from '@vendia/serverless-express';
import { AppModule } from './app.module';
let server: Handler;
async function bootstrap(): Promise<Handler> {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
}),
);
await app.init();
const expressApp = app.getHttpAdapter().getInstance();
return serverlessExpress({ app: expressApp });
}
export const handler: Handler = async (event: any, context: Context, callback: Callback) => {
server = server ?? (await bootstrap());
return server(event, context, callback);
};
Here is my serverless.yml
service:
name: serverless-example
plugins:
- serverless-offline
provider:
name: aws
runtime: nodejs12.x
functions:
main:
handler: dist/main.handler
events:
- http:
method: ANY
path: /
- http:
method: ANY
path: '{proxy+}'
Here is my webpack.config.js
return {
...options,
externals: [],
output: {
...options.output,
libraryTarget: 'commonjs2',
},
// ... the rest of the configuration
};
And lastly here is my tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"esModuleInterop": true
}
}
Am I missing some config on webpack? Or maybe change in the typescript config files? I have no idea and documentation says that it should just work, however it does not.
Theoretically all I need is it to be module.exports.handler = handler
instead of exports.handler = handler
in my compiled file because as I said I did change it and it started to work properly.
This is the interim fix I'm using but obviously this is wrong way of approaching it.
"build": "nest build --webpack && sed -i 's/exports.handler = handler;/module.exports.handler = handler;/g' dist/main.js",
Solution 1:[1]
I resolved this by creating ensuring that the webpack output has a libraryTarget
of commonjs2
. Create (or edit) a webpack.config.js
file in the root of the project with the following content ensuring that we set the libraryTarget
to commonjs2
:
module.exports = (options) => {
return {
...options,
output: {
...options.output,
libraryTarget: 'commonjs2',
},
};
};
In my serverless.yml
I have the following defined for my lambda function:
...
functions:
example:
handler: "./dist/apps/example/main.js.handler"
...
Please note that main.js.handler
should be changed if your entrypoint/function is different. For example if it was entrypoint
this string would be dist/apps/example/main.js.entrypoint
Solution 2:[2]
I found the solution :) for the same problem but with serverless-plugin-typescript with nx workspace
there is all about tsconfig with module: commonjs
"compilerOptions": {
"module": "commonjs",
},
and then I see in ./build folder
...
exports.main = main;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Cal |
Solution 2 |