-
Notifications
You must be signed in to change notification settings - Fork 636
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
97cde20
commit 1a00081
Showing
4 changed files
with
191 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,6 @@ | ||
--- | ||
name: 'Роман Троицкий' | ||
url: https://github.com/DreamShaded | ||
photo: 'photo.jpg' | ||
--- | ||
Влюблён во фронтенд. Один из организаторов [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,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) всё ещё в планах. |