Reputation: 163
I am unable to use the package p-map in my Azure Function. I get the following error:
Worker failed to load function: 'serverless' with function id: '<id>'.
Result: Failure
Exception: Worker was unable to load function serverless: 'Error [ERR_REQUIRE_ESM]: require() of ES Module <es-module> from /usr/local/Cellar/azure-functions-core-tools@4/4.0.4483/workers/node/worker-bundle.js not supported.
Instead change the require of index.js in /usr/local/Cellar/azure-functions-core-tools@4/4.0.4483/workers/node/worker-bundle.js to a dynamic import() which is available in all CommonJS modules.'
The project is created by following the steps in Azure's documentation. The following is in the index.ts:
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import pMap from "p-map";
import got from "got";
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const sites = [
'https://avajs.dev',
'https://github.com'
];
const mapper = async site => {
const {requestUrl} = await got.head(site);
return requestUrl;
};
const result = await pMap(sites, mapper, {concurrency: 2});
context.res = {
// status: 200, /* Defaults to 200 */
body: result
};
};
export default httpTrigger;
My tsconfig.json looks like following:
{
"compilerOptions": {
"module": "es2020",
"target": "es2020",
"outDir": "dist",
"rootDir": ".",
"sourceMap": true,
"strict": false,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
}
}
Lastly, this is my package.json:
{
"name": "azure-functions-test",
"version": "1.0.0",
"description": "",
"type": "module",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"prestart": "npm run build",
"start": "func start",
"test": "echo \"No tests yet...\""
},
"dependencies": {
"got": "^12.0.4",
"p-map": "^5.3.0"
},
"devDependencies": {
"@azure/functions": "^3.0.0",
"typescript": "^4.0.0"
}
}
p-map is strictly an ES Module and cannot be used in CommonJS projects.
Am I missing something or is it just not possible to use ES Module packages in Azure Functions? Thanks in advance.
GitHub repository of aforementioned code to test things out locally: azure-functions-test
Upvotes: 4
Views: 2612
Reputation: 295
I used the tsup
bundler with no compromises (no ugly .js or .mjs extensions in source code, just pure ESM). I am using the Azure Functions v4 programming model, but i am sure a few tweaks would make it work for the previous programming model aswell (the one using function.json
-files).
Here is what i did:
Remove "type": "module"
from package.json
Install tsup
npm i tsup -D
Add tsup.config.ts
import { defineConfig } from 'tsup'
export default defineConfig({
// Entry file(s) to start building from.
entry: ['src/**/*.ts'],
// To output .mjs files
format: 'esm',
// Optional: Include external packages inside the bundle. This was nescessary for a monorepo package in my case.
noExternal: ['@monorepo/package'],
// Optional: Empty dist directory before build
clean: true,
})
Modify package.json
{
"main": "./dist/functions/*.mjs",
"scripts": {
"build": "tsup",
...
},
...
}
Upvotes: 0
Reputation: 1971
According to the docs on Node.js' website, specifying "type": "module"
in your package.json
should also indicate if Node should use ESM.
Here's what I did to get ESM working for my functions in my Function App:
tsconfig.json
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"moduleResolution": "Node",
"outDir": "dist",
"rootDir": ".",
"sourceMap": true,
"strict": false,
"noImplicitAny": true,
"noUnusedLocals": true
}
}
Some relevant function app settings:
WEBSITE_NODE_DEFAULT_VERSION
: ~16
(To run using Node.js 16 runtime)
FUNCTIONS_EXTENSION_VERSION
: ~4
Then make sure to import your ES-style exports with a .js
extension if your original extension is .ts
. So if you have a file called custom.ts
that has exports, then you should import them as import { something } from "custom.js";
.
And for any npm packages that use default exports (CommonJS style), you should import the package using its default export, i.e. import * as pkg from "pkg";
.
Relevant links:
https://github.com/Azure/azure-functions-nodejs-worker/issues/104
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node?tabs=v2-v3-v4-export%2Cv2-v3-v4-done%2Cv2%2Cv2-log-custom-telemetry%2Cv2-accessing-request-and-response%2Cwindows-setting-the-node-version#ecmascript-modules (Note that this doc talks about importing your ESM exports with a .mjs
extension but I didn't have to do that.)
Upvotes: 2
Reputation: 163
I resolved my issue by renaming my index.ts file to index.mts. This built a index.mjs file (after running npm run build
) in my dist folder which fixed the issue.
One thing to note is that you also have to edit your function.json's scriptFile key so it uses your .mjs file instead of non-existing .js file.
Upvotes: 0