diff --git a/tools/deno/index.md b/tools/deno/index.md index 27165c370c..d5ca36e7c5 100644 --- a/tools/deno/index.md +++ b/tools/deno/index.md @@ -17,70 +17,75 @@ tags: ## Кратко -Deno - это современная среда выполнения JavaScript/TypeScript, созданная Райаном Далом, первоначальным создателем Node.js, в 2018 году. Она была разработана для решения ряда проблем и ограничений, присутствующих в Node.js. Deno внедряет различные функции и архитектурные решения для улучшения безопасности, опыта разработчиков и производительности. +Deno — это современная среда выполнения JavaScript/TypeScript, созданная [Райаном Далом](https://en.wikipedia.org/wiki/Ryan_Dahl), первоначальным создателем [Node.js](/tools/nodejs/), в 2018 году. Она была разработана для решения ряда проблем и ограничений, присутствующих в Node.js. Deno внедряет различные функции и архитектурные решения для улучшения безопасности, опыта разработчиков и производительности. ## Ключевые отличия от Node.js -В первую очередь Райана смущала безопасность. Node.js предоставляет неограниченные доступы к файловой системе, сети и переменным окружения. Это создаёт значительный риск для безопасности в случае исполнения недоверенного кода. Так же у Node.js нет механизмов для ограничения возможностей скриптов программно. В Deno же код выполняется в песочницах, требуя явных разрешений на доступы к файловой системе, сети и переменным окружения. Управлять доступами необходимо из командной строки. Так, например, для того, чтобы разрешить коду использовать сеть, мы должны запустить скрипт из терминала с флагами: +В первую очередь Райана смущала безопасность. Node.js предоставляет неограниченные доступы к файловой системе, сети и переменным окружения. Это создаёт значительный риск для безопасности в случае исполнения недоверенного кода. Так же у Node.js нет механизмов для ограничения возможностей скриптов программно. В Deno же код выполняется в песочницах, требуя явных разрешений на доступы к файловой системе, сети и переменным окружения. Управлять доступами необходимо из командной строки. + +Так, например, для того, чтобы разрешить коду использовать сеть, мы должны запустить скрипт из терминала с флагами: + +```bash +deno run --allow-net my-script.js +``` + +В файле _my-script.js_ напишем следующий код: ```javascript -// my-script.js -const url = "https://api.github.com/users/denoland"; +const url = 'https://api.github.com/users/denoland' async function fetchData() { try { - const response = await fetch(url); + const response = await fetch(url) if (!response.ok) { - throw new Error(`Request error! status: ${response.status}`); + throw new Error(`Request error! status: ${response.status}`) } - const data = await response.json(); - console.log('Data': data); + const data = await response.json() + console.log('Data: ', data) } catch (error) { - console.error("Error fetching data:", error); + console.error('Error fetching data: ', error) } } -fetchData(); +fetchData() ``` +Пример запуска скрипта с параметрами доступа к файловой системе: + ```bash -deno run --allow-net my-script.js +deno run --allow-read --allow-write my-other-script.js ``` -А вот пример запуска скрипта с параметрами доступа к файловой системе: +Содержимое файла _my-other-script.js_: + ```javascript -// my-other-script.js -const { readTextFile, writeTextFile } = Deno; +const { readTextFile, writeTextFile } = Deno async function modifyFileContent() { try { - const inputFile = 'input.txt'; // путь до файла может быть абсолютным и относительным - const inputContent = await readTextFile(inputFile); + const inputFile = 'input.txt' // путь до файла может быть абсолютным и относительным + const inputContent = await readTextFile(inputFile) - console.log(`Read from ${inputFile}: ${inputContent}`); + console.log(`Read from ${inputFile}: ${inputContent}`) // Приведём строки к верхнему регистру: - const modifiedContent = inputContent.toUpperCase(); - const outputFile = 'output.txt'; + const modifiedContent = inputContent.toUpperCase() + const outputFile = 'output.txt' - await writeTextFile(outputFile, modifiedContent); + await writeTextFile(outputFile, modifiedContent) - console.log(`Written to ${outputFile}: ${modifiedContent}`); + console.log(`Written to ${outputFile}: ${modifiedContent}`) } catch (error) { - console.error('Error with file operations:', error); + console.error('Error with file operations: ', error) } } -modifyFileContent(); -``` - -```bash -deno run --allow-read --allow-write my-other-script.js +modifyFileContent() ``` -Если мы установим пакет, которому необходимы дополнительные права, то при попытке выполнения увидим, что для выполнения скрипта Deno необходимо разрешение на запись: +Если мы установим пакет, которому необходимы дополнительные права, то при попытке запуска увидим, что для выполнения скрипта Deno необходимо разрешение на запись: ```bash deno run npm:file-access-package @@ -91,35 +96,31 @@ deno run npm:file-access-package ``` -Вторая проблема - управление зависимостями. В Node.js библиотеки и фреймворки устанавливаются с помощью NPM (Node Package Manager). Это означает, что каждый раз, когда вы добавляете новую библиотеку, она может иметь свои собственные зависимости. Например, если вы установите библиотеку "A", она может зависеть от библиотек "B" и "C", а те, в свою очередь, могут иметь свои зависимости. Это создает очень сложную структуру, похожую на дерево, где одна библиотека зависит от другой и так далее. Это усложняет управление зависимостями, потому что нужно следить за множеством версий разных библиотек. Если одна библиотека требует одну версию зависимости, а другая - другую, может возникнуть конфликт версий, и программа может перестать работать. Ещё централизация реестра зависимостей немного осложняет мененджмент пакетов из разных реестров: необходимо указать список реестров в .npmrc, авторизоваться или прописать явно токены авторизации и так далее. Кроме того, сообщество ещё не забыло [инцидент с left-pad](https://en.wikipedia.org/wiki/Npm_left-pad_incident). +Вторая проблема — управление зависимостями. В Node.js библиотеки и фреймворки устанавливаются с помощью NPM (Node Package Manager). Это означает, что каждый раз, когда вы добавляете новую библиотеку, она может иметь свои собственные зависимости. Например, если вы установите библиотеку «A», она может зависеть от библиотек «B» и «C», а те, в свою очередь, могут иметь свои зависимости. Это создает очень сложную структуру, похожую на дерево, где одна библиотека зависит от другой и так далее. Это усложняет управление зависимостями, потому что нужно следить за множеством версий разных библиотек. Если одна библиотека требует одну версию зависимости, а другая — другую, может возникнуть конфликт версий, и программа может перестать работать. Ещё централизация реестра зависимостей немного осложняет мененджмент пакетов из разных реестров: необходимо указать список реестров в _.npmrc_, авторизоваться или прописать явно токены авторизации и так далее. Кроме того, сообщество ещё не забыло [инцидент с left-pad](https://en.wikipedia.org/wiki/Npm_left-pad_incident). -Deno вместо этого предлагает механизм импорта по URL с локальным кешированием, что приводит к созданию плоской структуры зависимостей. Каждый URL рассматривается как отдельный, уникальный ESM модуль, что убирает возможность возникновения конфликтов версий начисто, а так же для доступов в различные реестры можно обойтись наличием VPN, т.к. в реестре теперь лежит статический JS или TS файл, а не .tar.gz архив. Однако децентрализация всё ещё оставляет возможности повторения ситуации с left-pad, особенно при использовании открытых, а не приватных репозиториев. Также в релизе 1.28 была добавлена возможность использования npm пакетов из registry.npmjs.org. +Deno вместо этого предлагает механизм импорта по URL с локальным кешированием, что приводит к созданию плоской структуры зависимостей. Каждый URL рассматривается как отдельный, уникальный ESM-модуль, что убирает возможность возникновения конфликтов версий начисто, а так же для доступов в различные реестры можно обойтись наличием VPN, так как в реестре теперь лежит статический JS- или TS-файл, а не _.tar.gz_ архив. Однако децентрализация всё ещё оставляет возможности повторения ситуации с left-pad, особенно при использовании открытых, а не приватных репозиториев. Также в релизе 1.28 была добавлена возможность использования npm пакетов из _registry.npmjs.org_. Как это выглядит на практике: ```javascript // импорт из самой последней, самой свежей версии пакета std: -import { assertEquals } from "https://deno.land/std/testing/asserts.ts"; +import { assertEquals } from 'https://deno.land/std/testing/asserts.ts' // импорт из конкретной версии пакета, в данном случае 0.104.0: -import { serve } from "https://deno.land/std@0.104.0/http/server.ts"; +import { serve } from 'https://deno.land/std@0.104.0/http/server.ts' // импорт из приватного реестра с моего сервера: -import { SimpleButton } from "https://nexus.vzhyx.digital/deno-test/chamomile-ui@1.1.2/index.ts"; +import { SimpleButton } from 'https://nexus.vzhyx.digital/deno-test/chamomile-ui@1.1.2/index.ts' // импорт из NPM: -import React from "npm:react@18.2.0" +import React from 'npm:react@18.2.0' ``` -Следом контрибьюторы посчитали необходимым привести работу с модулями к стандарту. Node.js, конечно, поддерживает ESModules, однако для этого необходимо указать "type": "module" в package.json или использовать файлы с расширением .mjs, оставляя работу с CommonJS с помощью require() поведением по умолчанию. Получается, код в Deno и в браузере выглядит консистентнее, чем в Node.js. - - - -Таким же образом Райан поступил и с асинхронными операциями. Node.js поддерживает промисы и async/await, однако значительная часть кор-фичей построена на колбэках, или получила асинхронный аналог, как, например, fs.readFile, который принимает в себя путь до файла и колбэк для обработки прочитанных данных, возвращая undefined, и fs.readFileSync, который принимает в себя путь до файла и возвращает его содержимое. Deno кор-фичи сразу спроектированы асинхронно, и разработчику теперь не нужно запоминать вариации решения одной и той же задачи, что также упрощает изучение апи. - +Следом контрибьюторы посчитали необходимым привести работу с модулями к стандарту. Node.js, конечно, поддерживает ESModules, однако для этого необходимо указать `"type": "module"` в _package.json_ или использовать файлы с расширением _.mjs_, оставляя работу с CommonJS с помощью `require()` поведением по умолчанию. Получается, код в Deno и в браузере выглядит консистентнее, чем в Node.js. +Таким же образом Райан поступил и с асинхронными операциями. Node.js поддерживает промисы и `async/await`, однако значительная часть кор-фичей построена на колбэках, или получила асинхронный аналог, как, например, `fs.readFile`, который принимает в себя путь до файла и колбэк для обработки прочитанных данных, возвращая `undefined`, и `fs.readFileSync`, который принимает в себя путь до файла и возвращает его содержимое. Deno кор-фичи сразу спроектированы асинхронно, и разработчику теперь не нужно запоминать вариации решения одной и той же задачи, что также упрощает изучение апи. -Ещё одно крупное нововведение - встроенный тулинг для работы с качеством кода. В Node.js это отдано на откуп отдельным пакетам: ESLint, Prettier, Mocha, Jest и так далее, а Deno поставляет это всё "из коробки". Запустив утилиту lint командой deno lint мы получим список отклонений от кодстайла, а запустив утилиту fmt командой deno fmt мы получим отформатированный код. Бонусом deno избавляет нас от пачки конфигурационных файлов для линтеров, форматтеров и прочих утилит, всё настраивается в одном месте - deno.json: +Ещё одно крупное нововведение — встроенный тулинг для работы с качеством кода. В Node.js это отдано на откуп отдельным пакетам: ESLint, Prettier, Mocha, Jest и так далее, а Deno поставляет это всё «из коробки». Запустив утилиту lint командой `deno lint` мы получим список отклонений от кодстайла, а запустив утилиту fmt командой `deno fmt` мы получим отформатированный код. Бонусом Deno избавляет нас от пачки конфигурационных файлов для линтеров, форматтеров и прочих утилит, всё настраивается в одном месте — _deno.json_: ```json { @@ -151,9 +152,9 @@ import React from "npm:react@18.2.0" } ``` -И, конечно, в отличие от Node.js, который поддерживает TypeScript только через установку и конфигурацию отдельных пакетов, Deno из коробки предоставляет компилятор ts, что позволяет нам писать на TypeScript без установки дополнительных пакетов. +И, конечно, в отличие от Node.js, который поддерживает TypeScript только через установку и конфигурацию отдельных пакетов, Deno из коробки предоставляет компилятор TS, что позволяет нам писать на TypeScript без установки дополнительных пакетов. -Последнее значительное отличие Deno от Node.js - исходный код. Node.js написан преимущественно на C|C++, а Deno - на Rust, на языке, известном более надёжной работой с памятью и мультипоточностью, а также даёт возможность расширять функциональность Deno с помощью плагинов, написанных на Rust. +Последнее значительное отличие Deno от Node.js — исходный код. Node.js написан преимущественно на C и C++, а Deno — на Rust. На языке, известном более надёжной работой с памятью и мультипоточностью. Также он даёт возможность расширять функциональность Deno с помощью плагинов, написанных на Rust. ## Использование @@ -164,6 +165,6 @@ Deno поддерживают и используют достаточно мн Несмотря на то, что Deno позиционируется как следующий этап эволюции Node.js, как переосмысление и исправление ошибок, Deno также не лишён и минусов: 1. Экосистема. Node.js развивается с 2009 года, и имеет более двух миллионов пакетов, в отличие от Deno. Также хоть Deno и внедрил поддержку npm пакетов, совместимость не полная и перенос существующего проекта с Node.js на Deno может затребовать колоссального рефакторинга. -2. Поддержка в IDE. Несмотря на то, что у Deno имеются все средства обеспечения качества кода "из коробки", IDE и редакторы могут не поддерживать плагины или лишиться поддержки при обновлении версии Deno, и проблемы уже возникали. -3. TS в коробке. Поддержка TS напрямую кажется отличным решением, однако даёт дополнительную нагрузку при компиляции "на лету". Это может приводить к замедлению работы и увеличению потребления ресурсов сервера. -4. Стабильность, поддержка. Так как Deno всё ещё является новым рантаймом, развивается, меняет, добавляет и выводит API, он не может обеспечить такую же стабильность, как у Node.js. Кроме того, политика долгосрочной поддержки (LTS) всё ещё в планах. +1. Поддержка в IDE. Несмотря на то, что у Deno имеются все средства обеспечения качества кода «из коробки», IDE и редакторы могут не поддерживать плагины или лишиться поддержки при обновлении версии Deno, и проблемы уже возникали. +1. TypeScript в коробке. Поддержка TS напрямую кажется отличным решением, однако даёт дополнительную нагрузку при компиляции «на лету». Это может приводить к замедлению работы и увеличению потребления ресурсов сервера. +1. Стабильность, поддержка. Так как Deno всё ещё является новым рантаймом, развивается, меняет, добавляет и выводит API, он не может обеспечить такую же стабильность, как у Node.js. Кроме того, политика долгосрочной поддержки (LTS) всё ещё в планах.