Беглый взгляд на многочисленные вводные статьи о Deno ¹ скажет вам, что это замена Node.js, избегающая NPM, со встроенным TypeScript и безопасностью с помощью флагов разрешений. Основное сообщение часто намекает на несовместимость с существующей экосистемой Node.js, подчеркивает подход давайте начнем с нуля и полностью упускает суть. Честно говоря, я бы сказал, что это даже не основные функции Deno, и сопоставлять его с существующей экосистемой Node.js в корне ошибочно.

Я слежу за Deno с момента его появления и в прошлом году переписал в него свои изоморфные библиотеки JavaScript ² ³ . Опираясь на этот опыт, я хотел бы убедить вас, что Deno — это не просто многообещающая платформа, но уже подходящая среда для написания изоморфного JavaScript, ориентированного как на браузеры Deno, так и на Node.js.

Отказ от ответственности: я не связан с компанией Deno, и хотя я открыт для взяток, я не получил от них (пока). Мнения являются моими собственными и не отражают точку зрения остального человечества.

Дело для Дено

Совместное использование кода между браузером и сервером, так называемый изоморфный JavaScript, было одним из основных преимуществ Node.js. Это уменьшает объем кода, но, что более важно, уменьшает количество переключений контекста, которые в противном случае приходится делать при работе с несколькими языками. К сожалению, по историческим причинам теперь у нас есть разные API, выполняющие аналогичные задачи в Node.js и браузерах. Процесс примирения был медленным и болезненным, как говорят модули ESM. Deno, с другой стороны, полагается на стандартные веб-API, которые потенциально исключают переключение контекста. Вы даже можете проверить в MDN, как Deno поддерживает каждый веб-API.

Соблюдение стандартных API-интерфейсов тем более важно, поскольку в Интернете больше нет строгого разграничения между клиентами и серверами: теперь у нас есть Service Workers, которые фактически являются «серверами», живущими на клиентской машине, и периферийные вычисления в Workers, таких как Cloudflare Workers, которые сидят в -между двумя — все реализующие подмножества стандартных веб-API.

Если вы слышали что-нибудь о JavaScript за последнее десятилетие, вы, вероятно, знакомы с усталостью — сценарием конца света, когда мошенническая папка node_modules занимает все доступное пространство в сети... Шучу, конечно. , однако Jest, популярный инструмент для запуска тестов, загружает около 300 зависимостей, другие инструменты и фреймворки не сильно отстают. Само по себе количество не является проблемой, однако каждый такой инструмент экспоненциально увеличивает сложность цепочки инструментов, усложняя ее настройку и обслуживание. Вдобавок ко всему, каждый раз, когда возникает скандал с какой-нибудь малоизвестной библиотекой заполнения строк в NPM, вы гарантированно принимаете участие в волнении, находя виновника среди своих зависимостей, часто через инструмент разработчика.

Deno решает эту проблему несколькими способами. Во-первых, Deno переименовывает рассматриваемую папку в cache, резко ограничивая ее деструктивный потенциал. Во-вторых, Deno представляет стандартную библиотеку , думаю, что lodash соответствует API-интерфейсам Node.js. И, наконец, у Deno есть встроенный набор инструментов...

Цепочка инструментов Deno

Из коробки Deno поставляется с форматером, линтером, тест-раннером, репортером покрытия, упаковщиком, генератором документов и Райаном знает чем еще, и все это с помощью одной консольной команды. Это огромное улучшение опыта разработчиков. Чтобы создавать качественный код Typescript, вам больше не нужно устанавливать Prettier, ESLint, Jest, TS Compiler, Webpack и тратить остаток дня, пытаясь заставить их все работать вместе с помощью различных плагинов, пресетов и ритуальных танцев.

Сами инструменты по большей части написаны на Rust и обычно на порядок быстрее, чем их аналоги на JavaScript. В то время как некоторые написаны с нуля, например deno_lint, другие взяты из существующих проектов Rust, например. форматер использует dprint, различные инструменты компиляции и связывания полагаются на swc. Тем не менее, Deno по-прежнему включает tsc для проверки типов просто из-за отсутствия альтернатив.

Недооцененной особенностью цепочки инструментов Deno является самоуверенный подход без настройки. Он принимает отраслевые стандарты де-факто и побуждает пользователей следовать им. Так, например, возможности конфигурации форматтера и линтера намеренно ограничены, хотя при необходимости всегда есть возможность отказаться.

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

# check formatting
deno fmt --check
# run the linter
deno lint
# run tests collecting coverage
deno test -A --coverage=cov
# check coverage
deno coverage cov

По общему признанию, инструменты могут быть не такими многофункциональными, как их популярные аналоги, и иногда они грубы по краям. Линтеру, скорее всего, не хватает одного или двух правил из вашего пользовательского набора правил ESLint. Форматтер, хотя и наравне с Prettier, по большей части, может иногда вас удивить, например, прямо сейчас у него есть своеобразный способ форматирования HTML внутри строковых шаблонов, таких как те, которые используются Lit и HyperHTML.

Кросс-компиляция и распространение

Код, написанный в Deno, можно скомпилировать и связать для использования в браузере или Node.js с помощью встроенного сборщика. Однако, если вы решите использовать код Typescript, написанный для Deno, как это делается с компилятором TypeScript (tsc), например. в наших обычных цепочках инструментов Node.js вы столкнетесь с небольшой, но сложной проблемой с импортом файлов. Deno (как и браузеры) импортирует именно то, что вы ему говорите, он ожидает полный путь (расширение и все) к импортируемому файлу, будь то URL-адрес или локальный путь:

import {...} from "https://deno.land/[email protected]/testing/asserts.ts"
import {...} from "./mod.ts"

Между тем, tsc предпочитает магию и будет помечать использование расширения .ts при импорте. Я сохраню для вас детали, но это одна из тех ситуаций, когда tsc неверен, а Дено прав. Этот вопрос неоднократно поднимался с командой Typescript и подробно обсуждался .

Существуют обходные пути для решения этой и других проблем, возникающих при распространении кода Deno для цепочек инструментов Node.js. Недавно команда Deno представила dnt¹⁰ — инструмент сборки, который создает пакет NPM из кода Deno. Это амбициозный инструмент, который решает проблему импорта, сопоставляет зависимости сторонних производителей с их пакетами NPM, добавляет прокладки для Deno или веб-API, которые вы можете использовать, но которых нет в Node.js, и многое другое. .

На практике вы можете иметь единую кодовую базу TypeScript (и/или JavaScript) с преимуществами инструментов Deno, которые затем можно легко распространять в браузерах и NPM. Все, что требуется, — это небольшой скрипт сборки с использованием dnt и, возможно, несколько дополнительных строк в вашем скрипте CI, если вы хотите также автоматизировать публикацию в NPM.

Следует также отметить, что на момент написания этой статьи команда Deno была занята ¹¹ улучшением совместимости с существующими пакетами Node.js, чтобы даже те, которые полагаются на специфичные для узла API, могли беспрепятственно использоваться Deno. Изоморфные пакеты NPM уже широко используются через CDN, такие как esm.sh, Skypack и им подобные.

Соглашения

В Deno есть несколько общих практик, которые могут оказаться полезными при написании ваших библиотек или просто при навигации по экосистеме. Они не применяются Deno, в лучшем случае могут считаться соглашениями, и вы можете отказаться от любого или всех из них:

  • Основная точка входа в библиотеку Deno обычно называется mod.ts, а index.ts оставлена ​​для приложений.
  • Сторонние зависимости собираются в файл с именем deps.ts или dev_deps.ts для зависимостей только для разработчиков. Таким образом, обновление версий может быть централизовано, как это делается в package.json для NPM.
  • змея_case используется для имен файлов, а тестовые файлы заканчиваются на _test.ts.
  • Структура папок библиотек плоская: большинство экспортируемых файлов расположены в основной папке, а вложенные папки используются для вспомогательных и второстепенных элементов, таких как docs для документации по API, examples для примеров использования и т. д. Это приводит к более коротким путям импорта для ваших зависимых файлов, поскольку Deno использует URL-адреса для импорта.

В целом, мой опыт портирования и обслуживания библиотек в Deno значительно улучшился по сравнению с предыдущим набором инструментов. Не всегда все было радужно: отладка в VSCode иногда прерывалась, покрытие какое-то время было неточным, в то время как тестирование API было переработано, импорт некоторых специфичных для узла библиотек все еще может быть сложным. Однако, когда что-то все-таки ломается, гораздо проще найти причину или, по крайней мере, кого винить. В то время как с нашей обычной коллекцией инструментов Node.js это часто превращается в погоню за дикими гусями по дюжине репозиториев. Команда Deno также активно реагировала на исправление и улучшение платформы.

[1]: Deno — современная среда выполнения для JavaScript и TypeScript

[2]: structurae: структуры данных для высокопроизводительных приложений JavaScript.

[3]: compago: минималистичный фреймворк для современных веб-приложений.

[4]: objectid64: преобразовать идентификаторы объектов MongoDB в формат base64, удобный для URL.

[5]: Стандартная библиотека Deno

[6]: deno_lint: невероятно быстрый линтер для JavaScript и TypeScript, написанный на Rust

[7]: dprint: подключаемая и настраиваемая платформа форматирования кода, написанная на Rust.

[8]: swc: платформа для Интернета на основе Rust

[9]: разрешить добровольный суффикс .ts для путей импорта · Проблема № 37582 · Microsoft/TypeScript

[10]: dnt: инструмент для сборки пакетов Deno в npm.

[11]: Улучшение режима совместимости узлов · Проблема № 12577 · denoland/deno