When using NestJS and Serverless, the error message "handler 'handler' is not a function" may be encountered

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

module.exports.handler = handler;
resolves the issue.

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",

Answer №1

To solve this issue, I made sure that the webpack output included a libraryTarget set to commonjs2. To do this, you can create or edit a webpack.config.js file at the root of your project with the following code snippet specifying the libraryTarget as commonjs2:

module.exports = (options) => {
  return {
    ...options,
    output: {
      ...options.output,
      libraryTarget: 'commonjs2',
    },
  };
};

In my serverless.yml file, I have configured my lambda function like so:

...

functions:
  example:
    handler: "./dist/apps/example/main.js.handler"
...

Please remember to adjust the main.js.handler if your entrypoint or function name is different. For instance, if it was named entrypoint, the string should be changed to

dist/apps/example/main.js.entrypoint
.

Answer №2

I managed to find the solution for a similar issue while using serverless-plugin-typescript within an nx workspace.

The key lies in configuring tsconfig with the module set to commonjs:

"compilerOptions": {  
  "module": "commonjs",
},

Subsequently, I observed the changes reflected in the ./build folder:

...
exports.main = main;

Answer №3

Many individuals are facing the same problem, and after searching for a suitable solution without success, I have discovered an effective fix: Simply replace exports.handler with module.exports.handler in the compiled file main.js.

You can easily achieve this by using sed during your build process within the package.json

"build": "nest build --webpack && sed -i 's/exports.handler = handler;/module.exports.handler = handler;/g' dist/main.js",
"build:mac": "nest build --webpack && sed -i '' 's~exports.handler = handler;~module.exports.handler = handler;~g' dist/main.js",

Please note that there is a separate command for MacOS due to its unique implementation of sed.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What are the consequences of relying too heavily on deep type inference in React and Typescript?

In the process of migrating my React + Javascript project to Typescript, I am faced with preserving a nice unidirectional flow in my existing code. The current flow is structured as follows: 1. Component: FoobarListComponent -> useQueryFetchFoobars() 2 ...

"Error: Unfinished string literal encountered" occurring in a TypeScript app.component.ts file in NativeScript

I've been trying to learn NativeScript through a tutorial, but I keep encountering errors. Here is an excerpt from my app.component.ts file: import { Component } from '@angular/core'; @Component ({ selector: 'my-app', temp ...

Having issues with using the class selector in SVG.select() method of the svg.js library when working with TypeScript

Exploring the capabilities of the svg.js library with typescript has presented some challenges when it comes to utilizing CSS selectors. My goal is to select an SVG element using the select() method with a class selector. In this interactive example, this ...

Issue: The function (0, react__WEBPACK_IMPORTED_MODULE_1__.useActionState) is not recognized as a valid function or its output is not iterable

I found a great example of using useActionState at this source. Currently, I am implementing it in my project with Next.js and TypeScript. app/page.tsx: "use client"; import { useActionState } from "react"; import { createUser } from ...

Using TypeScript to define a generic type for the key in a React select component

Check out this component that wraps a Material UI select: return ( <Box display="flex" justifyContent={justifyContent}> <SortWrapper> <InputLabel htmlFor={id} shrink={true} > Sort by </InputLabel& ...

The devastation caused by typing errors in TypeScript

I have a preference: const settings = { theme: "light", }; and feature: const Feature = ({ setting }: Props) => ( <FeatureBlock> <FeatureValue scale="large" size={20}> {setting.theme} </Styled.FeatureValue> ...

Determine whether the current time falls within the specified time slots and check if the day is included in the provided array of days

Listing my Weekly Schedule: weekly_schedule: any[] = [ { id: 0, value: 'Monday' }, { id: 1, value: 'Tuesday' }, { id: 2, value: 'Wednesday' }, { id: 3, value: ...

NESTJS does not have any impact on enabling CORS

I am facing issues with enabling CORS for testing purposes in the latest version of NestJS 8.0.6 on a fresh http + ws project. I need to have the Access-Control-Allow-Origin header in the server's response for the client to accept it. I have tried thr ...

Utilize cypress to analyze the loading time of a webpage

My current challenge involves using cypress to carry out website tests. I am looking for a reliable method to measure the duration it takes for certain cypress commands to load or execute. As an example: //var startTime = SomeStopwatchFunction(); cy.visit( ...

The module "react-leaflet" is showing a type error because it does not have a exported member named "useEventHandlers"

My Next.js application is built with TypeScript and React-Leaflet. Everything runs smoothly when I start my development server using npm run dev, no errors whatsoever. However, the problem arises when I attempt to build the project using npm run build. An ...

Utilizing internationalization and next/image in next.config.js alongside TypeScript

Currently, I am in the process of developing a miniature application using TypeScript within NextJS now that support for TypeScript comes standard in Next.js. Additionally, my aim is to integrate two recently introduced features: Image Component and Image ...

What is the best way to utilize project references with multiple tsconfig files?

Let's say I have three separate projects to work on: shared frontend backend In order to use the shared project as a reference in both the frontend and the backend, I need to make a few adjustments. The backend utilizes commonjs modules while the fr ...

Encountering the "encoding" Module Error when Implementing Nextjs-13 with Supabase

I encountered an issue while trying to utilize Supabase for handling data insertion/retrieval from my form. Upon compilation, I received an error stating that the encoding module was not found. Despite attempting cache cleaning and re-installation of npm m ...

Creating Angular UI states with parameters in TypeScript

My Understanding In my experience with TypeScript and angular's ui state, I have utilized "type assertion" through the UI-Router definitely typed library. By injecting $state into my code as shown below: function myCtrl($state: ng.ui.IStateService){ ...

Can a TypeScript variable in Angular contain a mixture of HTML and plain text?

I have a website where I am displaying content from a Model file. I would like to create a TypeScript variable that contains both a string related to the website's content and a URL enclosed in an HTML tag. When this variable is rendered on the view, ...

When running the 'nest build' command, a critical error occurs: 'FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory'

While my previous project works perfectly under the VS Code debugger, I am encountering issues when trying to build it from the command line. The specific error message I am receiving is: FATAL ERROR: Ineffective mark-compacts near heap limit Allocatio ...

Troubleshooting: TypeScript not functioning properly with Create Next App dev server启动时有问题

When I attempted to set up a nextjs+typescript app using the command npx create-next-app@latest --ts, all the installations went smoothly. However, upon running the dev function, I encountered an error related to Global CSS. error - ../../../#Typescript/Ne ...

Dealing with request-specific or session-specific data in LoopBack 4

I am currently facing a challenge within our LoopBack4 application. We have implemented controllers and are using JWT for Authorization. In the token's payload, we include a list of rights granted to the requesting user. Additionally, we have added an ...

Invoking a method within the same class in Typescript can be achieved by calling one method from another

I've recently delved into Typescript and I'm facing an issue when trying to call one method from another method within the same class. After researching this problem, some individuals suggested using "this" before the method name. However, in my ...

Convert the generic primitive type to a string

Hello, I am trying to create a function that can determine the primitive type of an array. However, I am facing an issue and haven't been able to find a solution that fits my problem. Below is the function I have written: export function isGenericType ...