I am looking to make use of the native import/export that comes with ES6.
I am using Serverless Containers within AWS Lambda.
I have my Dockerfile
which looks like this:
FROM public.ecr.aws/lambda/nodejs:14 COPY app ./ RUN npm install CMD [ "app.handler" ]
I then have an app
directory with my application code. The app.js
code looks like this:
import { success } from './utils/log'; exports.handler = async () => { success('lambda invoked'); const response = 'Hello World'; return { statusCode: 200, body: JSON.stringify(response), isBase64Encoded: false, }; };
As you can see from this line import { success } from './utils/log';
I am making use of native imports.
In my package.json I specify this:
"type": "module"
As I need to tell my application this is a module and I would like imports natively. If I don’t specify this, I get:
{ "errorType": "Runtime.UserCodeSyntaxError", "errorMessage": "SyntaxError: Cannot use import statement outside a module", "stack": [ "Runtime.UserCodeSyntaxError: SyntaxError: Cannot use import statement outside a module", " at _loadUserApp (/var/runtime/UserFunction.js:98:13)", " at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)", " at Object.<anonymous> (/var/runtime/index.js:43:30)", " at Module._compile (internal/modules/cjs/loader.js:1063:30)", " at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)", " at Module.load (internal/modules/cjs/loader.js:928:32)", " at Function.Module._load (internal/modules/cjs/loader.js:769:14)", " at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)", " at internal/main/run_main_module.js:17:47" ] }
So, I specify it, telling Lambda this is a module. However, for the life of me I can’t get it to work, I am seeing this error:
{ "errorType": "Error", "errorMessage": "Must use import to load ES Module: /var/task/app.jsnrequire() of ES modules is not supported.nrequire() of /var/task/app.js from /var/runtime/UserFunction.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.nInstead rename app.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /var/task/package.json.n", "code": "ERR_REQUIRE_ESM", "stack": [ "Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /var/task/app.js", "require() of ES modules is not supported.", "require() of /var/task/app.js from /var/runtime/UserFunction.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.", "Instead rename app.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /var/task/package.json.", "", " at Object.Module._extensions..js (internal/modules/cjs/loader.js:1080:13)", " at Module.load (internal/modules/cjs/loader.js:928:32)", " at Function.Module._load (internal/modules/cjs/loader.js:769:14)", " at Module.require (internal/modules/cjs/loader.js:952:19)", " at require (internal/modules/cjs/helpers.js:88:18)", " at _tryRequire (/var/runtime/UserFunction.js:75:12)", " at _loadUserApp (/var/runtime/UserFunction.js:95:12)", " at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)", " at Object.<anonymous> (/var/runtime/index.js:43:30)", " at Module._compile (internal/modules/cjs/loader.js:1063:30)" ] }
It looks like /var/runtime/UserFunction.js
is calling my app handler as a require and a module. However, I have no control over /var/runtime/UserFunction.js
(I don’t believe?). In my Dockerfile
I have specified Node14
. I don’t quite know where I have gone wrong?
What I am looking to do is run the latest and greatest of Node14 (such as imports) without Babel/Transpiler that “bloat” my code. If someone could point me in the right direction of where I have gone wrong, it would be appreciated.
Advertisement
Answer
It appears that since yesterday there finally is native support for the ES6 module syntax in Node 14 lambdas – see https://aws.amazon.com/blogs/compute/using-node-js-es-modules-and-top-level-await-in-aws-lambda