Skip to content

Commit

Permalink
Добавляет обзор рантайма Deno
Browse files Browse the repository at this point in the history
  • Loading branch information
DreamShaded committed Jul 17, 2024
1 parent 97cde20 commit daf597e
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 0 deletions.
6 changes: 6 additions & 0 deletions people/dreamshaded/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
name: 'Роман Троицкий'
url: https://github.com/DreamShaded
photo: 'photo.jpg'
---
Влюблён во фронтенд. Один из организаторов [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, внедряя различные функции и архитектурные решения, направленные на улучшение безопасности, опыта разработчиков и производительности.

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

В первую очередь Райана смущала безопасность NodeJS: наличие неограниченного доступа к файловой системе, сети, переменным окружения создаёт значительный риск для безопасности в случае исполнения недоверенного кода. Так же у NodeJS нет механизмов для ограничения возможностей скриптов программно. В 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
```

Если мы установим пакет, которому необходимы дополнительные права, то при попытке выполнения увидим запрос:

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

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

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

<!-- !спорный тезис, спорный пример. У них разные задачи же. Тезис "украден" с чужой статьи -->
<!-- 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 рантайма, а писать тесты на нём очень просто:

```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) всё ещё в планах.

0 comments on commit daf597e

Please sign in to comment.