Search code examples
node.jsaws-lambdaserverlesses6-modules

Use esmodules on aws lambda and serverless get "require is not defined in ES module scope"


I'm trying to dev a script on aws lambda through nodejs, serverless and using es modules

I got this error all the time:

{
    "errorType": "ReferenceError",
    "errorMessage": "require is not defined in ES module scope, you can use import instead\nThis file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains \"type\": \"module\". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.",
    "stack": [
        "ReferenceError: require is not defined in ES module scope, you can use import instead",
        "This file is being treated as an ES module because it has a '.js' file extension and '/var/task/package.json' contains \"type\": \"module\". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.",
        "    at file:///var/task/s_getStatus.js:2:21",
        "    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)"
    ]
}

I understand that somewhere a script still use commonjs style code but can't find it on local. When running with serverless-offline, no problem too (code is working).

My handler code is simple as this:

export default async function () {
  return {
    statusCode: 200,
    body: JSON.stringify({ status: true }),
  };
}

the code of main script (handler.js) is:

'use strict';

export {default as getStatus} from './handlers/get_status/index.js';

my package.json is:

{
  "name": "...-api",
  "version": "1.0.0",
  "main": "handler.js",
  "repository": "...-api.git",
  "type": "module",
  "private": true,
  "scripts": {
    "local": "sls offline",
  },
  "dependencies": {
    "@aws-sdk/client-kms": "3.348.0",
    "serverless-plugin-tracing": "2.0.0"
  },
  "devDependencies": {
    ...
    "serverless-offline": "12.0.4",
    "serverless-prune-plugin": "2.0.2"
  }
}

My serverless file:

org: mathkr
app: healthcheck-api
service: healthcheck-api
frameworkVersion: '3'
useDotenv: true
provider:
  name: aws
  runtime: nodejs18.x
  region: eu-west-3
  tracing:
    lambda: true
  iamRoleStatements:
    - Effect: Allow
      Action:
        - xray:PutTraceSegments
        - xray:PutTelemetryRecords
      Resource:
        - '*'
plugins:
  - serverless-plugin-tracing
functions:
  getStatus:
    handler: handler.getStatus
    timeout: 30
    events:
      - http:
          path: /status
          method: get
          cors: false

Nothing crazy. The point is, my opinion, on the 'var/task/s_getStatus.js:2:21' part of the errror. Seems that somewhere something uses require instruction but what ? It seems that in package.json file, the instruction type: 'module' is well defined. So I don't understand what i'm missing...

Is serverless translating code to commonjs ? Do i forget somewhere an option to setup to tell use esm ?


Solution

  • Since you are using the app and org keys in your serverless.yml file, its using Serverless Dashboard plugin for deployment.

    Unfortunately, this plugin doesn't have an ESM support and hence is using require() statements.

    At the moment, there is no plan to support ESM in Serverless Dashboard. Refer: https://github.com/serverless/dashboard-plugin/issues/564

    So you have a couple of options:

    1. Remove Serverless Dashboard (since its already deprecated). You can do this by removing the app and org keys from your serverless.yml file.
    2. Migrate from Serverless Dashboard to Serverless Console, which already supports ES Modules.
    3. Rewrite your application logic using CommonJS (instead of ES Modules).