Что нового в Node.js 18!

Как я всегда здесь делаю, давайте поговорим об очередном сенсационном релизе Node.js, версия 18 была анонсирована в апреле 2022 года! И вы, наверное, спрашиваете себя: ну и что?

Для тех, кто занимается JavaScript или нет, эта версия Node.js принесла много очень интересных изменений в саму среду исполнения, и некоторые из этих изменений настолько важны, что могут вдохновить другие среды исполнения на то же самое, так что давайте посмотрим на все, что мы имеем!

Но сначала, как я всегда делаю в подобных статьях, давайте немного подробнее расскажем о процессе выпуска Node.js.

Процесс выпуска Node.js

Как и многие другие крупные проекты, которые очень сильно зависят от сообщества, Node.js имеет чрезвычайно организованный график и организацию новых версий и релизов.

Все четные версии считаются «готовыми к производству», в то время как нечетные версии являются версиями для тестирования и разработки. Другими словами, версии с нечетными номерами — это как среда постановки, то есть более структурированное тестирование, чтобы освободить место для производственной версии. Обычно в таких релизах новые функции тестируются сообществом, а через некоторое время они переходят в стабильную версию.


График выпуска Node.js в 2022 году

Peer-релизы выпускаются в апреле и обозначаются как Current до октября, когда они становятся активной версией, а предыдущая peer-версия переходит в статус maintenance.

Разница между активной и текущей версией заключается в том, что активные версии считаются LTS или Long Term Support, которые получают обновления безопасности и поддержку в течение 3 лет, всегда есть 3 версии в статусе поддержки и одна LTS версия, все версии старше 3 лет являются устаревшими, что и произошло с версией 10 теперь, когда вышла версия 18.

Все даты и все планы по предыдущим и следующим версиям можно посмотреть на официальном сайте релизов.

В настоящее время таково состояние окружающей среды:

  • Node v12: достиг конца срока службы в апреле 2022 года
  • Node v14: Продолжает поддерживаться до апреля 2023 года, затем будет заброшен
  • Node v16: В настоящее время это LTS-версия до октября 2022 года, затем она переходит на обслуживание до апреля 2024 года, после чего от нее откажутся.
  • Node v18: Это текущая версия до октября 2022 года, когда она станет следующей LTS до апреля 2025 года.

Глобальная выборка доступна по умолчанию

В версии Node 17 было объявлено, что API fetch, уже присутствующий в большинстве браузеров для JavaScript, придет и в Node. Таким образом, нам больше не понадобятся внешние пакеты, такие как известные axios и got, чтобы иметь возможность делать HTTP-запросы более простым способом, не нуждаясь в родном HTTP-клиенте Node — который, скажем так… Немного сложный.

Этот клиент реализован с помощью одной из самых интересных библиотек, когда-либо созданных для Node, undici, клиента HTTP/1.1, написанного с нуля, полностью на JavaScript для Node.js.

Эта реализация была первоначально добавлена через экспериментальный флаг в Node, который включал эту функциональность, но теперь у нас fetch включен по умолчанию.

Вот как мы можем использовать этого нового клиента:

const res = await fetch('https://nodejs.org/api/documentation.json');
if (res.ok) {
  const data = await res.json();
  console.log(data);
}
Войдите в полноэкранный режим Выход из полноэкранного режима

В дополнение к fetch были добавлены другие глобальные переменные: Headers, Request, Response и FormData.

Будьте осторожны, чтобы не спутать нативные типы Request и Response с теми же типами, что и в Express, когда мы используем TypeScript

Другие глобальные API

  • Добавлена экспериментальная версия WebStreams API, позволяющая использовать потоки нативно в веб-средах без использования локальных интеграций
  • Новый экспериментальный тип Buffer, Blob, также был помещен в глобальный APIs
  • Для добавления в worker_threads, BroadcastChannel теперь также является открытым глобальным API

Нативная программа для запуска тестов

Один из самых крутых API, который лично я ждал много лет, — это поддержка нативного запуска тестов. Правильно, больше никаких mocha, jest, ava и других.

Теперь вы можете запускать все тесты программного обеспечения, которые у вас уже есть, с помощью модуля test, который может быть загружен, только если обозначен префиксом node::

import test from 'node:test'
import assert from 'node:assert'

test('top level test', async (t) => {
  await t.test('subtest 1', (t) => {
    assert.strictEqual(1, 1);
  });

  await t.test('subtest 2', (t) => {
    assert.strictEqual(2, 2);
  });
});
Войдите в полноэкранный режим Выход из полноэкранного режима

API полностью документирован, конечно, пройдет некоторое время, прежде чем он достигнет уровня других библиотек, таких как jest, если вообще достигнет.

Я говорю так, потому что основная идея этой библиотеки заключается не в том, что она заменяет основные библиотеки, которые мы уже используем, например, те, о которых я говорил ранее, а в том, что она снижает барьер входа для создания автоматизированных тестов с помощью Node.js. Таким образом, все больше систем смогут полагаться на автоматизированные тесты и станут гораздо более безопасными.

Однако есть некоторые соображения по реализации, которые мы должны рассмотреть:

  • Node запустит все файлы тестов, когда вы инициализируете среду выполнения с флагом --test, каждый тест будет выполняться в собственном изолированном процессе.
  • Тесты могут быть синхронными или асинхронными, синхронные тесты считаются корректными, если они не вызывают исключений. Асинхронные, как и ожидалось, если они не отвергают Promise
  • Подтесты, созданные с контекстом t, который мы передаем в примере, будут выполняться так же, как и родительский тест
  • Если вы хотите пропустить тест, просто отправьте объект options с флагом { skip: 'message' } к объекту test, как в этом примере:
test('pulado', { skip: 'Esse teste foi pulado' }, (t) => {
    // nunca executado
})
Войдите в полноэкранный режим Выход из полноэкранного режима

В настоящее время объект options принимает три типа ключей:

Бегунок тестирования пока носит экспериментальный характер и работает за флагами, но это должно измениться в следующих версиях.

Префикс node:

Давайте сделаем набросок, чтобы объяснить особенность, которая не обязательно появилась в самом Node 18, однако это было важное изменение, которое создает прецедент, которому можно следовать в будущем для всех других модулей.

В примере, который я приводил выше, вы можете заметить, что мы импортируем модули assert и test с префиксом node:. Это начало того, что называется основными модулями только с префиксом.

Это существовало и раньше, но не было обязательным, до сегодняшнего дня все нативные модули, такие как fs, assert и другие, работали одинаково, независимо от того, импортировались они с префиксом node: или нет. Сегодня это уже не так.

node:test — это первый нативный модуль, который может быть импортирован только при использовании префикса node:, если вы не используете префикс, среда выполнения попытается загрузить модуль под названием test, который считается модулем userland, то есть модулем, сделанным сообществом.

Это замечательное изменение, поскольку с появлением префикса node: в новых модулях (и, возможно, в качестве изменения в будущем релизе для старых модулей), у нас появится возможность иметь два модуля с одинаковым именем, один в userland, а другой в ядре Node.

Таким образом, поскольку модули ядра имеют приоритет над пользовательскими модулями, разработчики Node смогут создавать модули, не заботясь о том, что имя модуля уже существует, например, в NPM.

С другой стороны, это создает две проблемы, первая из которых заключается в том, что мы имеем явное несоответствие между модулями, которые уже существуют, такими как fs и http, и новыми модулями, которые только используют префикс. Решением этой проблемы должно быть обязательное использование префикса для всех модулей, а не только для новых.

Кроме того, возникает проблема безопасности: typosquatting, когда кто-то создает модуль в NPM с тем же именем или именем, очень похожим на оригинальный пакет — например, называя express a expres в NPM — так что ничего не подозревающие разработчики могут загрузить вредоносный пакет вместо оригинального пакета. Эти проблемы исходят не от команды Node, не в последнюю очередь потому, что NPM уже имеет некоторые блокировки безопасности против этого, но в любом случае, это то, о чем стоит упомянуть.

Пользовательские снимки

В версии 18 появилось нечто очень интересное — использование моментальных снимков во время сборки среды выполнения Node. Это очень интересно для тех, у кого много команд разработчиков и кому необходимо синхронизировать и даже улучшить производительность продукта между командами.

Начиная с этой новой версии, можно будет скомпилировать бинарный файл Node.js с пользовательским стартовым снимком, используя флаг --node-snapshot-main. Например:

$ cd /path/to/node/source
$ ./configure --node-snapshot-main=marked.js
# Build do binário
$ make node
Войдите в полноэкранный режим Выход из полноэкранного режима

Сборка бинарного файла Node путем передачи точки входа, например marked.js, которая является рендерером Markdown, инициализирует модуль и загрузит его в globalThis, и вы сможете использовать его нативно, например:

const html = globalThis.marked(process.argv[1]);
console.log(html);
Войдите в полноэкранный режим Выход из полноэкранного режима

И запустите двоичный файл, созданный с помощью:

$ out/Release/node render.js test.md
Войдите в полноэкранный режим Выход из полноэкранного режима

Конечно, это для очень специфических случаев использования, когда вам нужно, фактически, перекомпилировать всю среду выполнения Node, чтобы включить одну или несколько точек входа модуля непосредственно в двоичный файл для улучшения времени компиляции.

В качестве продолжения, команда работает над PR #42617 и #38905, которые соответственно

  • Позволяет загружать модуль без скрипта инициализации, который превратит весь бинарник в пользовательское приложение, таким образом, ваш конечный бинарник будет работать как $ out/Release/markedNode test.md, что на шаг ближе к полным бинарникам Node, как это делает сам Golang
  • Позволяет добавлять точки входа без необходимости перекомпиляции всего времени выполнения с помощью компилятора.

Изменения в V8 и других пунктах

Версия 10 v8 привносит некоторые новые возможности:

  • Поддержка новых методов findLast и findLastIndex для массивов, которые делают то же самое, что и find, но находят последнее значение вместо первого
  • Улучшения в API Intl.Locale
  • Улучшена производительность инициализации свойств и приватных методов класса, чтобы они работали так же быстро, как обычные свойства.
  • Импорт модулей JSON был официально удален из экспериментального флага

Оцените статью
Procodings.ru
Добавить комментарий