Серверный javascript. Структура против функции. Условия, близкие к боевым

Рисунок 2.1 Архитектура среды клиент-серверного приложения на языке JavaScript

Три слоя - это:

  • WWW-клиенты (такие как Netscape Navigator-клиенты): Этот слой предоставляет приложению межплатформенный интерфейс конечного пользователя. Этот слой может также содержать некоторую логику приложения, такую как правила проверки данных, реализованные в клиентском JavaScript. Клиенты могут находиться внутри или за пределами прокси-сервера корпоративной сети.
  • Netscape WWW-сервер/БД клиент: Этот слой состоит из Netscape-сервера с включённым JavaScript. Он содержит логику приложения, обслуживает безопасность и контролирует доступ к приложению нескольких пользователей, используя серверный JavaScript. Этот слой позволяет клиентам как в пределах действия, так и за пределами прокси-сервера иметь доступ к приложению. WWW -сервер также работает как клиент с любым установленным сервером БД.
  • Серверы баз данных: Этот слой состоит из SQL-серверов БД, работающих обычно на высокопроизводительных рабочих станциях. Он содержит все данные БД, метаданные и правила ссылочной целостности/referential integrity, необходимые для работы приложения. Этот слой обычно находится в зоне действия прокси-сервера корпоративной сети и может предоставлять слой безопасности дополнительно к слою безопасности WWW -сервера. Netscape Enterprise Server поддерживает использование серверов БД: ODBC, DB2, Informix, Oracle и Sybase. Netscape FastTrack Server поддерживает только ODBC. Дополнительно о LiveWire Database Service см. Часть 3, "Служба LiveWire Database Service."

Клиентская среда JavaScript работает как часть WWW -клиентов, а серверная среда JavaScript работает как часть Netscape web-сервера с доступом к одному или более серверов БД. показывает более детально, как серверная среда JavaScript и приложения, созданные для неё, встраиваются в Netscape web-сервер.

Системные Требования

Чтобы разрабатывать приложения JavaScript, использующие преимущества и клиентского, и серверного JavaScript, Вам нужна подходящая среда для разработки и публикации. В целом рекомендуется разрабатывать приложения на системе, отделённой от сервера публикации, поскольку разработка потребляет много ресурсов (порты соединений, пропускная способность, время процессора и память). При разработке также может быть нарушена работа уже опубликованных приложений конечного пользователя.

Среда разработки JavaScript состоит из:

  • Утилит для авторизации и компиляции приложений JavaScript. Эти утилиты обычно находятся на машине разработчика.
  • Машины разработчика с web-сервером для запуска приложений JavaScript, находящихся в стадии разработки.
  • Машины публикации с web-сервером для публикации разработанных приложений. Конечные пользователи осуществляют доступ к приложениям, находящимся на этом сервере.

Необходимые утилиты:

  • Браузер с возможностью выполнения JavaScript, такой как Netscape Navigator, входящий в состав Netscape Communicator.
  • Компилятор приложений JavaScript, такой как компилятор web-серверов Netscape.
  • Редактор, такой как Emacs или Notepad.

Публикация и машины публикации требуют наличия следующего программного обеспечения:

  • Web-сервера;
  • Машины выполнения JavaScript, такой как машина web-серверов Netscape.
  • Возможности конфигурирования Вашего сервера для работы приложений JavaScript, как это сделано в JavaScript Application Manager, поставляемом вместе с web-серверами Netscape.

Кроме того, если ваше приложение использует JavaScript-службу LiveWire Database Service, Вам понадобится:

  • Программа - сервер реляционных БД на Вашей машине-сервере БД. См. документацию вашего сервера БД. В некоторых случаях Вам понадобится установить web-сервер и сервер БД на одной машине. О специфических требованиях серверного JavaScript см. Главу 10, "Конфигурирование Базы Данных."
  • Клиент БД и сетевое программное обеспечение на машине Вашего web-сервера. Если Вы используете одну машину и как сервер БД, и как web-сервер, типичное клиентское обеспечение БД как правило уже установлено при установке сервера БД. В противном случае Вам нужно удостовериться, что клиент БД установлен на той же машине, что и web-сервер, чтобы можно было иметь доступ к БД как клиент. О требованиях к клиентскому программному обеспечению см. дополнительно документацию поставщика БД.
Информация Конфигурации

В этом разделе рассматривается информация конфигурации для использования серверного JavaScript. Дополнительно о настройке БД для работы с сервисом LiveWire Database Service см. Главу 10, "Конфигурирование Базы Данных."

Подключение Серверного JavaScript

Чтобы запускать приложения JavaScript на Вашем сервере, Вы обязаны подключить машину выполнения JavaScript в вашем Server Manager, щёлкнув Programs, а затем выбрав серверный JavaScript. После появления промпта "Activate the JavaScript application environment/Активизировать среду приложений JavaScript ?" выберите Yes и щёлкните OK. У Вас спросят также об ограничении доступа к Application Manager. Дополнительно см.

ПРИМЕЧАНИЕ: Если Вы не подключите машину выполнения JavaScript, приложения JavaScript не смогут запускаться на этом сервере.

Чтобы использовать и сервлеты, и LiveWire, Вам необходимо подключить серверный JavaScript до подключения Java. Оба могут быть подключены через использование меню программ Administration Server"а. Если Вы модифицируете путь к классам/classpath в obj.conf , Ваши изменения будут утеряны, если Вы подключите/отключите серверный JavaScript или Java из программного меню Administration Server"а. Альтернативой редактирования директивы classpath в obj.conf является установка переменной окружения CLASSPATH в Unix или установка переменной CLASSPATH в установках System в Windows NT. Если Вам нужно редактировать obj.conf непосредственно, сохраните первоначальный файл на всякий случай. В Enterprise Server 4.0 Вы должны добавить CLASSPATH info в файлы конфигурации JVM (jvm12.conf для Solaris и NT) через интерфейс Enterprise Administration Server.

Как только Вы активируете среду приложений JavaScript, Вы обязаны остановить и рестартовать Ваш web-сервер, чтобы ассоциированные переменные окружения начали действовать. Если этого не сделать, приложения JavaScript, использующие службу LiveWire Database Service, работать не будут.

Защита Application Manager"а

Application Manager предоставляет контроль над приложениями JavaScript. В связи с его особыми возможностями Вы должны защитить его от неавторизованного доступа. Если Вы не ограничиваете доступ к Application Manager"у, любой может добавлять, удалять, изменять, стартовать и останавливать приложения на Вашем сервере. Это, естественно, может привести к нежелательным последствиям.

Вы (разработчик приложений на JavaScript) должны иметь права доступа для использования Application Manager"а на сервере разработчика, так как Вы используете его для работы с приложением при разработке. Администратор Вашего web-сервера, однако, может не предоставить Вам таких прав на сервере разработчика.

Если Вы подключите машину выполнения JavaScript в Server Manager"е, промпт спросит Вас, ограничивать ли доступ к Application Manager"у. Выберите Yes и щёлкните OK. (Yes - по умолчанию.) После этого любой, кто попытается получить доступ к Application Manager"у, обязан будет ввести имя пользователя и пароль Server Manager"а, чтобы получить возможность использовать Application Manager и приложение-образец dbadmin . Дополнительно см. руководство администратора для Вашего web-сервера.

Если Ваш сервер не использует Secure Sockets Layer (SSL), имя пользователя и пароль для Application Manager"а передаются по сети в некодированном виде. Перехватив эти данные, можно получить доступ к Application Manager"у. Если Вы используете тот же самый пароль для Вашего сервера администратора, хакер получит также контроль и над этим сервером. Следовательно, можно рекомендовать не использовать Application Manager вне прокси-сервера, если Вы не используете SSL. О том, как подключить SSL к серверу, см. справочник администратора Вашего web-сервера.

Вопрос “Зачем?” - самый главный при принятии любого решения. В нашем случае причин было несколько.

Во-первых, люди. Текущий шаблонизатор обрабатывался Си. Все вопросы о его изменениях решались не быстро. А самое главное, что писали шаблонизатор одни люди, а использовали совсем другие.

Вообще это частая и, на мой взгляд, не очень хорошая практика написания инструментов для верстальщиков. Понятно, что им нужны инструменты, но реализуют эти инструменты люди, которые весьма отдаленно себе представляют ежедневные задачи верстальщиков. Скорее наоборот, часто принимаются решения плана «дадим им писать условия и циклы, а больше на верстке ничего понадобится не может». Возможно, это вина самих верстальщиков и их квалификации.

Но в Mail.Ru Group есть целая команда высококвалифицированных людей, знающих JS, способных самостоятельно написать инструмент, а самое главное - они же им и будут пользоваться.

Во-вторых, задачи. Возьмем проект Почта@Mail.ru. Мы не можем отказаться от шаблонизации на сервере – нам нужна быстрая загрузка при первом входе. Мы не можем отказаться от шаблонизации на клиенте – люди должны видеть высокую скорость реакции на их действия, а значит, обязателен AJAX и шаблонизация на клиенте.

Проблема очевидна: два набора совершенно разных шаблонов на сервере и на клиенте. А самое обидное, что решают они одну и ту же задачу. Дублирование логики нас просто измотало.

V8 - это интерпретатор JavaScript, а значит, мы можем получить один шаблон, который работает как на сервере, так и на клиенте.

В-третьих, скорость. Прочитав много статей, в которых хвалят скорость v8, решили, что надо проверить их справедливость. Но сначала нужно было понять, каким мы хотим видеть новый шаблонизатор.

Что нужно

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

Я давно и много использую для трансформации XSLT (не самый быстрый вариант трансформации), хотя, если его правильно использовать, он показывает хорошие цифры (я говорю про libxslt). Но у XSLT есть очень мощный инструмент шаблонизации – переопределение шаблонов. Мы решили реализовать нечто похожее, но намного проще.

/head.xml … Mail.ru /mail.xml … Почта Mail.ru

Странно было бы использовать v8 и не дать в шаблонах доступ к JavaScript.

var text = “mail.ru” text

И еще много чего по мелочи, помимо стандартных условий и циклов.

В качестве синтаксиса для шаблонизатора мы взяли XML.

Поддержка базового функционала в IDE. Сто процентов популярных IDE знают, что такое XML. Расстановку переносов, подсветку, базовое автодополнение вы получаете бесплатно.

Валидация на уровне IDE. Валидный HTML получается за счет валидных шаблонов. Опять же, все IDE умеют валидировать xml как таковой.

Модульность из коробки (name spaces). Базовые возможности шаблонизатора очень быстро захочется расширить. Например, добавить тег, который позволяет делать проекты на нескольких языках. Система Name Spaces позволяет легко это сделать.

Широкий набор готовых инструментов. За много лет скопилось множество инструментов для обработки XML, например, библиотеки по обработке XML посредством XSL или целый класс SAX парсеров, XSD и DTD схемы для валидации и т.п.

Совпадение синтаксиса обрабатывающих конструкций и результирующих конструкций. Другими словами, создавать XML на XML удобно, fest-шаблоны легко читать. Плюс решены все вопросы экранирования данных.

Реализация

Ковбойство. Я сам недавно узнал, что есть такой термин.

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

Отличие этой задачи от типичной: был известен шаблон и результирующий HTML, который этот шаблон должен выдавать. Мы с Костей (Frontend разработчик почты) начали писать свои реализации. Раз в неделю мы сравнивали замеры скорости трансформации.

Мы выбрали два разных подхода: он компилировал шаблон в функцию, а я - в структуру. Пример самой простой структуры:

...", 04 {action:"value"}, 05 "json.value" 06 ]

Вторая строка означает начало шаблона. Третью надо просто отдать браузеру. Четвертая говорит, что пятую надо исполнить как JavaScript и результат исполнения отдать браузеру.

01 [ 02 {action:"template"}, 03 "....”, 04 {action:"if"}, 05 "json.value", 06 "true", 07 "false" 08 ]

Вариант немного сложнее. Четвертая строчка означает, что пятую надо исполнить и если результат истина или ложь, то отдать шестую или седьмую строку соответственно.

Вариант с функцией особо пояснять не надо.

01 function template(json){ 02 var html = ""; 03 html += "…"; 04 html += json.value; 05 return html; 07 }

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

Чтобы понимать, что дал такой подход: моя первая реализация выполняла задачу за 200ms. Когда мы выжали все, что можно, а потом соединили лучшее из двух наших программ, то получили 3ms.

Если описать текущую реализацию кратко, то мы циклы транслируем в циклы, условные операторы в условные операторы и т.д.

Fest:foreach for(i = 0; i < l; i++) {} fest:if if(value) {} fest:choose if(value) {} else {}

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

Важно, что шаблоны транслируются в JS-функцию, которая работает в режиме strict mode. Это не дает верстальщикам шансов написать код, который приведет к утечкам памяти.

Везде, где нужна логическая работа с данными, доступен JavaScript.

_javascript_

Все конструкции, которые предполагают исполнение JavaScript, оборачиваются в try catch.

Все конструкции, которые предполагают вывод в HTML после выполнения JavaScript, по умолчанию проходят HTML escape.

json.name
try { html += __escape(json.name) } catch(e) {}

С самого начала разработка шаблонизатора ведется в открытом виде.
https://github.com/mailru/fest

Возможности интеграции

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

Имея нулевой опыт программирования на Cи и Perl, я сделал тестовые примеры на обоих языках. Плюс на текущий момент у нас есть связка с Python.

Ну и, конечно, NodeJS для прототипов и браузеры - среды, где JavaScript шаблоны работают из коробки.

Условия, близкие к боевым

Получив 3ms, я пошел к сервер-сайд программистам. На вопрос, сколько у меня есть времени на запрос, который отдает список писем пользователя, они сказали: не больше 4ms. У меня уже было 3ms на трансформацию, надо было пробовать.

Список писем у нас отдает наш собственный http-сервер, написанный на Cи. Получение данных - операции, которые не конкурируют за процессор, поэтому их не замеряли. Остановились на подготовке данных к трансформации и на самой трансформации.

По историческим причинам наш http сервер хранит данные в плоском хеше.

Msg_length = 5 msg_1_title = “letter” msg_1_Unread = 1

Так как мы говорим о JavaScript, то первое, что приходит на ум, - это JSON

Msg = [ {title: “letter”, Unread: true} ]

Мы взяли строку с плоским хешом, поместили ее в память и стали добиваться результата, когда при трансформации шаблона в v8 JavaScript оперировал с JSON.

Вариантов перебрали много. Пробрасывать объект, пробрасывать строку и парсить ее на JavaScript, пробрасывать строку и пропускать ее через JSON.parse.

Как ни странно, самым быстрым оказалось преобразовать плоский хеш в строку, которая совпадает с JSON, и в v8 отдать строку

“template([ {title: \“letter\”, Unread: true} ])”

Но, несмотря на все, мы уперлись в 6ms при трансформации 2ms. Все были готовы сдаться. Я все же решил взять исходные данные, строку с плоским хешом и, используя тот же скомпилированный шаблон, получить нужный HTML на NodeJS.

Получил 4ms. Когда пришел с этой цифрой к нашим сишникам, честно говоря, ожидал фразы “Классно, но NodeJS писать у нас нет ресурсов” Но вместо этого услышал “Если NodeJS может за 4ms, значит мы тоже сможем!”.

Именно в этот момент я понял - мы доведем это до продакшена. Появилось второе дыхание!

Решение оказалось простым. Раз мы 67% времени теряем на подготовке данных, а данные в принципе у нас уже есть, надо выкинуть подготовку данных.

Мы пробросили в v8 фукцию __get(‘key’). Таким образом, мы из v8 забирали данные напрямую из хеша нашего http сервера. Нет конвертации данных в нужный формат. Нет преобразования этой строки в объект внутри v8. Мы вышли на 3ms и имели запас 1ms.

Почти продакшен

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

Берем отдельный сервер, поднимаем на нем версию http сервера, который работает с v8, и дублируем реальные запросы на него. Оставляем на 30 часов одно ядро 2.2 ГГц Xeon.

10 000 000+ хитов 1.6ms среднее время трансформации 992 422 10% между 2 и 5ms 208 464 2% между 5 и 10ms 39 649 0,4% больше 10ms

Только 12% были больше 2ms. v8 стабильно ведет себя по памяти.

Продакшен

Я пришел с последними цифрами к заместителю технического директора, сказав, что v8 готов к продакшену, надо сделать отдельный небольшой проект, который, если что, можно и забыть в случае неудачи. В ответ получил «цифры хорошие, отдельный проект, провал которого не страшен, - это правильно, но ты правда хочешь запустить v8? Начни с главной страницы Mail.Ru». Вопрос поставлен правильно – либо мы делаем дело, либо развлекаемся в сторонке.

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

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

Стали смотреть. Тут я немного расскажу про архитектуру главной. На ней собирается информация от разных проектов. Собирает ее внутренняя разработка, мы ее называем RB. Из 165кб, которые генерируются для отдачи главной, 100кб собирает RB. И происходит следующее: RB отдает куски HTML через http сервер в v8, v8 конкатенирует их со своими строками, а результат возвращает все это обратно в http-сервер.

Налицо двойной проброс данных. Сделали оптимизацию. Теперь v8 вместо построения одной большой строки, включающей в себя данные от RB, отдает данные сразу в http-сервер.

Push_string(‘foo’); __push_rb(id); __push_string(‘bar’);

Как плюс, нет конкатенации строк на v8, нет двойного проброса RB из сервера в v8 и обратно, а самое главное, любой проброс данных - это конвертация из utf-8 в utf-16 и обратно. V8 все хранит в utf-16.

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

А теперь поучительная часть. Я интереса ради взял нагрузку, которую мы тестировали, умножил на два, на количество демонов на машине и на количество машин. Получил 440 000 000 хитов. При этом у нас в сутки 110 000 000 хитов. Закрались смутные сомнения.

Пошли смотреть логии. Оказалось, что на каждый запрос с нагрузкой мы получали три запроса с отчетами в логи для статистики! Реальная нагрузка на один http-сервер в четыре раза ниже той, на которой тестируемся мы!

На следующее утро мы раскатили версию главной страницы с v8.

Данные на сегодня:
Размер отдаваемого HTML, который генерирует v8 65кб.
Время, работы v8 на запрос 1ms.
В среднем v8 требует 40MB на контекст.

Пара уточнений

Все, кто думают про v8, натыкались на статью Игоря Сысоева

На данный момент множество разработчиков говорят о Node.js , создавая высоконагруженные приложения, работающие в реальном времени. С Node.js вы можете использовать JavaScript как на клиенте, так и на сервере. В данном туториале мы установим Node и создадим вашу первую "Hello World" программу - масштабируемый сервер для стриминга Twitter сообщений.

Что такое Node.js?

Чаще всего JavaScript выполняется исключительно на стороне клиента, веб-браузера, но с недавних пор разработчики заинтересовались использование его на сервере, во многом благодаря проекту CommonJS . Из других заметных серверных JavaScript сред стоить отметить Jaxer и Narwhal . Однако Node.js отличается от подобных решений, так как в своей основе он работает следуея концепции событий, нежели потоков. Веб-сервер Apache к примеру, который обрабатывает PHP и другие CGI скрипты, основан на потоках, он создает отдельный поток для каждого запроса. Конечно этот подход работает для большинства приложений, однако модель основанная на потоках не подходит для приложений с продолжительным подключение в реальном времени, на подобии приложений как Friendfeed и Google Wave .

"Каждое действие с вводом/выводом (I/O) - асинхронное..."

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

Шаг 1 установка

Node.js работает на Unix подобных системах, к примеру Mac OS X, Linux b FreeBSD. К сожалению Windows не поддерживается на данный момент времени, так что если вы пользователь Windows, можно воспользоваться установленной на Virtualbox Ubuntu. Чтобы это сделать, ознакомтесь со . Вы должны воспользоваться терминалом для установки и запуска Node.js.

  • Скачайте последний релиз Node.js с nodejs.org (на момент написания данной статьи, последняя версия - 0.1.31) и распакуйте zip архив.
  • Откройте терминал и запустите следующие команды. cd /path/to/nodejs make sudo make install

    Много сообщений будет показано в терминале во время установки и компиляции Node.js.

  • Шаг 2 Hello World!

    Любое знакомство с новой технологией начинается с туториала "Hello World!", мы создадим простой HTTP сервер, который будет отправлять данное сообщение. Однако для начала, вы должны понять систему модулей Node.js. В Node функционал инкапсулирован в модули и для того, чтобы он работал нам предварительно следует загрузить интересующий нас модуль. Существует множество модулей, со списком можно ознакомиться в Node.js документации . Загрузить модуль можно с помощью функции require:

    Var sys = require("sys");

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

    Sys.puts("Hello World!");

    Запуск этих двух строчек кода также прост, как запуск команды node с именем javascript файла в качестве аргумента.

    Node test.js

    Этот пример выведет "Hello World!" в терминал, после того, как будет запущен.

    Для создания HTTP сервера, нам нужно будет вызвать require для http модуля.

    Var sys = require("sys"), http = require("http"); http.createServer(function(request, response) { response.sendHeader(200, {"Content-Type": "text/html"}); response.write("Hello World!"); response.close(); }).listen(8080); sys.puts("Server running at http://localhost:8080/");

    Этот скрипт импортирует sys и http модули и создаёт HTTP сервер. Анонимная функция передаваемая в http.createServer будет вызвана, каждый раз когда совершается запрос к серверу. Как только сервер будет создан, он будет прослушивать порт 8080. Когда приходит запрос к серверу, сначала отправляем хедер с типом контента (content type) и статус кодом 200 - успешно (successful). Затем мы посылаем "Hello World!" и закрываем соединение. После чего вы можете заметить, как мы явно закрываем соединение. Таким образом мы можем просто передавать данные клиенту, не закрывая соединения. Если запустить данный скрипт и перейти по адресу в браузере - http://localhost:8080/ , вы увидите "Hello World!"

    Шаг 3 простой статичный файловый сервер

    Хорошо, мы создали HTTP сервер, но кроме "Hello World" ничего не посылается, не важно какой адрес мы введём. Любой HTTP должен быть способен посылать статичные файлы, такие как HTML, изображение и другие файлы. Код ниже делает следующее:

    Var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"); http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { response.sendHeader(404, {"Content-Type": "text/plain"}); response.write("404 Not Found\n"); response.close(); return; } fs.readFile(filename, "binary", function(err, file) { if(err) { response.sendHeader(500, {"Content-Type": "text/plain"}); response.write(err + "\n"); response.close(); return; } response.sendHeader(200); response.write(file, "binary"); response.close(); }); }); }).listen(8080); sys.puts("Server running at http://localhost:8080/");

    Мы начали, загрузив все необходимые нашему коду модули. Включая sys , http , url , path , также fs или модули для работы с файловой системой. Далее мы создаём HTTP сервер, как делали это раньше. На этот раз, мы используем модуль url для парсинга входящих URL запросов, который будет находить путь к запрашиваемому файлу. Мы нашли имя файла на жёстком диске сервере используя path.join , который объединяет process.cwd() , или текущую рабочую директорию, к пути запрашиваемого файла. Далее, мы проверяем существует-ли файл, это асинхронная операция, тем самым требует каллбека. Если файл не существует, сообщение 404 Not Found будет послано пользователю и произойдёт возврат функции. В противном случае, мы читаем файл используя модуль fs , используя бинарную кодировку и посылая файл пользователю. Если случится ошибка чтения файла, мы показываем сообщение ошибки пользователю и закрываем соединение. Так как всё это работает асинхронно, сервер будет в состоянии обрабатывать другие запросы, читая файл с диска, не важно насколько он большой.

    Запустив данный пример и открыв http://localhost:8080/path/to/file , файл будет показан в браузере.

    Шаг 4 стриминг твитов в реальном времени

    Используя уже работающий, статичный файловый сервер, мы создадим сервер на Node.js, который будет показывать твиты клиенту, которые будут обрабатываться статичным файловым сервером. Для начала нам понадобиться один дополнительный модуль для данного примера: модуль для работы с событиями - events . В Node существует концепция называемая EventEmitter , который используется для обработки слушателей событий (event listeners) для асинхронных задач. Также как jQuery или другие JavaScript фреймворки для клиентской части, когда вы привязываете (bind) слушатель события к таким вещям, как клики мышки и AJAX запросы, Node позволяет вам привязать слушатель событий ко многим вещам, некоторые мы уже использовали. Сюда можно включить все операции ввода/вывода, такие как чтение или запись файла, проверка существует-ли файл, ожидание HTTP запросов и так далее. EventEmitter абстрагирует логику связывания (binding), развязывания (unbinding) и вызвает слушатели событий. Мы используем EventEmitter посылая сигналы слушателю события, когда новые твиты будут загружены. Первые несколько строк нашего стримера твитов включают все необходимые модули и определяют функцию для обработки статичных файлов, которые были взяты из предыдущего примера.

    Var sys = require("sys"), http = require("http"), url = require("url"), path = require("path"), fs = require("fs"), events = require("events"); function load_static_file(uri, response) { var filename = path.join(process.cwd(), uri); path.exists(filename, function(exists) { if(!exists) { response.sendHeader(404, {"Content-Type": "text/plain"}); response.write("404 Not Found\n"); response.close(); return; } fs.readFile(filename, "binary", function(err, file) { if(err) { response.sendHeader(500, {"Content-Type": "text/plain"}); response.write(err + "\n"); response.close(); return; } response.sendHeader(200); response.write(file, "binary"); response.close(); }); }); }

    Ранее мы использовали http модуль для создания сервера, но кроме этого у нас есть возможность, с помощью модуля, создать HTTP клиент. Мы будем использовать HTTP клиент для загрузки твитов из публичного лога Twitter, для этого нам понадобится функция get_tweets .

    Var twitter_client = http.createClient(80, "api.twitter.com"); var tweet_emitter = new events.EventEmitter(); function get_tweets() { var request = twitter_client.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"}); request.addListener("response", function(response) { var body = ""; response.addListener("data", function(data) { body += data; }); response.addListener("end", function() { var tweets = JSON.parse(body); if(tweets.length > 0) { tweet_emitter.emit("tweets", tweets); } }); }); request.close(); } setInterval(get_tweets, 5000);

    Сперва мы создадим HTTP клиент на порту 80 для api.twitter.com, и создадим новый EventEmitter . Функция get_tweets создаёт HTTP "GET" запрос к публичному логу Twitter, и добавляется слушатель, который будет срабатывать когда сервер Twitter даст ответ. Так как Node.js асинхронный, данные из тела ответа приходят кусками, которые затем обрабатываются ответом "data" слушателя. Данный слушатель добавляет куски сообщения переменной body . Как только придут все кусочки сообщения, запустится слушатель "end", и мы распарсим входящие JSON данные. Если возвращается лишь одит твит, мы создадим событие "tweets" для нашего tweet_emitter , и передадим массив с новыми твитами. Это вызовет все слушатели событий для работы с событием "tweets", и посылает новые твиты каждому клиенту. Мы запрашиваем новые твиты каждые пять секунд, используя setInterval .

    Наконец мы должны создать HTTP сервер для обработки запросов.

    Http.createServer(function(request, response) { var uri = url.parse(request.url).pathname; if(uri === "/stream") { var listener = tweet_emitter.addListener("tweets", function(tweets) { response.sendHeader(200, { "Content-Type" : "text/plain" }); response.write(JSON.stringify(tweets)); response.close(); clearTimeout(timeout); }); var timeout = setTimeout(function() { response.sendHeader(200, { "Content-Type" : "text/plain" }); response.write(JSON.stringify()); response.close(); tweet_emitter.removeListener(listener); }, 10000); } else { load_static_file(uri, response); } }).listen(8080); sys.puts("Server running at http://localhost:8080/");

    Также как мы сделали со статичным файловым сервером, мы создадим HTTP сервер работающий на порту 8080. Мы обрабатываем входящий URL, и если URL - "/stream" , мы обработаем его, в другом случае мы передадим запрос отключения нашему статичному серверу. Стриминг представляет из себя слушатель, который будет отслеживать новые твиты от нашего tweet_emitter , которые будут отправляться функцией get_tweets . Мы также создали таймер, для остановки запросов, которые длятся больше 10 секунд, отправляя им пустой массив. Когда появляются новые твиты, мы отправляем эти твиты в качестве JSON данных и останавливаем таймер. Вы лучше поймёте как это работает изучив код на стороне клиента, который показан ниже. Сохраните его как test.html в туже директорию где находится серверный JavaScript.

    Tweet Streamer var tweet_list = $("#tweets"); function load_tweets() { $.getJSON("/stream", function(tweets) { $.each(tweets, function() { $("

  • ").html(this.text).prependTo(tweet_list); }); load_tweets(); }); } setTimeout(load_tweets, 1000);

    У нас имеется простая HTML страница, в которую добавляется библиотека jQuery и создан неупорядоченный список, куда мы будем вставлять твиты. Клиентский JavaScript кеширует список твитов и запускает функцию load_tweets , по прошествию одной секунды. Так браузеру даётся достаточно времени для завершения загрузки страницы, до того как мы совершим AJAX запрос к серверу. Функция load_tweets очень проста; она использует jQuery функция getJSON для загрузки /stream . Когда приходит ответ, мы обходим циклом все твиты и добавляем их к списку твитов. После этого снова вызывается функция load_tweets . Тем самым создаётся цикл, который эффективно загружает новые твиты, таймер останавливается через десять секунд по истечению таймаута на сервере. Каждый раз когда у нас есть новые твиты, они посылаются клиенту, который поддерживает непрерывное соединение с сервером. Данный метод называется long-pooling.

    Если запустить сервер с помощью node и открыть http://localhost:8080/test.html , вы увидете публичный лог твиттера в вашем браузере.

    Следующие шаги

    Node.js очень впечатляющая технология, с которой легко создать высоконагруженные приложение в реальном времени. Надеюсь вам удалось понять все преимущества и можете их использовать в собственных приложениях. Поскольку Node обладает отличной системой модулей, можно с легкостью использовать написанный ранее код для ваших приложений, также имеется большое количество сторонних модулей, созданных для чего угодно - включая соединение с базой данных, шаблонизаторы, почтовые клиенты и даже целые фреймворки соединяющие всё вместе взятое. Вы можете ознакомиться с полным списком модулей на вики Node.js , ещё больше туториалов могут быть найдены на How To Node . Я также рекомендую посмотреть видео с JSConf, в котором Ryan Dahl, создатель Node, объясняет философию стоящию позади создания и дизайна Node. Оно доступно.

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

    Клиентский JavaScript расширяет ядро языка за счёт объектов, управляющих браузером (Navigator или другой подобный web-браузер) и его Document Object Model (DOM). Например, клиентские расширения позволяют приложению размещать элементы на HTML-форме и отвечать на пользовательские события, такие как щелчок мышью, ввод данных в форму и навигация по страницам.
  • Серверный JavaScript расширяет ядро языка за счёт объектов, имеющих отношение к работе JavaScript на сервере. Например, серверные расширения позволяют подключиться к реляционной БД, поддерживать непрерывность информации между вызовами приложения или работать с файлами на сервере.
  • JavaScript даёт Вам возможность создавать приложения, работающие в Internet. Клиентские приложения работают в браузере, таком как Netscape Navigator, а серверные приложения запускаются на сервере, таком как Netscape Enterprise Server. Используя JavaScript, Вы можете создавать динамические HTML-страницы, которые обрабатывают пользовательский ввод и работают с данными через использование специальных объектов, файлов и реляционных баз данных.

    С помощью функциональности LiveConnect Вы можете дать возможность коду Java и JavaScript взаимодействовать. Из JavaScript Вы можете инстанциировать Java-объекты и получить доступ к их public-методам и полям. Из Java Вы можете иметь доступ к объекта, методам и свойствам JavaScript.

    Netscape изобрела JavaScript, и JavaScript впервые был использован в браузерах Netscape.

    Ядро, клиентский и серверный JavaScript

    Компоненты JavaScript показаны на этом рисунке.

    Рисунок 1.1 Язык JavaScript

    Следующие разделы являются введением в JavaScript на клиенте и на сервере.

    Ядро JavaScript

    Клиентский и серверный JavaScript имеют следующие общие элементы:

    • Ключевые слова
    • Синтаксис и грамматику операторов
    • Требования к выражениям, переменным и литералам
    • Объектную модель (хотя клиентский и серверный JavaScript имеют разные наборы предопределённых объектов)
    • Предопределённые объекты и функции, такие как Array , Date и Math
    Клиентский JavaScript

    Web-браузеры, такие как Navigator (2.0 и более поздние версии), могут интерпретировать операторы клиентского JavaScript, внедрённые в HTML-страницу. Если браузер (или клиент ) запрашивает такую страницу, сервер высылает полное содержимое документа, включая HTML и операторы JavaScript, клиенту по сети. Браузер читает страницу сверху вниз, отображая результирующий HTML и выполняя операторы JavaScript по мере из обнаружения. Этот процесс, показанный на следующем рисунке, выдает пользователю конечный результат.

    Рисунок 1.2 Клиентский JavaScript

    Операторы клиентского JavaScript, внедрённые в HTML-страницу, могут реагировать на пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по странице. Например, Вы можете написать функцию JavaScript для проверки правильности введённой пользователем в форму информации - номера телефона или zip-кода. Без передачи по сети, JavaScript, внедрённый на HTML-страницу, может проверить введённые данные и вывести диалоговое окно, если пользователь ввёл неправильные данные.

    Разные версии JavaScript работают с конкретными версиями Navigator" а. Например, JavaScript 1.2 предназначен для Navigator 4.0. Некоторые возможности JavaScript 1.2 недоступны в JavaScript 1.1 и, следовательно, недоступны в Navigator 3.0. О версиях JavaScript и Navigator см. "Версии JavaScript" .

    Серверный JavaScript

    Серверный JavaScript также встраивается в HTML-страницы. Серверные операторы могут подключать к реляционным БД разных производителей, предоставлять информацию в совместное использование несколькими потребителями, давать доступ к файловой системе сервера или взаимодействовать с другими приложениями через LiveConnect и Java. HTML-страницы с серверным JavaScript могут также содержать клиентский JavaScript.

    В отличие от страниц, написанных на чисто клиентском JavaScript, HTML-страницы с серверным JavaScript компилируются в байт-код исполняемых файлов. Эти исполняемые файлы запускаются web-сервером, имеющим машину выполнения JavaScript. Поэтому создание приложений JavaScript это процесс из двух этапов.

    На первом этапе, показанном на , Вы создаёте HTML-страницы (которые могут содержать операторы клиентского и серверного JavaScript) и JavaScript-файлы. Затем Вы компилируете все эти файлы в единый исполняемый файл.

    Рисунок 1.3 Серверный JavaScript в процессе разработки

    На втором этапе, показанном на , страница приложения запрашивается клиентским браузером. Машина выполнения использует исполняемый файл приложения для поиска исходной страницы и динамически генерирует возвращаемую клиенту HTML-страницу. Машина запускает на выполнение операторы серверного JavaScript, найденные на странице. В результате этого на HTML-страницу могут быть добавлены новый HTML или операторы JavaScript. Машина выполнения высылает результирующую страницу по сети Navigator" у-клиенту, который запускает на выполнение клиентский JavaScript и выводит результаты.

    Рисунок 1.4 Серверный JavaScript на этапе прогона

    В отличие от стандартных программ Common Gateway Interface (CGI), весь исходный JavaScript интегрируется непосредственно в HTML-страницы, ускоряя разработку и облегчая обслуживание. Служба Session Management Service серверного JavaScript содержит объекты, которые Вы можете использовать для обслуживания данных, существующих в промежутке между клиентскими запросами, нескольких клиентов и нескольких приложений. Служба LiveWire Database Service серверного JavaScript предоставляет объекты для доступа к БД, являясь интерфейсом для Structured Query Language (SQL)-серверов БД.

    JavaScript и Java

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

    В отличие от системы времени компиляции классов Java, построенной на объявлениях, JavaScript поддерживает систему времени прогона, базирующуюся на небольшом количестве типов данных: числовых, Булевых и строковых значениях. JavaScript имеет объектную модель на основе прототипов, а не более распространённую модель на основе классов. Модель на прототипах предоставляет возможность динамического наследования; то есть то, что наследуется, может варьироваться для разных объектов. JavaScript также поддерживает функции без специальных требований к объявлению. Функции могут быть свойствами объектов, выполняясь как слабо типизированные методы.

    JavaScript намного более свободен по форме по сравнению с Java. Вы не должны объявлять все переменные, классы и методы. Вы не должны учитывать, какие методы являются public, private или protected и Вы не должны реализовывать интерфейсы. Возвращаемые значения переменных, параметров и функций не являются явно типизированными.

    Java это язык программирования на основе классов, созданный для быстрого выполнения и строгой проверки типов. Строгая проверка типов означает, к примеру, что Вы не можете привести/cast целое число Java к ссылке на объект или получить доступ к private-памяти, нарушив байт-коды Java. Модель классов Java означает, что программы состоят исключительно из классов и их методов. Наследование классов Java и строгая типизация обычно требуют плотно выстроенной иерархии объектов. Эти требования делают программирование на Java более сложным, чем авторизация в JavaScript.

    JavaScript по духу происходит от небольших, динамически типизируемых языков, таких как HyperTalk и dBASE. Эти языки программирования являются утилитами программирования для широкой аудитории, так как имеют упрощённый синтаксис, специализированную встроенную функциональность и минимальные требования при создании объектов.

    Таблица 1.1 JavaScript в сравнении с Java JavaScript Java

    Интерпретируется (не компилируется) клиентом.

    Скомпилированные байт-коды загружаются с сервера, выполняются на клиенте.

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

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

    Код, интегрированный с и внедрённый в HTML.

    Аплеты отличаются от HTML (при доступе из HTML-страниц).

    Тип данных переменной не объявляется (динамическая типизация).

    Тип данных переменной обязан быть объявлен (статическая типизация).

    Не может автоматически записывать на жёсткий диск.

    Не может автоматически записывать на жёсткий диск.

    Отладка в JavaScript

    JavaScript позволяет создавать сложные компьютерные программы. Как и в других языках, Вы можете ошибаться при написании скриптов. Отладчик Netscape JavaScript Debugger позволяет отлаживать Ваши скрипты. Об использовании Отладчика/Debugger см. следующие документы:

    • Netscape JavaScript Debugger 1.1 - введение в Debugger.
    • Вы можете загрузить Debugger с указанного URL. Загружаемый файл это SmartUpdate .jar. Для установки Debugger загрузите этот.jar-файл в Navigator: используйте процедуру, описанную в вышеуказанном URL, или введите URL к.jar-файлу в поле location (адресную строку).

    • Getting Started with Netscape JavaScript Debugger объясняет, как пользоваться Отладчиком.
    Visual JavaScript

    Netscape Visual JavaScript это утилита визуальной разработки на базе компонентов для платформы Netscape Open Network Environment (ONE). Она предназначена в основном для использования разработчиками, которые хотят создавать платформонезависимые web-приложения на основе стандартов из готовых к использованию компонентов с минимальными затратами на программирование. Эти приложения основаны на HTML, JavaScript и Java.

    JavaScript и спецификация ECMA

    Корпорация Netscape изобрела JavaScript, и JavaScript впервые был использован в Netscape-браузерах. Одновременно Netscape работает совместно с ECMA (European Computer Manufacturers Association) над созданием стандартизованного международного языка программирования на основе ядра JavaScript. ECMA это международная ассоциация стандартов для информационных и коммуникационных систем. эта стандартизованная версия JavaScript, называемая ECMAScript, работает совершенно одинаково во всех приложениях, поддерживающих данный стандарт. Компании могут использовать этот открытый стандартный язык для разработки своих реализаций JavaScript. Первая версия стандарта ECMA документирована в спецификации ECMA-262.

    Стандарт ECMA-262 одобрен также ISO (International Organization for Standards) как ISO-16262. Вы можете найти PDF-версию ECMA-262 на сайте Netscape DevEdge Online. Вы можете также найти эту спецификацию на web-сайте ECMA . Спецификация ECMA не описывает Document Object Model (DOM), которая стандартизована консорциумом World Wide Web Consortium (W3C) . DOM определяет способ, которым HTML-объекты документа экспонируются Вашему скрипту.

    Соотношение версий JavaScript и ECMA

    Netscape тесно сотрудничает с ECMA для создания ECMA-спецификации. В таблице показано соотношение между версиями JavaScript и ECMA.

    • Перевод

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

    Возможно, вы думаете, что подобные заявления звучат слишком уж напыщенно. Однако, попробуйте поискать в Google, и вы столкнётесь с неистощимым источником бесконечных споров . Среди рассуждений не в пользу Node, которые могут вам встретиться, есть, например, такие, которые, вопрошая о том, что случилось с аксиомой об использовании лучшего из имеющихся инструментов для решения некоей задачи, указывают, что JS и рядом не стоял с правильным серверным инструментарием. критические замечания о JS, вроде «Callback hell is real», призывающие поверить в реальность ада коллбэков, звучат как строчки из стихотворения. Некоторые из критиков Node выражаются более прямо и однозначно: «Node - это раковая опухоль».

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

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

    А именно, это среда выполнения JavaScript, построенная на базе JS-движка V8 , разработанного Google и применяемого в Google Chrome. Node.js использует неблокирующую модель ввода-вывода, управляемую событиями, которая делает эту платформу простой и эффективной.

    В начале этого материала Node показан как прямо-таки кошмар программиста. Однако, эта платформа не случайно стала весьма популярной. Тут мы не станем опираться на голословные утверждения. Лучше взглянем на факты. А именно, свежее исследование Stack Overflow показывает, что Node.js - это, на сегодняшний момент, самая популярная среди разработчиков технология.


    Кроме того, JS - это язык, популярность которого за последние пять лет растёт быстрее, чем у других языков, при том, что C# и PHP теряют позиции. Распространённость JavaScript, если даже не говорить исключительно о Node, идёт вверх.


    Как можно объяснить то, что JavaScript, в роли серверного языка, был столь быстро и широко принят сообществом разработчиков? Проще говоря, Node пережил стадию, в которой воспринимался как некая забава, и вошёл в фазу стабильности и зрелости. Вокруг него сформировалось мощное сообщество, размер которого неуклонно растёт. Экосистема Node также достойна упоминания, так как, например, менеджер пакетов Node, npm , в настоящий момент представлен самым большим реестром ПО в интернете.

    Node.js не только совершил революцию в серверной разработке, но благодаря ему сделан вклад и в производительность клиентских приложений, так как к развитию V8 были привлечены серьёзные силы. Кроме того, он играет заметную роль в расширении всей экосистемы JavaScript и в совершенствовании современных JS-фреймворков, таких, как Angular , React или Vue .

    С течением времени Node смог опровергнуть предрассудки ранних дней. Вот некоторые из них.

    JavaScript-код для Node.js печально известен сложностью отладки.

    Для отладки серверных JS-приложений можно использовать те же самые методики, которые применяются для отладки клиентского кода, применяя node-inspector , где собраны средства инструментов разработчика Chrome.

    Node нельзя использовать для разработки серверных приложений корпоративного класса.

    Это утверждение тоже не соответствует действительности. На базе Node можно создавать корпоративные системы. Сложность заключается лишь в том, что в нём имеется не особенно много встроенных средств, упрощающих создание подобных систем. Однако, заметные игроки IT-рынка используют Node в качестве корпоративной веб-платформы. Среди них - Netflix. PayPal, Yahoo!, Walmart.

    JavaScript - это динамический язык, поэтому, работая на нём, нельзя использовать нечто вроде статической проверки типов при компиляции.

    Это правда. Однако, в экосистеме JS появились средства вроде TypeScript и Flow, которые нацелены на работу с типами в JS, что позволяет повысить стабильность и предсказуемость программ, упростить отладку. В этой сфере можно воспользоваться и возможностями Closure Compiler от Google.

    JavaScript не создавался как язык для серверной разработки.

    Тут можно лишь сказать, что JS уже мог работать на серверах , тогда же, когда Netscape встроила поддержку этого языка в свой браузер. А было это аж в 1995-м. JS обычно называют языком клиентской веб-разработки лишь потому, что он полностью захватил эту сферу.

    На самом деле, этот список можно продолжать и продолжать.

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

    Сценарии применения Node Итак, зачем вообще рассматривать Node.js как средство серверной разработки в применяемом вами стеке технологий?▍Преимущества и общие характеристики Позвольте мне в двух словах обозначить самое важное:
    • Весьма вероятно, что клиентские части ваших веб-приложений написаны на JavaScript. В этом случае универсальность кода в применяемом стеке технологий - это важный плюс использования JS и на сервере, о котором стоит помнить.
    • Инструменты вроде webpack помогают в повторном использовании кода и на клиенте, и на сервере, что ведёт к его единообразию на всех уровнях системы.
    • Применяя JS на клиенте и на сервере , можно создавать веб-приложения, которые могут рендериться и в браузере, и на сервере . При этом такие системы обычно работают весьма чётко и понятно. Полагаю, это - просто потрясающе.
    • Появление в Node конструкции async/await полностью изменило подход к написанию асинхронного кода. Теперь такой код напоминает обычный синхронный код, и по внешнему виду, и по поведению. Механизм async/await поддерживается в Node начиная с версии 7.6 . Он, в частности, является решением печально известной проблемы ада коллбэков .
    Некоторые видят в сближении кодовой базы клиента и сервера минус Node.js, говоря о том, что он принуждает разработчика к использованию JavaScript. Однако, это не совсем так. При необходимости из Node-приложений можно обращаться к сторонним специализированным библиотекам.

    Скажем, вам нужны инструменты для кодирования видео. Для того, чтобы оснастить ими свой проект, написанный на JavaScript, вам не придётся искать какие-то малораспространённые таинственные библиотеки для Node. Вы вполне сможете воспользоваться проверенными инструментами, наладив взаимодействие с ними из Node. Или, например, если имеется некая библиотека на Python, выполняющая необходимые вам сложные вычисления, специально для работы с ней можно запустить микросервис и обращаться к соответствующим функциям этой библиотеки через REST API.

    Учитывая всё вышесказанное, можно выделить следующие варианты использования Node.js, в которых он в полной мере раскрывает свои сильные стороны.

    ▍Сценарий №1. Приложения реального времени Приложения для совместной работы (такие, как Trello и Google Docs), интерактивные чаты, системы мгновенного обмена сообщениями и онлайн-игры - это примеры приложений реального времени, при разработке которых особенности архитектуры Node.js могут сослужить вам хорошую службу.

    Время, необходимое этим приложениям для выполнения тех или иных действий, можно охарактеризовать, с точки зрения пользователя, словами «немедленно» и «сейчас» . Для нормальной работы таких приложений система, на которой они основаны, должна обеспечивать очень высокую скорость отклика на действия пользователя и низкий уровень задержек. Node отвечает этим требованиям.

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

    ▍Сценарий №2. Одностраничные приложения Одностраничное приложение - это приложение, которое представлено единственной загружаемой в браузер веб-страницей, содержимое которой динамически обновляется в ходе взаимодействия с ней пользователя. Большая часть нагрузки при работе таких приложений ложится на клиентскую часть системы, написанную на JavaScript.

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

    ▍Сценарий №3. Масштабируемость Сервер на Node никогда не окажется гораздо мощнее, чем нужно. Красота архитектуры Node заключается в её минималистичности, в том, что серверную часть приложений можно масштабировать в зависимости от потребностей проекта. Секрет тут кроется в правильном отношении к производительности.

    Даже название предмета нашего разговора, «node» акцентирует внимание на возможности построения систем из множества небольших распределённых вычислительных узлов, которые могут обмениваться друг с другом данными.

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

    Однако, надо отметить, что подобным возможностям масштабирования сопутствуют и определённые сложности. И, если потерять бдительность, Node.js может стать… опасным.

    Ограничения Node.js Если говорить честно, то Node позволяет разработчику, что называется, «выстрелить себе в ногу». В этом мире за всё надо платить, в том числе - и за широкие возможности по настройке системы и по подгонке её под свои нужды. Если работать с Node, не имея достаточного опыта или регулярно пуская дело на самотёк - можно столкнуться с серьёзными проблемами вроде потери клиентов.

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

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

    Node переворачивает всё, так сказать, с ног на голову. Разработчику даётся больше свободы, но путь к реализации задуманного может оказаться полным опасностей, если в ходе работы будут приняты неверные решения. Тут уместно будет вспомнить о пресловутом «аде коллбэков», который вдруг окажется совершенно реальным.


    Это не означает, что на Node нельзя создавать большие серверные приложения, но вышесказанное стоит постоянно держать в голове.

    Даже создатель Node.js, Райан Даль , в итоге, перед переходом к другим проектам, осознал ограничения системы. Он высказался на этот счёт весьма однозначно:

    «Думаю, Node - это не лучшая система для создания крупномасштабных серверных проектов. Я бы использовал для этого . И, честно говоря, именно поэтому я и оставляю работу над Node. Я однажды понял, что, на самом деле, это вовсе не самая лучшая система для серверной разработки ».

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

    Популярные вспомогательные средства для серверной разработки на JS Не слишком давно, если некто задумывался о том, чтобы создавать все части своей системы на JS, в голову тут же приходила мысль о стеке MEAN (MongoDB, Express, Angular и Node).

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

    Вот несколько популярных современных серверных JS-фреймворков:

    • Express.js был и всё ещё является самым популярным Node.js-фреймворком . Он быстр, компактен, не навязывает разработчику жёстких архитектурных решений. В основе его стремительного развития лежит простота и понятность. Возможно, он идеологически ближе всех остальных инструментов к идеям, лежащим в основе, Node, следуя которым он представляет собой легковесную модульную систему.
    • Meteor , с другой стороны, использует чистый JavaScript и Node.js внутри довольно-таки масштабной конструкции. Meteor и сам по себе - это целая экосистема, которая может подойти для разработки более сложных серверных приложений. Однако, использование Meteor может усложниться, если нужно что-то, что не встроено в систему.
    • Sails.js - это MVC-фреймворк реального времени. Он был разработал для имитации шаблона MVC на платформе Ruby on Rails, но при этом подразумевал поддержку требований современных веб-приложений. Работает это всё благодаря API, которые управляются данными, при наличии масштабируемой, сервис-ориентированной архитектуры.

      Полагаю, самое главное, что мне хотелось сделать - так это показать, что между безапеляционными «да» и «нет», которые можно встретить во многих рассуждениях о Node и о JS как о серверном языке, если обширная область «может быть».

      И, нравится это кому-нибудь или нет, интерес к Node постоянно растёт.


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

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

      Например, в компании Snipcart, где я работаю, используется архитектура.NET, о которой можно наговорить много всего нелицеприятного. Почему выбрана именно она? Да просто потому, что в конкретный момент она оказалась наилучшим инструментом для решения поставленной перед нами задачи.

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

      Теги: Добавить метки