Узнайте, как серверный JavaScript развивался на протяжении многих лет, от среды выполнения на основе Java до появления Node.js, рождения NPM, растущей экосистемы, инновационного Deno и появления молниеносного Bun.

Первые дни

Когда мы говорим о серверном JavaScript, первое, что приходит на ум, — Node.js. Чего вы, возможно, не знаете, так это того, что серверный JavaScript существовал задолго до Node.
Это те, которые не произвели революцию в экосистеме. Это не вдохновило сообщество. Потерянные на страницах истории:

  • Джаксер
  • Шелк
  • РингоJS
  • Рино
  • AppEngineJS и т. д.

JavaScript избегали в бэкэнд-проектах по определенной причине. Серверы работали по модели «поток на запрос», которая плохо сочеталась с однопоточным JavaScript.

Занятость одного потока означала, что серверы будут работать медленно, поскольку они смогут обрабатывать только один запрос за раз.

Для достижения многопоточности такие библиотеки, как Ringo, создаются поверх виртуальной машины Java. Однако даже с помощью JVM ни один из них не смог решить проблему C10K (обработка 10 000 одновременных подключений на одном сервере).

Казалось, что в JavaScript не было решения этой проблемы, пока Райан Дал не представил Node.js в 2009 году.
Node.js не был основан на JVM, но решал проблему C10K. проблема.

Так что же выделяет Node.js? — Это было неблокирующее!

Node.js

Node.js — это кроссплатформенная асинхронная среда выполнения JavaScript с открытым исходным кодом, управляемая событиями, которая позволяет разработчикам запускать код JavaScript на сервере. Он построен на движке JavaScript V8, который является тем же движком, который используется в браузере Google Chrome.

Node.js позволял разработчикам работать с ОС через JavaScript, включая:

  • Файловая система
  • Проверьте операционную систему
  • Управление процессами

Помимо создания серверов HTTP и TCP, используйте DNS, CLI и этот список можно продолжать.

Минимализм, скорость и модульность (достигаемые с помощью модулей CommonJS) сделали Node.js идеальным выбором при разработке микросервисов.
В конце концов, Node.js предназначен для создания распределенных приложений со множеством узлов, отсюда и название Node.js.

Но Node.js не просто поднял планку. Оно уничтожило его, и все началось с того, что за кулисами работала гениальная архитектура.

Неблокирующий ввод-вывод

Будучи построенным на движке Chrome V8 (C++) и Libuv (библиотека C), Node.js позволял обрабатывать ввод-вывод и асинхронные задачи в дополнительных потоках вне JavaScript, в то время как планирование операций выполнялось в цикле событий.

Это означает, что Node.js может выполнять несколько запросов API или читать/записывать в файл/базу данных без ущерба для скорости или, говоря простым языком, — без блокировки основного потока JavaScript.

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

Эта формула повторно используется в Node.js для событий, сокетов, потоков и даже алгоритмов хеширования. Все, что не является задачей, связанной с процессором.

Команда Node.js пошла еще дальше, позволив вам расширить возможности приложения Node.js до предела возможностей вашего процессора. По умолчанию Node.js запускается на одном процессе вашего процессора, и если он выходит из строя, то все.
Но, позволяя разработчикам использовать дочерние процессы, Node.js может использовать всю мощь вашей машины, создавая копию для каждого процессора и балансируя трафик с помощью встроенного балансировщика нагрузки.

И если один из них терпит неудачу, Node.js разветвляет другой, и цикл возобновляется.
Поговорим о выходе за рамки «одного потока».

Node.js предоставляет все это изначально. Если вы почувствуете необходимость, вы можете расширить его возможности с помощью Nginx или диспетчеров процессов, таких как PM2, Docker или Kubernetes.
Появившиеся после него среды выполнения JavaScript пошли по стопам Node.js при разработке своих основанных на событиях (не блокирующая) архитектура.

Но помимо собственной механики Node.js также допускал обновления в виде сторонних пакетов для утилит, библиотек и фреймворков.

НПМ

Node Package Manager (NPM) — это менеджер пакетов для языка JavaScript, разработанный Исааком З. Шлютером. Цель NPM — позволить вам обновить Node.js или веб-приложение с помощью множества сторонних инструментов.

Добавить пакет очень просто:

> npm i package-name

Вот и все.
Пакет добавляется в проект (как показано в файле package.json) и готов к использованию. Не нужно самостоятельно искать CDN или настраивать .dll.

Некоторые пакеты предназначены исключительно для серверных или веб-приложений, тогда как другие работают на обоих концах. И есть множество менеджеров пакетов:

  • Нпм
  • Пряжа

Поскольку каждый может публиковать свои собственные пакеты, NPM превратился в один из крупнейших реестров инструментов с открытым исходным кодом.

Экспресс.js

Стандартный модуль HTTP-сервера, встроенный в Node.js, не оправдал ожиданий разработчика. Вскоре пришел Express, чтобы спасти положение.
Express — это минималистичная платформа API, которая популяризировала Node.js. Прелесть Express в том, что для запуска HTTP-сервера с нуля требуется всего несколько строк.

Еще одна особенность Express — его сверхрасширяемость. То, что не было разработано основной командой Express, было разработано сообществом разработчиков открытого исходного кода по всему миру.

Полный стек JavaScript

Поскольку Node.js — это серверная технология JavaScript, это означает, что разработчики интерфейсного, уже знакомые с JavaScript, могут перейти к бэкенд разработчикам без необходимости изучать новый язык программирования или стек.

В квартале появился еще один новичок. Примерно в том же году, что и Express, вышла MongoDB — база данных на основе документов, использующая структуру JSON для хранения данных. Команде MongoDB нужен был подходящий партнер для популяризации своей базы данных, и они нашли его в лице Node.js и Express.

  • С помощью веб-фреймворка JavaScript, такого как (Angular.js)
  • Серверный JavaScript-фреймворк сзади (например, Express.js)
  • База данных, похожая на JavaScript (MongoDB).
  • И встроенная среда выполнения JavaScript (Node.js).

Появились стеки JavaScript.

ECMAScript 6

ES6 (иногда называемый ES2015) был основной версией JavaScript, ставшей поворотным моментом для языка.

  • Пусть и Конст
  • Классы
  • Обещания
  • ES-модули
  • Сопоставление и установка структур данных
  • Стрелочные функции
  • Оператор распространения
  • Деструктуризация

Классы помогли разработчикам, перешедшим с других языков, на JavaScript, хотя по большей части классы — это всего лишь синтаксический сахар для наследования прототипов JavaScript.

Промисы были новым способом манипулирования асинхронными данными, более простым в использовании и более быстрым, чем обратные вызовы. В ES6 также появились функции генератора.

Синтаксис обратного вызова стал намного чище и проще благодаря функциям со стрелками, а оператор Spread и деструктуризация упростили извлечение данных из сложных структур.

Возможности модулей были также реализованы в браузерах. В отличие от модулей CommonJS, которые использовались в Node.js, новые модули ES импортировали пакеты асинхронно. Это позволило разделить файл сценария JavaScript на более мелкие файлы, соединенные вместе.

После внесения изменений в язык серверный JavaScript (Node.js) также должен был адаптироваться к нему, например, использовать функции ES6, позволяя обрабатывать асинхронные операции через Promises (а позже и Async Await), а также предоставляя модули ES. поддержка (последняя появилась в Node.js v13).

Упаковщики

У всех этих новых языковых функций и новых библиотек был один серьезный недостаток — поддержка браузеров. Если что-то работало в Google Chrome, оно может вести себя не так или вообще не работать в других веб-браузерах. В конце концов, каждый браузер построен на своем движке JavaScript.

Чтобы бороться с этим, фреймворки использовали транспиляторы, такие как Babel, и инструменты сборки, такие как Webpack, для объединения кода, написанного на ES6, React или TypeScript, в простой JavaScript.
Эти инструменты также обеспечивали различные оптимизации, такие как удаление импорта модулей ES (например, импорта библиотек), преобразование кода ES6 (и будущих версий ES) в эквивалент ES5, удаление пустых мест, сжатие изображений, а также автоматизация процесса.

После транспилирования и объединения код стал полностью исполняемым в браузере и Node.js. Хотя с годами технологии развивались и все современные браузеры поддерживают ES6, эти методы по-прежнему используются всякий раз, когда выходит новая версия ECMAScript.

Если вам нравится мой контент и вы хотите увидеть больше, купите мне чашку теплого кофе ☕

Машинопись

Одной из крупнейших инноваций (помимо ES6), привнесенных в язык JavaScript за последние годы, является TypeScript.

TypeScript — это язык с открытым исходным кодом, основанный на JavaScript и расширяющий его за счет добавления в язык строгих типов. TypeScript ограничивает разработчиков использованием типизированных переменных, таких как строки, числа, логические значения и массивы, но также вводит такие вещи, как словари, универсальные шаблоны, перечисления, интерфейсы, классы и кортежи, а также строгие проверки на null, предоставляя каждой функции больше контекста.

Однако TypeScript был не первой попыткой ввести строгие типы в JavaScript.

Еще в начале 2000-х годов возникла идея расширить JavaScript с помощью типов. Он имел кодовое название JavaScript ECMAScript 4. Однако изменения были слишком большими и не работали в браузерах того времени.

Можно с уверенностью сказать, что эксперимент провалился. Вот почему после ES 3.1 мы сразу перешли на ES5, а ES4 переделали в TypeScript.

Растущая экосистема

По мере роста популярности Node.js росла и экосистема. Внезапно JavaScript появился повсюду: на вашем телефоне, в настольных приложениях, во всех остальных блогах и на встречах разработчиков.

  • Кроссплатформенные инструменты (Electron, React Native, Ionic)
  • Инструменты визуализации (D3, Chart, Three.js)
  • Видеоигры (Фейзер)
  • Разнообразие веб-фреймворков (React, Angular, Vue)
  • Инструменты управления состоянием (Redux, Ngrx, Mobx)
  • Манипулирование временем и датой (Moment, DateFns, Day.js)
  • Библиотеки утилит (Lodash, Rx.js, Async.js)
  • Машинное обучение (TensorFlow.js)
  • Операционная система (NodeOS)

А также более 100 тысяч других модулей на NPM.

Если этого было недостаточно, поклонники бессерверных вычислений разработали платформу, позволяющую разработчикам настраивать инфраструктуру в виде кода и распределять ее по облачным платформам (AWS, Azure и GCP). Появилась бессерверная платформа.

Прогрессивные веб-приложения также стали реальностью. Node.js также эволюционировал. Поддержка HTTP 2, асинхронные перехватчики, рабочие потоки и режим наблюдения — и это лишь некоторые из них.
Тем временем поклонники Angular разработали Nest.js, новую серверную среду, в которой объектно-ориентированная парадигма (присутствующая в таких языках, как C# и Java) отдается предпочтение функциональному подходу, используемому Express.js.

JavaScript развивался по всем фронтам и, судя по всему, не собирается исчезать в ближайшее время.
Однако Node.js с трудом справлялся с этой задачей.

Node.js чакра

Была еще одна версия Node.js.
Node.js Chakra — это попытка Microsoft воссоздать Node.js с использованием их движка JavaScript Chakra. Он был известен своей высокой производительностью, специально предназначенной для платформы Windows.

Однако этого не должно было случиться. Популярность Node.js Chakra была настолько низкой, что Microsoft отказалась от проекта и тоже начала использовать V8.

Проблемы с Node.js

Со временем недостатки Node.js стали более очевидными.

ES-модули

Когда Frontend JavaScript начал использовать модули ECMAScript, стало ясно, что Node.js должен следовать этой тенденции. Однако более старые модули NPM по-прежнему полагались на модули CommonJS. Это означало, что создателям библиотек также необходимо было изменить свои библиотеки, чтобы они либо работали только с модулями ES, либо поддерживали оба. Node.js изначально поддерживает оба варианта.

Машинопись

TypeSript улучшил Node.js во многих отношениях. Обратной стороной является то, что для его работы вам потребуется установить пакет ts-node, а также варианты TypeScript используемых вами пакетов NPM. Поэтому при установке Express вам также потребуется установить @types/express.
Некоторые пакеты никогда не имели варианта TypeScript и вообще несовместимы с TS. Плюсом является то, что в новые пакеты встроена поддержка TS, поэтому вам не придется устанавливать один и тот же пакет дважды.

Различные проблемы безопасности NPM

Одна вещь, которой известен NPM, — это проблемы с безопасностью. Поскольку любой может создать пакет и опубликовать его в NPM, ничто не мешает вам создавать вредоносное ПО и распространять его в Интернете. Также нет никаких предупреждений при установке пакета, который может быть вредным или устаревшим.

Эти проблемы преследовали разработчиков Node.js с момента его создания. Команда NPM постоянно занята исправлением этой проблемы.

Отсутствие стандартизации

Не существует предпочтительного способа настройки проекта в Node.js, не существует того, какие библиотечные инструменты использовать, или уникальной практики написания кода, которой следует следовать. Каждый второй пакет имеет свою реализацию (функциональную, событийную или объектно-ориентированную).

И все, что вам нужно, есть в NPM, чтобы вы могли бесконечно копаться и тестировать, подходит ли это вашему проекту. К счастью, в Интернете есть хорошие создатели контента, руководства и статьи в блогах, которые помогут вам найти нужные инструменты.

Глядя на эти проблемы, становится понятно, почему разработчики серверной части других языков держатся подальше от Node.js. Большинство проблем уже решено, но переход от одного стандарта к другому оставил след на многих разработчиках Node.js. Даже его создатель Райан Даль, который несколько лет назад решил создать новую среду выполнения JavaScript. Введите Дено.

Дено

Deno — это новый взгляд на серверный JavaScript. Новичок в квартале. Написанный на V8 и Tokio (библиотека Rust), в отличие от Libuv, он рекламировался как более быстрая и легкая среда выполнения.

Разработка изобретателем Node.js стала огромным маркетинговым ходом. Райан точно знал, что не так с Node.js и как его улучшить с помощью Deno. Во-вторых, увидев, что создатель Node.js, больше не использующий его, перетащил некоторых разработчиков Node.js на территорию Deno.

Deno привнес много нового:

  • Готовая поддержка TS
  • Встроенная поддержка модулей ES
  • Импорт модулей из онлайн-источника (без необходимости устанавливать их в вашей системе)
  • Нет каталога NPM/node_modules
  • Подсказки безопасности
  • Стандартизация
  • Ожидание верхнего уровня (использование ожидания без необходимости использования асинхронной функции) и т. д.

При установке пакета Deno задаст вам вопрос, хотите ли вы его установить или нет, и поделится подробностями об устанавливаемом пакете. Deno также совместим с большинством собственных API Node.js.

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

Более того, поклонники Node.js начали требовать включения в Node.js некоторых функций Deno, в первую очередь TypeScript «из коробки». Пока последнего еще не произошло.

Но при всех этих функциях была одна серьезная проблема — сторонние модули! Удаление NPM из Deno означало, что разработчикам пришлось заново изобретать велосипед для большинства функций, которые у них уже были в Node.js с NPM.

Конечно, команда Deno разработала способ включения некоторых пакетов NPM, но из-за значительной нехватки контента Deno так и не заменил Node.js. Вместо этого Node.js использовал несколько новых приемов, позаимствованных у Deno. Сегодня Node.js по-прежнему остается наиболее широко используемой серверной платформой в экосистеме JS.

Метафреймворки

В последние годы мы также наблюдаем рост популярности метафреймворков JavaScript — инструментов, которые могут создавать полноценные приложения (а не только половину приложения). Бэкэнд-часть отвечает за взаимодействие с базой данных, предоставление конечных точек и рендеринг контента несколькими способами:

  • Статические поколения сайтов
  • Серверный рендеринг
  • Поэтапная статическая регенерация,

в то время как интерфейсная часть представляет собой одностраничное приложение. Есть несколько инструментов, которые способны на это, и лидирует Next.js (от Vercel).

Новые фреймворки, такие как Svelte и Qwik, привнесли свои собственные функции, отказавшись от гидратации в пользу новой концепции — Возобновляемость.

Затем появился Vite — новый инструмент для разработки внешнего интерфейса, ориентированный на скорость и производительность и прямой конкурент Webpack.
Vite также нашел свое применение в бэкэнде. Команда Nest.js нашла SWC — платформу на основе Rust, которую можно использовать как для быстрой компиляции, так и для объединения в пакеты и которая совместима с Vite.

Излишне говорить, что движок V8 (который поддерживает Node.js) больше не рассматривается как Святой Грааль серверной разработки. Ржавчина начала брать верх, а затем совершенно неожиданно появился новый инструмент для забивания гроба.

булочка

В конце 2022 года в Интернете появились различные статьи по сравнению производительности среды выполнения JavaScript. Одной из них была новая сверхбыстрая технология — Бун.

Будучи написанным на Zig и полностью избегая движка V8, Bun оказался значительно быстрее, чем Deno и Node.js вместе взятые, но на этом преимущества не заканчиваются:

  • Готовая поддержка TypeScript
  • Поддержка основных модулей Node.js
  • поддержка НПМ
  • Встроенный упаковщик
  • Поддержка модулей ECMAScript и CommonJS.
  • Поддержка существующих платформ (таких как Next, Express или Nest)

Джаред Самнер (изобретатель булочек) создал монстра.

Бун произвел настоящий фурор в сообществе JavaScript.

Это не значит, что сейчас все идеально. Несмотря на то, что Бун открыл двери для NPM, существует длинный список пакетов, которые не работают должным образом. А поскольку Bun только вышел, ему явно не хватает опыта и упоминаний в Интернете по сравнению с предыдущими средами выполнения.

Лично для меня преимущество Bun не в том, что он быстрый или новый и разрекламированный, а в том, что Bun пытается создать стандарт.
Вместо того, чтобы отталкивать разработчиков и диктовать, как вы импортируете модули или откуда вы получаете свои пакеты, Бун призывает вас использовать методы, которые вы считаете подходящими, что, я думаю, является значительным шагом вперед в объединении разработчиков JavaScript и его экосистемы.

Бун будет развиваться. Ошибки исправляются и регулярно добавляются новые функции. Я с нетерпением жду возможности увидеть, куда Бан пойдет в ближайшие годы.

Будущее серверного JavaScript

За прошедшие годы JavaScript претерпел множество изменений. Некоторые расширения не удалось. Другие преуспели, и экосистема прошла через трудные этапы, чтобы достичь того, что она есть сегодня.

Находится ли сегодня серверный JavaScript в лучшем состоянии, чем много лет назад? Смотря как.

JavaScript продвинулся на расстояние, которое никто не мог предсказать по сравнению с тем, что было до Node.js, не говоря уже о том, когда JavaScript появился в 1995 году.
Если вы опытный разработчик, вы должны найти изменения приятными и иметь возможность быстро адаптироваться. Но если вы новичок в JavaScript и все это звучит как беспорядок из разных сред выполнения, языков, сборщиков, модулей и т. д., вы, вероятно, правы.

Я думаю, что в обозримом будущем Node.js по-прежнему будет удерживать звание лучшей среды выполнения серверного JavaScript. Несмотря на положительные стороны конкурентов, ни один другой инструмент не обладает такой стабильностью, таким количеством API и онлайн-справок, популярностью и не подвергался таким испытаниям на протяжении многих лет, как Node.js.

Я очень надеюсь, что однажды у нас будет лучшее из всех трех под одной крышей — быстрая, безопасная среда выполнения, имеющая готовую поддержку JS, TS и связывания, а также множество встроенных инструментов. и сторонние инструменты, а также используются разработчиками по всему миру.
На данный момент Bun — хороший способ добиться именно этого.

Одно можно сказать наверняка: вы можете точно сказать, что произойдет дальше в интригующем мире JavaScript.

Читать больше историй о JavaScript







Пока 👋