Summary
The Node.js ecosystem is steadily moving toward ES Modules (ESM) as the default module system. Several key dependencies of the Azure Functions Node.js Worker have already shipped ESM-only major versions, and Node.js itself is on a path to make ESM the default. The Worker currently uses CommonJS throughout, which will become increasingly difficult to maintain.
Ecosystem Facts
Node.js: ESM as default is in progress
Key npm packages going ESM-only
Several packages in the Worker's dependency chain have shipped ESM-only versions:
- long@5 (ESM-only): Required by
@grpc/proto-loader >= 0.7.9 and protobufjs >= 8.0
- chalk@5, ora@6, globby@13, got@13, node-fetch@3, execa@6: Popular utilities that dropped CommonJS in major versions
- sindresorhus ecosystem: One of the largest package authors, ESM-only since 2021
protobufjs 8.x: ESM migration pressure on gRPC stack
protobufjs 8.0 depends on long@5 (ESM-only). This blocks upgrading:
@grpc/proto-loader >= 0.7.9 requires long@5
@grpc/proto-loader@0.8.0 requires protobufjs ^7.5.3 (still v7, but long@5)
- The Worker's proto generation script uses
pbjs -w commonjs, which would need to change to -w es6
Current Worker State
- Worker entry point (
nodejsWorker.js) uses require()
- Proto generation uses
pbjs -w commonjs output format
- webpack bundles everything into CommonJS (
libraryTarget: 'commonjs2')
- All source files use CommonJS
require()/module.exports
@grpc/grpc-js@1.8.22 and @grpc/proto-loader@0.7.8 are pinned to avoid long@5
Impact on Azure Functions Users
When the Worker migrates to ESM internally, user-facing behavior should remain compatible. However:
- Users writing ESM function apps (
type: module in package.json) are already supported
- Users should be informed about the direction of the ecosystem
- Documentation should be updated to recommend ESM for new projects
- The v4 programming model already encourages ESM patterns
Proposed Phased Approach
Phase 1: Internal ESM readiness (no user impact)
- Migrate Worker source from CommonJS to ESM (TypeScript with ESM output)
- Update webpack config or switch to ESM-compatible bundler
- Update proto generation to
-w es6
- Bump
@grpc/proto-loader and @grpc/grpc-js to latest
Phase 2: Dependency unblocking
- Upgrade protobufjs to 8.x + protobufjs-cli 2.x
- Upgrade
long to v5
- Unpin gRPC stack dependencies
Phase 3: User communication
- Update docs to recommend ESM for new projects
- Provide migration guide for CommonJS -> ESM function apps
- Announce timeline for any breaking changes
Related Issues and PRs
Summary
The Node.js ecosystem is steadily moving toward ES Modules (ESM) as the default module system. Several key dependencies of the Azure Functions Node.js Worker have already shipped ESM-only major versions, and Node.js itself is on a path to make ESM the default. The Worker currently uses CommonJS throughout, which will become increasingly difficult to maintain.
Ecosystem Facts
Node.js: ESM as default is in progress
--default-type=modulethe default (When to make--default-type=modulethe Node.js default nodejs/TSC#1445)require()of ESM modules)--experimental-default-typeand--experimental-transform-types, continuing the trend toward ESM-firstnpm init --type=module: The--init-typeflag should default tomodulenpm/cli#8159Key npm packages going ESM-only
Several packages in the Worker's dependency chain have shipped ESM-only versions:
@grpc/proto-loader >= 0.7.9andprotobufjs >= 8.0protobufjs 8.x: ESM migration pressure on gRPC stack
protobufjs 8.0 depends on
long@5(ESM-only). This blocks upgrading:@grpc/proto-loader >= 0.7.9requireslong@5@grpc/proto-loader@0.8.0requiresprotobufjs ^7.5.3(still v7, butlong@5)pbjs -w commonjs, which would need to change to-w es6Current Worker State
nodejsWorker.js) usesrequire()pbjs -w commonjsoutput formatlibraryTarget: 'commonjs2')require()/module.exports@grpc/grpc-js@1.8.22and@grpc/proto-loader@0.7.8are pinned to avoidlong@5Impact on Azure Functions Users
When the Worker migrates to ESM internally, user-facing behavior should remain compatible. However:
type: modulein package.json) are already supportedProposed Phased Approach
Phase 1: Internal ESM readiness (no user impact)
-w es6@grpc/proto-loaderand@grpc/grpc-jsto latestPhase 2: Dependency unblocking
longto v5Phase 3: User communication
Related Issues and PRs
long@5(merged)--default-type=modulethe Node.js default nodejs/TSC#1445 - When to make --default-type=module the Node.js default