TGViewer
Настоящий JavaScript Настоящий JavaScript @true_js · 5.89K subscribers
Post #3566 426
Dual package hazard в ESM/CJS: conditional exports без двух копий singleton-состояния в одном Node.js-процессе

Это важно для SDK, API clients, SSR, Node.js-сервисов и shared libraries. Частая ошибка - считать, что одинаковый TS-код в .mjs и .cjs даст общий runtime.

Где ломается
const cjs = require('@acme/sdk')
const esm = await import('@acme/sdk')


Если require попал в dist/index.cjs, а import - в dist/index.mjs, Node загрузит два разных модуля.

Итог:
* два singleton-инстанса
* две registry/cache/map
* разные подключения
* сломанный instanceof
* расходящееся состояние

Рабочая схема
Один runtime source of truth, второй формат - только фасад. Например, состояние живет в core.cjs, а ESM лишь импортирует его:

// package.json
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/core.cjs"
}
}

// core.cjs
const registry = new Registry()
module.exports = { Registry, registry }

// index.mjs
import api from './core.cjs'
export const Registry = api.Registry
export const registry = api.registry
export default api


Теперь require и import смотрят на один singleton:

cjs.registry === esm.registry // true
cjs.Registry === esm.Registry // true


Типичная ошибка
Не делайте две независимые реализации:

"import": "./dist/index.mjs",
"require": "./dist/index.cjs"


Если оба файла содержат состояние, hazard почти гарантирован. Conditional exports только маршрутизируют загрузку, но не объединяют объекты в памяти.

Практический чеклист
* закрывайте deep imports вроде @acme/sdk/dist/index.mjs
* для каждого subpath, например @acme/sdk/cache, повторяйте ту же схему
* для чистых функций риск ниже, для DI, логгеров, метрик, БД-клиентов и кэшей - критичен

Вывод:
Dual ESM/CJS-пакету нужен один общий runtime-модуль и фасадные entrypoint, а не две сгенерированные копии реализации.
More from @true_js
  1. Oct 3, 2026Post #3963
  2. Oct 2, 2026😅 Айтишник отправил в одну компанию три одинаковых резюме и только одно дошло до финала О…
  3. Oct 2, 2026Post #3961
  4. Oct 2, 2026🤣 Правильно расставленные приоритеты в моей жизни би лайк: 💥 xCode Journal
  5. Oct 1, 2026🤯 Люди взбунтовались против «пыточной для ИИ» На GitHub заметили открытый проект AI Tortu…
  6. Oct 1, 2026День в Заонежье начинается ещё в дороге. Мы встретим вас в аэропорту или на вокзале. Дальш…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →