
Just change the .mjs extension of index.mjs to index.js
Answer from Manookian on Stack Overflow
Just change the .mjs extension of index.mjs to index.js
Node18 for Lambda uses JavaScript SDK V3 .
AWS SDK for Javascript v2 publishes a single npm package that supports all the AWS services. This makes it easy to use multiple services in a project at the cost of a large dependency when only using a handful of services or operations.
In resource constrained environment such as mobile devices, having separate packages for each service client allows optimizing the dependency. The AWS SDK for Javascript v3 provides such modular packages. We have also split up the core parts of the SDK so that service clients only pull in what they need. For example, a service that sends responses in JSON will no longer need to also have an XML parser as a dependency.
As you only import modules that you need, you can do so like below:
const { S3 } = require("@aws-sdk/client-s3");
SDK V2
const AWS = require("aws-sdk");
const s3Client = new AWS.S3({});
await s3Client.createBucket(params).promise();
SDK V3
const { S3 } = require("@aws-sdk/client-s3");
const s3Client = new S3({});
await s3Client.createBucket(params)
Backward V2 Compatibility Style
import * as AWS from "@aws-sdk/client-s3";
const s3Client = new AWS.S3({});
await s3Client.createBucket(params);
File Extension
Lambda index.js now has the extension of .mjs. Renaming this can sometimes fix any issues you have.
source
To upgrade to Node.js 18, you have to change the code to make the function work again. I don't use zip files, config files or layers.
Steps to upgrade your AWS Lambda function:
1. Change the filename of index.js to index.mjs
File names ending in .mjs are always treated as ES modules. File names ending in .js inherit their type from the package.
Reference: https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda/
You should rename your index.js file to index.mjs to prevent one of the following errors:
SyntaxError: Cannot use import statement outside a module
SyntaxError: Unexpected token 'export'
2. Change your handler from CommonJS module handler to ES module handler
You must update the way you define your handler to prevent one of the following errors:
Runtime.HandlerNotFound: index.handler is undefined or not exported
ReferenceError: exports is not defined in ES module scope
Reference: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html
// Before NodeJS 18
exports.handler = async function (event, context) {
console.log("EVENT: \n" + JSON.stringify(event, null, 2));
return context.logStreamName;
};
// NodeJS 18 and above
export const handler = async (event, context) => {
console.log("EVENT: \n" + JSON.stringify(event, null, 2));
return context.logStreamName;
};
3. Change the way you import your modules
You cannot use the "require" keyword anymore. You will get the following error when you do:
- ReferenceError: require is not defined in ES module scope, you can use import instead
It is important to know that since NodeJS 18 you cannot import the complete AWS SDK anymore, but you have to specify which modules you need, or you will get the following error:
- Runtime.ImportModuleError: Error: Cannot find module 'aws-sdk'
Reference: https://aws.amazon.com/blogs/compute/node-js-18-x-runtime-now-available-in-aws-lambda/
// Before NodeJS 18
const AWS = require("aws-sdk");
const https = require("https");
const querystring = require("querystring");
// NodeJS 18 and above. In this example the module "client-sns" is imported from the AWS SDK.
import * as AWS from "@aws-sdk/client-sns";
import https from "https";
import querystring from "querystring";
In order to fix the error, you could opt to use at least NodeJS version 18 or the latest runtime version (NodeJS 22)
You can upgrade your old functions by adding
"type": "module"to your package.json file. This will inform the Node runtime to use ES6 modules instead of the traditional ES5/CommonJS syntax.Change the extension of your files to
.mjsto force the NodeJS runtime to treat your file as an ES6 module.If you are using
esbuild, you will have to make sure that your build output is compatible with the ES6 modules (import/export).If you were using TypeScript, configure your transpiler to produce a build output that is compatible with ES modules.
If there is a performance issue, it would be minimal that we don't have to worry about it! PS: I recommend to test the compatibility of the ES5/CJS/CommonJS modules that the lambda uses when you change the runtime.
Since you have "type": "module", ES6 modules are enabled. You should change index.js to
import * as OneSignal from '@onesignal/node-onesignal';
export const handler = async (event) => {
const response = "hey";
console.log("testing")
return response;
};
And, if you want a default export, use:
import * as OneSignal from '@onesignal/node-onesignal';
const handler = async (event) => {
const response = "hey";
console.log("testing")
return response;
};
export default handler
Below changes worked for me.
Change from this:
export.handler = async (event) => {
To this:
export const handler = async (event) => {