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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions