-
Notifications
You must be signed in to change notification settings - Fork 635
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Добавляет обзор рантайма Deno (#5438)
- Loading branch information
1 parent
8d2dc71
commit 375bb87
Showing
4 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
name: 'Роман Троицкий' | ||
url: https://github.com/DreamShaded | ||
photo: 'photo.jpg' | ||
badges: | ||
- first-contribution-small | ||
--- | ||
Влюблён во фронтенд. Один из организаторов [MoscowCSS митапа](https://t.me/moscowcss) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"updatedAt": "2024-07-13T18:44:00.719Z", | ||
"createdAt": "2024-07-13T18:44:00.719Z" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
--- | ||
title: "Что такое Deno" | ||
description: "Альтернатива Node.js от создателя Node.js." | ||
authors: | ||
- dreamshaded | ||
# contributors: | ||
keywords: | ||
- deno | ||
- js runtime | ||
- альтернатива node js | ||
related: | ||
- tools/Node.js | ||
- tools/Node.js-tooling | ||
- tools/gateway | ||
tags: | ||
- article | ||
--- | ||
|
||
## Кратко | ||
|
||
Deno - это современная среда выполнения JavaScript/TypeScript, созданная Райаном Далом, первоначальным создателем Node.js, в 2018 году. Она была разработана для решения ряда проблем и ограничений, присутствующих в Node.js. Deno внедряет различные функции и архитектурные решения для улучшения безопасности, опыта разработчиков и производительности. | ||
|
||
## Ключевые отличия от Node.js | ||
|
||
В первую очередь Райана смущала безопасность. Node.js предоставляет неограниченные доступы к файловой системе, сети и переменным окружения. Это создаёт значительный риск для безопасности в случае исполнения недоверенного кода. Так же у Node.js нет механизмов для ограничения возможностей скриптов программно. В Deno же код выполняется в песочницах, требуя явных разрешений на доступы к файловой системе, сети и переменным окружения. Управлять доступами необходимо из командной строки. Так, например, для того, чтобы разрешить коду использовать сеть, мы должны запустить скрипт из терминала с флагами: | ||
|
||
```javascript | ||
// my-script.js | ||
const url = "https://api.github.com/users/denoland"; | ||
|
||
async function fetchData() { | ||
try { | ||
const response = await fetch(url); | ||
|
||
if (!response.ok) { | ||
throw new Error(`Request error! status: ${response.status}`); | ||
} | ||
|
||
const data = await response.json(); | ||
console.log('Data': data); | ||
} catch (error) { | ||
console.error("Error fetching data:", error); | ||
} | ||
} | ||
|
||
fetchData(); | ||
``` | ||
|
||
```bash | ||
deno run --allow-net my-script.js | ||
``` | ||
|
||
А вот пример запуска скрипта с параметрами доступа к файловой системе: | ||
```javascript | ||
// my-other-script.js | ||
const { readTextFile, writeTextFile } = Deno; | ||
|
||
async function modifyFileContent() { | ||
try { | ||
const inputFile = 'input.txt'; // путь до файла может быть абсолютным и относительным | ||
const inputContent = await readTextFile(inputFile); | ||
|
||
console.log(`Read from ${inputFile}: ${inputContent}`); | ||
|
||
// Приведём строки к верхнему регистру: | ||
const modifiedContent = inputContent.toUpperCase(); | ||
const outputFile = 'output.txt'; | ||
|
||
await writeTextFile(outputFile, modifiedContent); | ||
|
||
console.log(`Written to ${outputFile}: ${modifiedContent}`); | ||
} catch (error) { | ||
console.error('Error with file operations:', error); | ||
} | ||
} | ||
|
||
modifyFileContent(); | ||
``` | ||
|
||
```bash | ||
deno run --allow-read --allow-write my-other-script.js | ||
``` | ||
|
||
Если мы установим пакет, которому необходимы дополнительные права, то при попытке выполнения увидим, что для выполнения скрипта Deno необходимо разрешение на запись: | ||
|
||
```bash | ||
deno run npm:file-access-package | ||
┌ Deno requests write access to /usr/bin/. | ||
├ Requested by `file-access-package` | ||
├ Run again with --allow-write to bypass this prompt. | ||
└ Allow? [y/n] (y = yes, allow; n = no, deny) | ||
|
||
``` | ||
|
||
Вторая проблема - управление зависимостями. В 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. | ||
|
||
Как это выглядит на практике: | ||
|
||
```javascript | ||
// импорт из самой последней, самой свежей версии пакета std: | ||
import { assertEquals } from "https://deno.land/std/testing/asserts.ts"; | ||
|
||
// импорт из конкретной версии пакета, в данном случае 0.104.0: | ||
import { serve } from "https://deno.land/[email protected]/http/server.ts"; | ||
|
||
// импорт из приватного реестра с моего сервера: | ||
import { SimpleButton } from "https://nexus.vzhyx.digital/deno-test/[email protected]/index.ts"; | ||
|
||
// импорт из NPM: | ||
import React from "npm:[email protected]" | ||
``` | ||
|
||
Следом контрибьюторы посчитали необходимым привести работу с модулями к стандарту. Node.js, конечно, поддерживает ESModules, однако для этого необходимо указать "type": "module" в package.json или использовать файлы с расширением .mjs, оставляя работу с CommonJS с помощью require() поведением по умолчанию. Получается, код в Deno и в браузере выглядит консистентнее, чем в Node.js. | ||
|
||
<!-- !спорный тезис, спорный пример. У них разные задачи же. Тезис "украден" с чужой статьи --> | ||
<!-- 13.07.2024 - не помню, где нашёл --> | ||
Таким же образом Райан поступил и с асинхронными операциями. 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: | ||
|
||
```json | ||
{ | ||
"imports": { | ||
"std/": "https://deno.land/[email protected]/" | ||
}, | ||
"tasks": { | ||
"dev": "deno run --watch main.ts" | ||
}, | ||
"lint": { | ||
"include": ["src/"], | ||
"exclude": ["src/testdata/", "src/fixtures/**/*.ts"], | ||
"rules": { | ||
"tags": ["recommended"], | ||
"include": ["ban-untagged-todo"], | ||
"exclude": ["no-unused-vars"] | ||
} | ||
}, | ||
"fmt": { | ||
"useTabs": true, | ||
"lineWidth": 80, | ||
"indentWidth": 4, | ||
"semiColons": true, | ||
"singleQuote": true, | ||
"proseWrap": "preserve", | ||
"include": ["src/"], | ||
"exclude": ["src/testdata/", "src/fixtures/**/*.ts"] | ||
} | ||
} | ||
``` | ||
|
||
И, конечно, в отличие от Node.js, который поддерживает TypeScript только через установку и конфигурацию отдельных пакетов, Deno из коробки предоставляет компилятор ts, что позволяет нам писать на TypeScript без установки дополнительных пакетов. | ||
|
||
Последнее значительное отличие Deno от Node.js - исходный код. Node.js написан преимущественно на C|C++, а Deno - на Rust, на языке, известном более надёжной работой с памятью и мультипоточностью, а также даёт возможность расширять функциональность Deno с помощью плагинов, написанных на Rust. | ||
|
||
## Использование | ||
|
||
Deno поддерживают и используют достаточно много компаний: Slack, Netlify, SalesForce, Tencent, однако нет подробной информации о проектах и статистики использования. | ||
|
||
## Минусы | ||
|
||
Несмотря на то, что 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) всё ещё в планах. |