Что нового в Node.js 20
Версия 20 от Node. js была выпущена 18 апреля 2023 года. В ней рассматриваются некоторые проблемы и критические замечания, которые уже “решены” Deno и Bun, включая новую модель разрешений и стабильную встроенную программу запуска тестов. В этой статье рассматриваются новые возможности, доступные разработчикам, использующим наиболее часто используемую в мире среду выполнения JavaScript.
График выпуска Node. js
имеет шестимесячный график выпуска:
- Апрельские выпуски с четными номерами (14, 16, 18 и т. д. ) стабильны и получают обновления долгосрочной поддержки (LTS) в течение трех лет.
- Октябрьские выпуски с нечетными номерами (15, 17, 19 и т. д. ) являются более экспериментальными, и обновления часто заканчиваются через год.
В общем, вам следует выбрать версию LTS с четным номером, если только вам не требуется определенная функция в экспериментальном выпуске и вы не собираетесь обновить ее позже. Тем не менее, Node. js 20 является новым, и веб-сайт рекомендует вы продолжаете использовать версию 18, в то время как команда разработчиков исправляет все проблемы, возникшие в последнее время.
Node. js 20 имеет следующие новые функции …
Новая модель разрешений
Запущенный узел somescript. js это не лишено риска. Скрипт может делать все, что угодно: удалять важные файлы, отправлять личные данные на сервер или запускать майнер криптовалюты в дочернем процессе. Трудно гарантировать, что ваш собственный код ничего не нарушит: можете ли вы быть уверены, что все модули и их зависимости безопасны?
Новый (экспериментальный) Node. js Модель разрешений ограничивает то, что может делать скрипт. Чтобы использовать его, добавьте флаг --experimental-permission в командную строку вашего узла, за которым следует:
- --allow-fs-read для предоставления доступа на чтение к файлам. Вы можете ограничить доступ для чтения к: конкретные каталоги: --allow-fs-read=/tmp/ конкретные файлы: --allow-fs-read=/home/me/data. json или шаблоны файлов с подстановочными знаками: --allow-fs-read=/home/me/*. json
- --allow-fs-write для предоставления доступа на запись к файлам с идентичными шаблонами каталогов, файлов или подстановочных знаков.
- --allow-child-process, позволяющий дочерним процессам, таким как выполнение других скриптов, возможно, написанных на других языках.
- --allow-worker разрешать рабочие потоки, которые выполняют Node. js код выполняется параллельно основному потоку обработки.
В следующем примере, somescript. js может читать файлы в каталоге /home/me/data/:
node --experimental-permission --allow-fs-read=/home/me/data/ somescript.js
Любая попытка записать файл, выполнить другой процесс или запустить web worker вызывает ошибку ERR_ACCESS_DENIED.
Вы можете проверить разрешения в своем приложении, используя новый объект process. permission. Например, вот как проверить, может ли скрипт записывать файлы:
process.permission.has('fs.write');
Вот как проверить, может ли скрипт выполнять запись в определенный файл:
if ( !process.permission.has('fs.write', '/home/me/mydata.json') ) { console.error('Cannot write to file'); }
Управление разрешениями JavaScript было впервые введено компанией Deno, которая предлагает детальный контроль над доступом к файлам, окружающей среде переменные управления, информация об операционной системе, измерение времени, сеть, динамически загружаемые библиотеки и дочерние процессы. Node. js является небезопасным по умолчанию, если вы не добавите флаг --experimental-permission. Это менее эффективно, но гарантирует, что существующие скрипты будут продолжать выполняться без изменений.
Native Test Runner
Исторически сложилось так, Node. js время выполнения было минимальным, чтобы разработчики могли выбирать, какие инструменты и модули им требуются. Для запуска тестов кода требовался сторонний модуль, такой как Mocha, AVA или Jest. Несмотря на то, что это привело к большому выбору, принять наилучшее решение может быть трудно, а переключение инструментов может оказаться непростым делом.
Другие среды выполнения придерживались альтернативной точки зрения и предлагали встроенные инструменты, которые считались необходимыми для разработки. Deno, Bun, Go и Rust предлагают встроенные тестовые программы. У разработчиков есть выбор по умолчанию, но они могут выбрать альтернативу, если к их проекту предъявляются особые требования.
Node. js 18 представил экспериментальный test runner, который теперь стабилен в версии 20. Теперь нет необходимости устанавливать сторонний модуль, и вы можете создавать тестовые сценарии:
- в каталоге /test/ вашего проекта,
- присвоив файлу имя test. js , test. mjs или test. cjs
- с использованием test- в начале имени файла — например test-mycode. js
- используя test в конце имени файла с предшествующей точкой (. ), дефисом (-) или подчеркиванием (_) — такие, как mycode-test. js , mycode_test. cjs или mycode. test. mjs
Затем вы можете импортировать node:test и node:assert и записать тестовые функции:
// test.mjs import { test, mock } from 'node:test'; import assert from 'node:assert'; import fs from 'node:fs'; test('my first test', (t) => { assert.strictEqual(1, 1); }); test('my second test', (t) => { assert.strictEqual(1, 2); }); // asynchronous test with mocking mock.method(fs, 'readFile', async () => 'Node.js test'); test('my third test', async (t) => { assert.strictEqual( await fs.readFile('anyfile'), 'Node.js test' ); });
Запустите тесты с помощью node --test test. mjs и проверьте выходные данные:
✔ my first test (0.9792ms) ✖ my second test (1.2304ms) AssertionError: Expected values to be strictly equal: 1 !== 2 at TestContext.<anonymous> (test.mjs:10:10) at Test.runInAsyncScope (node:async_hooks:203:9) at Test.run (node:internal/test_runner/test:547:25) at Test.processPendingSubtests (node:internal/test_runner/test:300:27) at Test.postRun (node:internal/test_runner/test:637:19) at Test.run (node:internal/test_runner/test:575:10) at async startSubtest (node:internal/test_runner/harness:190:3) { generatedMessage: false, code: 'ERR_ASSERTION', actual: 1, expected: 2, operator: 'strictEqual' } ✔ my third test (0.1882ms) ℹ tests 3 ℹ pass 2 ℹ fail 1 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 72.6767
Вы можете добавить флаг --watch для автоматического повторного запуска тестов при изменении файла:
node --test --watch test.mjs
Вы также можете запустить все тесты, найденные в проекте:
node --test
Native testing является желанным дополнением к Node. js время выполнения. Здесь меньше необходимости изучать различные сторонние API, и у меня больше нет оправданий, когда я забываю добавлять тесты в небольшие проекты!
Компиляция одного исполняемого приложения
Node. js для выполнения проектов требуется среда выполнения. Это может стать препятствием при распространении приложений среди платформ или пользователей, которым нелегко устанавливать или обслуживать Node. js.
Версия 20 предлагает экспериментальную функцию, которая позволяет вам создать единое исполняемое приложение (SEA), которое вы можете развернуть без зависимостей. В руководстве объясняется этот процесс, хотя он немного запутан:
- У вас должен быть проект с одним скриптом ввода. Он должен использовать CommonJS, а не ES-модули.
- Создайте конфигурационный файл JSON, используемый для сборки вашего скрипта в большой двоичный объект, который запускается внутри среды выполнения. Например, sea-config. json:
{ "main": "myscript.js", "output": "sea-prep.blob" }
3. Сгенерируйте большой двоичный объект с помощью node --experimental-sea-config sea-config. json.
4. В соответствии с вашей операционной системой, затем вы должны скопировать узел исполняемый файл, удалите подпись двоичного файла, вставьте большой двоичный объект в двоичный файл, повторно подпишите его и протестируйте получившееся приложение.
Пока это работает, вы ограничены старыми проектами CommonJS и можете ориентироваться только на ту же ОС, которую используете. Это наверняка улучшится, учитывая, что превосходный компилятор Deno может создать исполняемый файл для любой платформы с помощью одной команды из исходных файлов JavaScript или TypeScript.
Вы также должны быть осведомлены о размере результирующего исполняемого файла. Один console. log('Hello World'); генерирует файл размером 85 МБ, потому что Node. js (и Deno) необходимо добавить весь движок JavaScript версии 8 и стандартные библиотеки. Рассматриваются варианты уменьшения размера файлов, но вряд ли он опустится ниже 25 МБ.
Компиляция нецелесообразна для небольших инструментов командной строки, но это более приемлемый вариант для более крупных проектов, таких как полноценное веб-серверное приложение.
Обновленный движок JavaScript версии 8
Node. js 20 включает в себя последнюю версию движка V8, который включает в себя следующие функции JavaScript:
- String.prototype.isWellFormed(): возвращает значение true, если строка правильно сформирована и не содержит одиночных (непарных) суррогатных символов.
- String.prototype.toWellFormed(): возвращает правильно сформированную строку, которая устраняет проблемы с одиночным суррогатным символом.
- Новый флаг v регулярного выражения, который устраняет проблемы с регистром символов Unicode.
Прочие обновления
Также доступны следующие обновления и улучшения:
- улучшена производительность API URL, встроенной функции fetch() и EventTarget
- Улучшения загрузки модуля ES, включая экспериментальную поддержку import. meta. resolve(), которая может привязывать ссылку на путь к файлу модуля к строке URL
- Улучшения взаимодействия Web Crypto API
- Дальнейший прогресс в системном интерфейсе WebAssembly (WASI), который предоставляет изолированным приложениям WASM доступ к операционной системе
- Официальная поддержка ARM64 в Windows
Вывод
Node. js 20 - это важный шаг вперед. Это более значительный релиз, в котором реализованы некоторые из возможностей Deno в другие особенности.
Однако в связи с этим возникает вопрос: следует ли вам вместо этого использовать Deno?
Дено великолепен. Он стабилен, изначально поддерживает TypeScript, сокращает время разработки, требует меньше инструментов и регулярно получает обновления. С другой стороны, он существует меньше времени, имеет меньше модулей и часто является более мелкой имитацией Node. js библиотеки. Deno и Bun стоит рассмотреть для новых проектов, но существуют тысячи существующих Node. js приложения.
Deno и Bun упрощают переход к коду, но не всегда будет очевидное преимущество перехода от Node. js. Хорошая новость в том, что у нас процветающая экосистема JavaScript. Команды, работающие во время выполнения, учатся друг у друга, и быстрая эволюция приносит пользу разработчикам.