Currently, I am in the process of incorporating NestJS as an AWS Serverless function using serverless-framework.
Following the official documentation, my code mirrors that of the documentation. However, upon launching it, I encounter the error message
Failure: offline: handler 'handler' in [..] is not a function
.
Upon inspecting my compiled source code in main.js
, changing the line from exports.handler = handler;
to
resolves the issue.module.exports.handler = handler;
Attempts to modify the code within main.ts
were unsuccessful due to webpack compiling it differently.
// main.ts
const handler ...;
module.exports.handler = handler;
Shown below 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);
};
The following 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+}'
This is my webpack.config.js:
return {
...options,
externals: [],
output: {
...options.output,
libraryTarget: 'commonjs2',
},
// ... the rest of the configuration
};
Lastly, here's my tsconfig.json file:
{
"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
}
}
Are there specific configurations missing in webpack or changes needed in the typescript configuration files? The documentation implies it should work effortlessly, but unfortunately, it doesn't.
In essence, switching from exports.handler = handler
to module.exports.handler = handler
in my compiled file serves as a temporary fix and a less than ideal solution.
"build": "nest build --webpack && sed -i 's/exports.handler = handler;/module.exports.handler = handler;/g' dist/main.js",