Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Добавляет обзор рантайма Deno #5438

Merged
merged 8 commits into from
Sep 29, 2024
8 changes: 8 additions & 0 deletions people/dreamshaded/index.md
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)
Binary file added people/dreamshaded/photo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions tools/deno/index.11tydata.json
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"
}
181 changes: 181 additions & 0 deletions tools/deno/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
---
title: "Что такое Deno"
description: "Альтернатива NodeJS от создателя NodeJS."
authors:
- dreamshaded
# contributors:
keywords:
- deno
- js runtime
- альтернатива node js
related:
- tools/nodejs
- tools/nodejs-tooling
- tools/gateway
tags:
- article
---

## Кратко

Deno - это современная среда выполнения JavaScript/TypeScript, созданная Райаном Далом, первоначальным создателем Node.js, в 2018 году. Она была разработана для решения ряда проблем и ограничений, присутствующих в Node.js, внедряя различные функции и архитектурные решения, направленные на улучшение безопасности, опыта разработчиков и производительности.
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved

## Ключевые отличия от NodeJS

В первую очередь Райана смущала безопасность NodeJS: наличие неограниченного доступа к файловой системе, сети, переменным окружения создаёт значительный риск для безопасности в случае исполнения недоверенного кода. Так же у NodeJS нет механизмов для ограничения возможностей скриптов программно. В Deno же код выполняется в песочницах, требуя явных разрешений на доступы к файловой системе, сети и переменным окружения. Управлять доступами необходимо из командной строки. Так, например, для того, чтобы разрешить коду использовать сеть, мы должны запустить скрипт из терминала с флагами:
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved

```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
```

Если мы установим пакет, которому необходимы дополнительные права, то при попытке выполнения увидим запрос:
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved

```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)

```

Вторая проблема - менеджмент зависимостей. В NodeJS библиотеки и фреймворки устанавливаются с помощью NPM, и большая часть пакетов имеет свои зависимости, что приводит к созданию графа зависимостей высокой вложенности, что, естественно, усложняет менеджмент зависимостей (привет, overrides) и увеличивает риски возникновения конфликтов версий. Ещё централизация реестра зависимостей немного осложняет мененджмент пакетов из разных реестров: необходимо указать список реестров в .npmrc, авторизоваться или прописать явно токены авторизации и так далее. Кроме того, сообщество и Райан ещё не забыли [инцидент с left-pad](https://en.wikipedia.org/wiki/Npm_left-pad_incident).

Deno вместо этого предлагает механизм импорта по URL с локальным кешированием, что приводит к созданию плоской структуры зависимостей. Каждый URL рассматривается как отдельный, уникальный модуль, что убирает возможность возникновения конфликтов версий начисто, а так же для доступов в различные реестры можно обойтись наличием VPN, т.к. в реестре теперь лежит статический JS или TS файл, а не .tar.gz архив. Однако децентрализация всё ещё оставляет возможности повторения ситуации с left-pad, особенно при использовании открытых, а не приватных репозиториев. Также в релизе 1.28 была добавлена возможность использования npm пакев из registry.npmjs.org.
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved

Как это выглядит на практике:

```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]"
```

Следом Райан посчитал необходимым привести работу с модулями к стандарту. NodeJS, конечно, поддерживает ESModules, однако для этого необходимо указать "type": "module" в package.json или использовать файлы с расширением .mjs, оставляя работу с CommonJS с помощью require() поведением по умолчанию. Получается, код в Deno и в браузере выглядит консистентнее, чем в NodeJS.
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved

<!-- !спорный тезис, спорный пример. У них разные задачи же. Тезис "украден" с чужой статьи -->
<!-- 13.07.2024 - не помню, где нашёл -->
Таким же образом Райан поступил и с асинхронными операциями. NodeJS поддерживает промисы и async/await, однако значительная часть кор-фичей построена на колбэках, или получила асинхронный аналог, как, например, fs.readFile, который принимает в себя путь до файла и колбэк для обработки прочитанных данных, возвращая undefined, и fs.readFileSync, который принимает в себя путь до файла и возвращает его содержимое. Deno кор-фичи сразу спроектированы асинхронно, и разработчику теперь не нужно запоминать вариации решения одной и той же задачи, что также упрощает изучение апи.



Ещё одно крупное нововведение - встроенный тулинг для работы с качеством кода. В NodeJS это отдано на откуп отдельным пакетам: 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"]
}
}
```

Встроенный фреймворк для тестирования так же позволяет разобраться с одним фреймворком и продолжить изучение других API рантайма, а писать тесты на нём очень просто:
DreamShaded marked this conversation as resolved.
Show resolved Hide resolved

```javascript
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";

Deno.test("example test", () => {
const x = 1 + 2;
assertEquals(x, 3);
});
```

И, конечно, в отличие от NodeJS, который поддерживает TypeScript только через установку и конфигурацию отдельных пакетов, Deno из коробки предоставляет компилятор ts, что позволяет нам писать на TypeScript без установки дополнительных пакетов.

Последнее значительное отличие Deno от NodeJS - исходный код. NodeJS написан преимущественно на C|C++, а Deno - на Rust, на языке, известном более надёжной работой с памятью и мультипоточностью, а также даёт возможность расширять функциональность Deno с помощью плагинов, написанных на Rust.

## Использование

Deno поддерживают и используют достаточно много компаний: Slack, Netlify, SalesForce, Tencent, однако нет подробной информации о проектах и статистики использования.

## Минусы

Несмотря на то, что Deno позиционируется как следующий этап эволюции NodeJS, как переосмысление и исправление ошибок, Deno также не лишён и минусов:

1. Экосистема. NodeJS развивается с 2009 года, и имеет более двух миллионов пакетов, в отличие от Deno. Также хоть Deno и внедрил поддержку npm пакетов, совместимость не полная и перенос существующего проекта с NodeJS на Deno может затребовать колоссального рефакторинга.
2. Поддержка в IDE. Несмотря на то, что у Deno имеются все средства обеспечения качества кода "из коробки", IDE и редакторы могут не поддерживать плагины или лишиться поддержки при обновлении версии Deno, и проблемы уже возникали.
3. TS в коробке. Поддержка TS напрямую кажется отличным решением, однако даёт дополнительную нагрузку при компиляции "на лету". Это может приводить к замедлению работы и увеличению потребления ресурсов сервера.
4. Стабильность, поддержка. Так как Deno всё ещё является новым рантаймом, развивается, меняет, добавляет и выводит API, он не может обеспечить такую же стабильность, как у NodeJS. Кроме того, политика долгосрочной поддержки (LTS) всё ещё в планах.
Loading