How to make ES modules import from a Lambda layer work? - node.js

I have a lambda function in node v14 that imports AWS SDK v3 from a lambda layer.
In my function I can use my node modules from the layer only if I use CommonJS syntax:
const { parseUrl } = require('#aws-sdk/url-parser');
Using ES modules doesn't work.
import { parseUrl } from '#aws-sdk/url-parser';
It will throw an error:
"errorMessage": "Cannot find package '#aws-sdk/url-parser' imported from /var/task/index.js\nDid you mean to import #aws-sdk/url-parser/dist-cjs/index.js?"
It should work. I have "type": "module" in package.json and locally the import works.
It also starts working when I specify the full path to cjs index file:
import { parseUrl } from '/opt/nodejs/node_modules/#aws-sdk/url-parser/dist-cjs/index.js';
Which is really weird.
I checked NODE_PATH and /opt/nodejs/node_modules is there so I don't know where the problem is.
The full implementation is here so you can replicate the error:
https://github.com/simon-q/lambda-layer-es-modules-error
Is it something broken in lambda layers or am I doing something wrong?
I would really appreciate any help.
Thanks.

it's a path error for files in node_modules folder. In this link you can get more details about the problem.
I created a serverless plugin that fixes it automatically, hope it helps someone. Follow the link: https://www.npmjs.com/serverless-esm-layer

Related

Unable to import module 'lambda_function': No module named 'aws_xray_sdk'

I am trying to implement this AWS Lambda Rest API Handler in my lambda code to handle proper response code. For this I needed to repackage the library aws_lambda_powertools and add as a layer in lambda function.
All the import related to this lib below are working.
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext
But When I am creating object of above Tracer class below its giving error(Rest two commented object logger and app are working fine.
tracer = Tracer()
# logger = Logger()
# app = APIGatewayRestResolver()
Error I am getting while declaring tracer object is below:
Response
{
"errorMessage": "Unable to import module 'lambda_function': No module named 'aws_xray_sdk'",
"errorType": "Runtime.ImportModuleError",
"stackTrace": []
}
Function Logs
OpenBLAS WARNING - could not determine the L2 cache size on this system, assuming 256k
START RequestId: ae8b006b-e7f7-495b-99a0-eb5231c3f81c Version: $LATEST
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'aws_xray_sdk'
Traceback (most recent call last):
I tried to install pip install aws_xray_sdk and repackaged it and re-added to layer still its giving the same error.
Can anyone help me with this? I am new to lambda. Thanks in advance.
Fixed the error by using AWS Arn arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPythonV2:18📋 instead of using my own custom repackaged library layer.
Reference Link:
https://awslabs.github.io/aws-lambda-powertools-python/2.6.0/
Tracing (like validation and parsing) requires additional dependencies. They're not included by default in an attempt to keep the resulting package as small as possible.
When packaging with AWS SAM, I'm using this in my my_code/requirements.txt, which I then pip install in my local virtual env:
aws-lambda-powertools[parser, validation, tracer]==2.6.0
Additionally, I'm including this in tests/requirements.txt, which I also pip install locally but which is not picked up by SAM (keeping the image small again, and it's not required at runtime anyhow).
aws-lambda-powertools[aws-sdk]==2.6.0
pytest==7.2.1
In version 2.0 the xray SDK is not included by default, as this would introduce a size overhead even for those who would not be using Tracer.
To solve this problem, just put in your requirements.txt the tracer dependency using aws-lambda-powertools[tracer] or all dependencies using aws-lambda-powertools[all].
Refer This link:
https://github.com/awslabs/aws-lambda-powertools-python/issues/1872

Convert old CJS module into ESM and import into TS files

I am wanting to convert an old module, https://github.com/capaj/object-resolve-path, into ESM so I can use it via an import statement, in order to move all my NodeJS Lambda functions to ESM.
I have forked the repo, and changed the 2 main .js files to .mjs, updated the exports, as well as update the main property in package.json to point to the object-resolve-path.mjs file.
In my NodeJS Lambda function, I have then installed the fork via NPM from my private repo, which pulls the new code in.
However, when I try to import the package in my code now, using import * as resolvePath from 'object-resolve-path'; I get an error:
Could not find a declaration file for module 'object-resolve-path'.
What am I missing? The module isn't written in TS, so why is it asking for a declaration file?

'ReferenceError: require is not defined' while importing fs module

I am new to NodeJS. I was importing the 'fs' module in NodeJS and this happened.
Is this because of the new import syntax in the current versions?
What went wrong?
Thanks in advance!
This is because something is telling nodejs that this is the newer ESM module. This could be your package.json file or something else. In an ESM module file, you use import, not require() to load modules.
You can see in the stack trace where it shows Object.loadESM and that's how you know it is trying to load this module as an ESM module.
With an ESM module, perhaps you want this:
import fs from "fs";
or
import * as fs from'fs';
Or, if you intend to use a CommonJS module instead (where you can use require()), then we need to see your package.json file to figure out why the loader is attempting to load your file as an ESM module.

TypeScript - how to import 'os' module

I'm learning Typescript. To do this, I'm building a basic utility app with Node for myself. For this app, I need to use Node's OS Module. My question is, how do I import this module?
In my Typescript file, I have the following:
import { os } from 'os';
This line generates the error: "Cannot find module 'os'". What am I missing?
This line generates the error: "Cannot find module 'os'". What am I missing?
The correct code is
import os from 'os';
Also make sure you have npm i #types/node
More
Some notes I wrote on NodeJS quickstart : https://basarat.gitbook.io/typescript/docs/quick/nodejs.html
Just to update this entry:
import * as os from 'os';
and later, you can use:
const hostname = os.hostname();

Import native node modules correctly in Typescript

I've been using node for quite a while now (for my backends) and typescript with ionic (for frontend). On Ionic i realize I have managed to avoid many pitfalls and errors just because of TypeScript. I have hence decided to convert all my backends that are in pure JS to TypeScript.
The first obstacle I've run into is how to import native node modules like http, os and child_process, among others, correctly.
On most modules you can usually do something like import { some_export } from 'that_module'. I can also see the type definitions for node in the #types/ repo. I've tried import { http, os } from 'node' but I get a complaint that
/node_modules/#types/node/index.d.ts is not a module
My question hence is how should I import native node modules?
I've managed to solve this issue thanks to some light reading from this simple tutorial
To my understanding, the native modules are standalone modules that are not namespaced under node. You should therefore import from them directly.
Simply done so:
import * as http from "http";
import * as os from "os";
import * as path from "path";
.
.
.
and so on

Resources