Plan ESM migration for Azure Functions Node.js Worker

Aperta
#807 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
5/5
Tempo stimato
Più di una settimana
Idoneità per principianti
30/100
Tipo di issue
Refactoring
Chiarezza
Abbastanza chiara
Stato di attività
Tranquilla
Stack tecnologico
node.js, typescript, webpack

Direzione di ricerca

Inizia leggendo nodejsWorker.js e loadScriptFile.ts, quindi esamina l'attuale generazione dei proto e la configurazione di webpack. Esamina le issue correlate #791 e #804 e identifica i controlli di compatibilità necessari per le applicazioni cliente CJS ed ESM. Il lavoro sarà considerato completato quando sarà concordato un piano di migrazione circoscritto, con fasi, modifiche alle dipendenze e criteri di convalida.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

feature

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.

Key Insight: Worker ESM migration does NOT break customer code

The Worker loads customer code via dynamic import() or require() based on the customer's own package.json "type" field and file extension (.mjs/.cjs). See loadScriptFile.ts:

if (isESModule(filePath, packageJson)) {
    script = await eval('import(fileUrl.href)');  // ESM customer code
} else {
    script = require(filePath);                    // CJS customer code
}

The Worker's internal module system and the customer's module system are independent. Node.js supports CJS and ESM coexisting in the same process. Therefore:

Layer Current After Worker ESM migration
Worker (internal) CJS ESM
@azure/functions library Dual (CJS + ESM) Maintain dual support
Customer code CJS or ESM (user choice) No change

This means:

  • Worker can safely migrate to ESM-only internally — it is not exposed to customers
  • @azure/functions library should maintain dual CJS/ESM support in the current major version (4.x)
  • Library 5.x can go ESM-only with sufficient migration period (keep 4.x CJS support for 1+ year)

Ecosystem Facts

Node.js: ESM as default is in progress
  • Node.js TSC discussed making --default-type=module the default (nodejs/TSC#1445)
  • Node.js 22.7.0+ can auto-detect module format (require() of ESM modules)
  • Node.js 26.0.0 (released May 2026) removed --experimental-default-type and --experimental-transform-types, continuing the trend toward ESM-first
  • PR to mark CommonJS as legacy in Node.js docs: nodejs/node#57460
  • npm CLI issue to default npm init --type=module: npm/cli#8159
  • Node.js continues to support CommonJS but is shifting it to opt-in rather than opt-out
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/[email protected] 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/[email protected] and @grpc/[email protected] are pinned to avoid long@5

Migration Strategy

Phase 1: Worker internal ESM migration (no customer impact)
  • Migrate Worker source from CommonJS to ESM (TypeScript with ESM output)
  • Update proto generation from pbjs -w commonjs to pbjs -w es6
  • Update webpack config (libraryTarget) or switch to ESM-compatible bundler
  • Bump @grpc/proto-loader to 0.8.x and @grpc/grpc-js to latest
  • Upgrade protobufjs to 8.x, protobufjs-cli to 2.x, long to v5
  • Validation: E2E test with both CJS and ESM customer function apps to confirm backward compatibility
  • Target: Can be done as a focused effort with comprehensive testing
Phase 2: Library dual support (current 4.x)
  • Ensure @azure/functions 4.x continues to provide dual CJS/ESM exports
  • Validate that ESM Worker + CJS library + CJS customer code works end-to-end
  • Validate that ESM Worker + ESM library + ESM customer code works end-to-end
Phase 3: Library ESM-only (future 5.x, customer impact)
  • Release @azure/functions 5.x as ESM-only
  • Maintain @azure/functions 4.x with CJS support for at least 1 year after 5.x release
  • Provide clear migration documentation for customers
  • Announce timeline well in advance
  • This is the only phase that impacts customers

Related Issues and PRs

  • #791 - Add ESM support for @azure/functions-core virtual module (open PR)
  • #804 - protobufjs bump blocked protobufjs 8.x due to ESM-only long@5 (merged)
  • #803 - protobufjs vulnerability fix (closed)
  • #344 - Add support for ES Modules (closed)
  • #531 - Respect package.json type: module for ESM Functions (closed)
  • #104 - Add ES6 Style Exports (open, 2018)
  • nodejs/TSC#1445 - When to make --default-type=module the Node.js default
  • nodejs/node#57460 - Mark CommonJS as legacy in docs
Lingua principale
TypeScript
Stelle
110
Fork
52
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Azure/azure-functions-nodejs-worker

Tutte le issue di Azure/azure-functions-nodejs-worker

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.