Introduction to Migrating Lambda Functions to ECMAScript Modules (ESM)

With AWS Lambda’s support for ECMAScript Modules (ESM), developers now have more flexibility when using JavaScript’s modern module system. ESM allows a cleaner syntax and modular codebase, making it a preferred option for developers accustomed to the latest JavaScript features. This guide explores why you should consider ESM for Lambda functions, the migration steps involved, and some practical tips for testing and validation.

Why Choose ECMAScript Modules for Lambda Functions?

Migrating to ESM offers several advantages:

  • Modern Syntax: ESM uses import and export syntax, which is more concise and aligns with JavaScript’s evolving standards.
  • Tree Shaking: ESM allows bundlers to remove unused code during the build process, improving Lambda function performance.
  • Scoped Modules: ESM provides scoping by default, reducing potential naming conflicts across functions.
  • Better Interoperability: As ESM becomes the de facto standard, using it in Lambda functions enhances compatibility with other modules and libraries.

By migrating Lambda functions to ESM, you can follow best practices, write cleaner code, and effectively leverage modern JavaScript capabilities.

Step 1: Designating Lambda Functions as ESM

To designate Lambda functions as ESM, you must update your project settings to instruct Node.js that you’re using the ESM syntax. Here are two methods:

Method 1: Updating package.json for ESM

The first and most straightforward approach is to update the package.json file to declare your Lambda project as an ESM project:

  1. Open package.json in your Lambda function’s root directory.
  2. Add or update the “type” field to “module”.

{

  “type”: “module”

}

Setting “type”: “module” tells Node.js to interpret .js files as ECMAScript Modules instead of CommonJS. This approach is ideal if you convert all your project’s Lambda function files to ESM.

Method 2: Changing File Extensions to .mjs

If you prefer not to set the entire project as an ESM, you can selectively apply ESM syntax to specific files by changing their file extensions to .mjs:

  1. Rename Lambda function files from .js to .mjs.
  2. Adjust any require statements in your code to use the ESM import syntax (covered in Step 2).

This approach is helpful if you have a mixed project or need compatibility with CommonJS and ESM modules.

Step 2: Adjusting Dependency Management

Migrating to ESM also means updating your import and export statements. Here’s how to handle dependencies and imports effectively.

From CommonJS to ECMAScript Imports

In CommonJS, you may have imported modules like this:

const express = require(‘express’);

const axios = require(‘axios’);

For ESM, replace require with import:

import express from ‘express’;

import axios from ‘axios’;

Note:

  • Default Exports: ESM requires you to use default exports when importing modules like axios.
  • Named Exports: If the module exports specific named items, use the syntax { namedExport }.

For instance, importing a named export would look like:

import { Router } from ‘express’;

Step 3: Modifying Function Exports

In addition to updating imports, you’ll need to convert module.exports statements to ESM export syntax.

Transitioning from CommonJS Exports to ESM Syntax

CommonJS exports use module.exports or exports, as shown below:

module.exports = handlerFunction;

In ESM, this syntax is replaced with export default:

export default handlerFunction;

Or, if exporting multiple items, use named exports:

export { handlerFunction, helperFunction };

After modifying exports, verify the syntax throughout the code to ensure all module.exports and exports statements are converted to ESM-compatible syntax.

Final Thoughts: Testing and Validation

After making these changes, thorough testing is essential to validate the migration. Here are a few tips:

  • Local Testing: Run Lambda functions locally using frameworks like AWS SAM CLI or Serverless Framework to test the ESM configuration.
  • AWS Console Testing: Deploy and test the function in the AWS Lambda console. Look out for runtime errors, especially related to module imports.
  • Logging and Monitoring: Use Amazon CloudWatch Logs to monitor function performance and troubleshoot issues arising from the ESM migration.
  • Optimize Dependencies: Check for deprecated or packages with limited ESM support.

Following these steps, you can successfully transition your AWS Lambda functions to ECMAScript Modules, unlocking the potential for more readable, efficient, and future-proof JavaScript code.

References

Using Node.js ES modules and top-level await in AWS Lambda

AWS Lambda now supports ES Modules and Top-Level Await for Node.js 14