Skip to content

Plan ESM migration for Azure Functions Node.js Worker #806

@TsuyoshiUshio

Description

@TsuyoshiUshio

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions