- npm забезпечує керування основними залежностями, керування версіями та скриптами, необхідні для структурування проектів, орієнтованих на середовище виконання Cloudflare.
- workerd відрізняється від Node.js тим, що зосереджується на безпечних API, що відповідають веб-стандартам, і вимагає рівнів сумісності для модулів, специфічних для Node.
- Новий режим nodejs_compat_v2 поєднує нативні реалізації C++, поліфіли unenv та макети, щоб значно покращити підтримку пакетів npm.
- Псевдонімування модулів та вибіркові поліфіли дозволяють налаштовувати поведінку для несумісних залежностей та розблоковувати більше екосистеми npm на Workers.

Поєднання екосистеми npm з середовищем виконання workerd від Cloudflare може звучати дещо загадково, але під капотом вся суть у тому, щоб код і пакети в стилі Node.js працювали безперебійно на веб-орієнтованій платформі. Cloudflare Workers і Pages тепер пропонують покращений рівень сумісності з Node.js, який дозволяє завантажувати набагато більше npm-пакетів, не стикаючись з низькорівневими відмінностями між середовищами виконання.
У цій статті пояснюється, як npm-пакети перетинаються з workerd та новими прапорцями сумісності., що показує, чому деякі пакети раніше давали збій і що змінюється з nodejs_compat_v2 режим. Ви також побачите, як поведінка npm (встановлення, оновлення, скрипти та типи залежностей) вписується в проекти, орієнтовані на workerd, щоб ви могли впевнено структурувати програми та уникати несподіванок.
Що таке npm і чому це важливо для worker'а
npm залишається фактичним менеджером пакетів для Node.js, що забезпечує роботу як серверного коду, так і значної частини сучасних інструментів для фронтенду. Спочатку він був простим менеджером залежностей, але швидко перетворився на універсальний реєстр та CLI, з якими практично кожен розробник JavaScript стикається щодня.
Реєстр npm містить мільйони пакетів, що означає, що, ймовірно, існує бібліотека майже для будь-якої проблеми: HTTP-клієнти, автентифікація, драйвери баз даних, інструменти збірки, фреймворки для тестування тощо. Для workerd та Cloudflare Workers ця екосистема є одночасно благословенням і викликом: ви отримуєте доступ до багатьох інструментів, але багато з них були створені з урахуванням середовища виконання Node.js, а не веб-стандартного середовища.
npm однаково важливий для робочих процесів фронтенду, де пакетери, транспілери та лінтери встановлюються як залежності часу розробки. Незалежно від того, чи створюєте ви React SPA, чи Worker-скрипт, який працює на workerd, ви, ймовірно, використовуватимете npm (або Yarn/pnpm) для керування залежностями та скриптами.
По суті, npm автоматизує встановлення, оновлення та відстеження залежностей., зберігаючи модулі в node_modules та вимоги до запису в package.jsonДля Worker-ів на основі workerd ваша конфігурація npm виглядає знайомою, але середовище виконання вашого коду — це рушій workerd, а не сам Node.js.
Альтернативи, такі як Yarn та pnpm, пропонують різні інтерфейси командного рядка та характеристики продуктивності., але коли орієнтовано на workerd, концепція та сама: менеджер пакетів вирішує модулі, тоді як інструменти збірки та прапорці сумісності Cloudflare визначають, як ці модулі виконуються у середовищі виконання Worker.
Як працює встановлення залежностей за допомогою npm

Виконання стандартної команди npm install заповнює ваш node_modules шляхом читання списків залежностей та витягування кожного переліченого пакета разом з його транзитивними залежностями, щоб вам не доводилося вручну переслідувати вкладені вимоги.
Щоб додати нову бібліотеку, зазвичай виконується одна команда встановлення, а починаючи з npm 5, він автоматично додається до dependencies розділ package.json якщо ви не переосмислите цю поведінку.
npm підтримує прапорці, які класифікують, як пакет використовується у вашому проєкті., що корисно, коли ви орієнтуєтесь на середовища виконання, такі як workerd, де вам можуть знадобитися різні пакети або процеси збірки:
--save-devдодає пакет доdevDependencies, позначаючи його як необхідний лише під час розробки або етапів збірки, таких як запускачі тестів або збирачі.--no-saveвстановлюється без змінpackage.json, зручно для швидких експериментів або одноразових команд.--save-optionalпоміщає пакет уoptionalDependencies, тому невдалі встановлення не переривають весь процес.--no-optionalзапобігає встановленню необов'язкових залежностей, зменшуючи обсяг пам'яті або уникаючи проблемних необов'язкових пакетів на деяких платформах.
Різниця між dependencies та devDependencies має значення під час будівництва для працівників, оскільки зазвичай лише залежності середовища виконання потребують об'єднання в пакети та доставки; залежності від розробки видаляються під час збірки, що зменшує розмір розгортань.
Додаткові залежності забезпечують гнучку обробку збоїв, але ваш код має перевірити їх доступність, перш ніж покладатися на них. Це допомагає, коли пакет має використовувати різні реалізації в Node.js та workerd або використовувати резервний варіант, коли нативний модуль не підтримується.
Керування оновленнями та версіями в npm-проектах
Команда update в npm оновлює пакети відповідно до оголошених вами діапазонів semver., сканування встановлених модулів та їх оновлення до найновіших дозволених версій як для прямих, так і для вкладених залежностей.
Ви також можете оновити окремий пакет за потреби, корисно, якщо бібліотека випускає виправлення помилки або покращення, яке впливає на ваш Worker або його сумісність із середовищами виконання, відмінними від Node, такими як workerd.
npm дотримується семантичного версіонування, що дозволяє точно контролювати межі оновлення, що критично важливо, коли ваш Worker залежить від бібліотеки, прив'язаної до певної основної версії, або коли критичні зміни вносяться в початковий етап.
Блокування версій та використання файлів блокування забезпечує відтворюваність збірок, тому команди та середовища неперевершеної інтеграції створюють однаковий графік залежностей для локальних працівників розробки, проміжної та виробничої обробки.
npm-скрипти та автоматизація в робочих процесах на основі workerdu
Команда scripts поле в package.json служить вашим виконавцем скриптів, що дозволяє вам зіставляти короткі імена з довшими командами CLI та виконувати їх за допомогою npm run <script-name>.
Сучасні проекти використовують npm-скрипти для обгортання інструментів збірки, тестів та пакетів., а проекти Worker, орієнтовані на workerd, зазвичай таким чином надають доступ до команд пакетування, перевірки типів та розгортання.
Поширеною схемою є підключення пакетера або виконавця завдань через запис скрипта, перетворюючи складний виклик CLI на просту команду, доступну для всієї команди.
Скрипти стають потужними в поєднанні з прапорцями сумісності Node.js для workerd., оскільки скрипти можуть контролювати, які параметри сумісності активні та які поліфіли або псевдоніми застосовуються перед об'єднанням фінального Worker.
workerd проти Node.js: розуміння розриву у виконанні
workerd — це рушій JavaScript та WebAssembly з відкритим кодом, оптимізований для виконання на периферії, побудований на V8 — тому ж низькорівневому рушії, що використовується Node.js та Chromium, — але розроблений з різними умовами роботи та моделями довіри.
Node.js був створений для запуску JavaScript на хост-ОС та надає потужні системні API. такий як process, fs та низькорівневі криптоутиліти, що робить його ідеальним для серверів, інтерфейсів командного рядка та бекенд-інфраструктури з прямим доступом до машин.
workerd налаштовано для запуску ненадійного коду в багатокористувацьких периферійних процесах, з акцентом на ізоляції та веб-орієнтованих API, таких як fetch, потоки та прив’язки, специфічні для Cloudflare (KV, Durable Objects, внутрішній RPC), а не доступ до файлової системи чи процесів.
Для покращення сумісності Cloudflare допоміг створити WinterCG, метою якого є узгодження серверних середовищ виконання JavaScript та веб-платформи навколо спільного набору API, щоб програми поводилися однаково в різних середовищах.
Однак багато npm-пакетів припускають середовище Node.js та імпортують вбудовані модулі. як events, fs, net, crypto or bufferБез рівня сумісності цей імпорт може завершитися невдачею, оскільки workerd не надає автоматично модулі, специфічні для вузла.
Від поліфілів до вбудованих API Node.js у Workers
Cloudflare спочатку покладався на поліфіли для поєднання Node.js та workerd., використовуючи реалізації JavaScript для імітації API Node. У 2021 році Workers отримали режим сумісності на основі поліфілів, і Wrangler почав впроваджувати ці поліфіли, коли node_compat = true було встановлено wrangler.toml.
З node_compat = true, Wrangler об'єднав JS-реалізації для кількох основних модулів Node, використовуючи плагіни, такі як @esbuild-plugins/node-globals-polyfill та rollup-plugin-node-polyfills тому імпорт, такий як import EventEmitter from 'events' міг би працювати в Робітнику.
Поліфіли дозволяли багатьом npm-пакетам запускатися на Workers, але мали обмеження., особливо для модулів, що виконують важку бінарну або крипто-операцію, де нативні реалізації набагато швидші та точніші, ніж чисті JS-шайми.
Buffer є яскравим прикладом функції, яку важко ефективно імітувати в умовах користувача, оскільки такі операції, як копіювання та перетворення кодування, отримують користь від оптимізованих нативних реалізацій. Те саме стосується API, таких як Crypto та AsyncLocalStorage.
Щоб покращити продуктивність та повноту, Cloudflare почав вбудовувати деякі Node API у середовище виконання. у 2023 році через nodejs_compat прапор; ці основні модулі реалізовані на C++ та відображаються у Workers для кращої точності, ніж JS поліфіли.
Під час використання вбудованих модулів Node у Workers їх слід імпортувати разом із node: префіксНаприклад import { Buffer } from 'node:buffer', що сигналізує про залежність від модуля, що надається середовищем виконання, а не від пакета реєстру.
Чому багато npm-пакетів все ще не вдавалося виконати роботу з ранніми версіями nodejs_compat
Рано nodejs_compat все ще спричиняло збої, оскільки багато бібліотек використовували імпорт без префікса, наприклад, import { EventEmitter } from 'events', які пакетер трактував як модулі файлової системи та не зміг вирішити, коли вони були відсутні.
Під час імпорту драйверів траплялася поширена помилка, така як pg що залежать від основних модулів без префікса, що призводить до скарг на те, що модуль не знайдено на етапах збірки, хоча Node вважає його вбудованим.
Розробники зіткнулися з компромісом між невеликою підтримкою нативного API та повільнішим, неповним набором поліфілів, а також відсутні глобальні змінні, такі як process що багато бібліотек припускали, що вони існуватимуть на глобальному об'єкті.
Через ці труднощі було важко надійно використовувати складні npm-пакети на workerd., особливо коли непрямі залежності очікували певних модулів Node або глобальних змінних, що призводило до збоїв під час збірки до того, як Worker міг запуститися.
Новий nodejs_compat_v2: покращена підтримка npm на workerd
nodejs_compat_v2 поєднує нативні реалізації з поліфілами на вимогу, що значно збільшує придатність екосистеми npm для використання на Workers, вирішуючи, коли використовувати модулі на основі C++, JS-поліфіли або легкі заглушки, що забезпечують успішний імпорт.
Увімкніть цей режим, додавши compatibility_flags = ["nodejs_compat_v2"] до wrangler.toml, що змінює як спосіб, у який середовище виконання надає доступ до Node API, так і те, як Wrangler об'єднує імпорт та залежності в стилі Node.
Багато пакетів, які раніше не вдавалося імпортувати, тепер завантажуються коректно у версії 2., включаючи такі бібліотеки, як body-parser, jsonwebtoken, got, passport, knex та інші — зменшення помилок під час збірки на користь локалізованого зворотного зв'язку під час виконання для непідтримуваних операцій.
У версії 2 ви можете писати імпорт, наприклад import { Buffer } from 'buffer' і середовище виконання ефективно маршрутизує їх до реалізацій, що підтримуються C++; водночас, модулі, такі як net може бути полізаповнений Wrangler за допомогою unenv, що дозволяє нативним та поліфілованим API співіснувати без конфліктів.
Wrangler тепер вставляє поліфіли лише для тих модулів Node, які ваш Worker фактично використовує., зменшуючи розміри пакетів шляхом аналізу коду та залежностей, замість того, щоб постачати повний набір поліфілів за замовчуванням.
unenv поліфіли та імітовані Node.js API
Коли нативна реалізація або зрілий поліфіл недоступні, unenv надає імітовані модулі які надають доступ до тих самих інтерфейсів, але або виконують операції без операцій, або викликають описові помилки під час виконання, коли викликаються непідтримувані методи.
Такі помилки, як [unenv] <method name> is not implemented yet! є більш чіткими та локалізованими, дозволяючи Worker запускатися та завершувати роботу лише на сайті виклику, який ініціює несумісність, замість переривання під час збірки.
Імітовані модулі дозволяють імпортувати та використовувати пакети, які частково залежать від функцій Node., за умови уникнення непідтримуваних частин; безпечні частини можуть виконуватися, тоді як файлово-залежні операції викликають помилки лише під час їх виконання.
Раніше будь-який імпорт fs може зробити пакет непридатним для використання в Workers, але з nodejs_compat_v2 а unenv імітує, що залежність може бути включена та викликана вибірково.
Цей перехід від зворотного зв'язку під час збірки до зворотного зв'язку під час виконання спрощує налагодження, оскільки ви можете точно визначити, який метод і стек викликів викликають несумісність, а потім реструктуризувати код або надати цільові поліфіли чи псевдоніми як тимчасове рішення.
Псевдонім модулів: налаштування поведінки для проблемних залежностей
Псевдонім модулів дозволяє перенаправляти імпорт до ваших власних реалізацій, налаштований у wrangler.toml, тому проблемний шлях до модуля перетворюється на користувацький файл замість поведінки за замовчуванням.
Якщо бібліотека залежить від fs.readFile але вам не потрібен доступ до файлової системи, псевдонім "fs" до ./fs-polyfill і розкрити звичай readFile який реєструє, викликає інший API або зчитує з KV.
Після псевдонімізації імпортується так import { readFile } from 'fs' звернутися до вашого модуля та обійти значення за замовчуванням unenv, запобігаючи помилкам «ще не реалізовано», зберігаючи при цьому пакет-споживач незмінним.
Псевдонім також допомагає, коли залежність завантажує специфічні для Node пакети, такі як node-fetch, який може спиратися на непідтримувані модулі Node; ви можете зіставити "node-fetch" до модуля, який реекспортує глобальний fetch.
Такі інструменти, як nolyfill зробити схеми реекспорту простими, що дозволяє вам скоротити несумісні реалізації та зберегти функціональність залежних пакетів на workrd.
Псевдонім модулів діє як гнучкий рівень сумісності поверх nodejs_compat_v2, що дозволяє вам адаптувати певні пакети без їх переписування чи розгалуження.
Продуктивність, співпраця в екосистемі та розгортання
Критичні API Node.js, реалізовані нативно на C++ всередині workerd, забезпечують кращу продуктивність та коректність., та модулі, подібні до Buffer, AsyncLocalStorage та Crypto скористатися перевагами цих нативних реалізацій, обгорнутих JS-шайбами, що відображають поведінку Node.
Cloudflare сприяє unenv, який забезпечує розумні поліфіли та макети на вимогу, оскільки він орієнтований на кілька середовищ виконання та був прийнятий такими проектами, як Nuxt та Nitro; додавання лише необхідних поліфілів забезпечує легкість додатків та сприяє конвергенції екосистем.
Ширша мета — переносимість коду в стилі Node між різними середовищами виконання., тож розробники можуть написати один раз і запускати на Node.js, workerd або інших середовищах з мінімальними труднощами, автоматично вибираючи поліфіли та нативні функції на основі використання.
Покращена поведінка в nodejs_compat_v2 очікується, що з часом стане за замовчуванням коли дата сумісності вашого Worker досить недавня, щоб більше Worker прозоро отримали вигоду від сильнішої сумісності з npm без додаткового налаштування.
Розробникам рекомендується спробувати покращену сумісність з Node.js та оновити свої wrangler.toml, повідомляючи про несумісності або помилки, що залишилися, через канали зворотного зв'язку, щоб прогалини можна було усунути.
Поєднання зрілого управління залежностями npm, безпечного веб-орієнтованого середовища виконання workerd та рівня сумісності Node.js, що постійно розвивається надає вам практичний шлях для повторного використання величезної кількості існуючого JavaScript-коду, використовуючи переваги edge-виконання, ізоляції та функцій платформи Cloudflare. Завдяки розумним поліфілам, нативним реалізаціям, mocking та аліасингу модулів, що є у вашому розпорядженні, стає набагато реалістичніше впроваджувати складні npm-пакети у ваші Workers-проекти, не постійно борючись із середовищем виконання.