Разработка WEB-проекта на Node.JS: Часть 1
Прошла неделя с момента пиара на хабре моего проекта «Что делать?». Я напомню, что этот проект начинался, как эксперимент по разработке среднестатистического WEB-проекта целиком на JavaScript (Node.JS). Сейчас я хочу поделиться с сообществом результатами этого эксперимента, полученным полезным опытом, а также подробной картой с отмеченными на ней граблями.
Эпизод 1: начало пути
- Понять, насколько удобно разрабатывать обычные WEB-проекты на Node.JS;
- Сравнить скорость разработки на Node.JS с другими используемыми технологиями (в моём случае это были PHP и Java);
- Добраться до подводных камней, с которыми не сталкиваешься на многочисленных синтетических примерах;
- Оценить работу готового проекта: стабильность, устойчивость к нагрузкам, сложность поддержки и развития такого проекта.
Из всех фреймворков выбор пал на Express. Он показался мне наименее перегруженным излишествами и при этом наиболее полно соответствовал моим требованиям и его можно было легко дополнить сторонними модулями.
- MVC архитектура;
- Роутинг;
- Работа с СУБД;
- Шаблонизатор;
- Поддержка мультиязычности;
- Поддержка многопоточности;
- Минимальный оверхед.
Эпизод 2: путь самурая
Поигравшись немного с Express на тестовом примере, разобравшись в его архитектуре и изучив исходный код, я принял решение сделать свой фреймворк, который бы удовлетворял все мои потребности и не был перегружен лишним для меня функционалом. Велосипед — скажите Вы. Опыт — скажу я. Один из лучших способов понять систему — разработать её аналог самому. Фреймворк был разработан, отлажен, и на нём была основана первая версия сайта. Сайт был запущен, и я стал наблюдать за его работой, параллельно исправляя всплывающие ошибки и добавляя новые фичи.
Эпизод 3: великий потоп
Естественно, что первое время на сайте было крайне мало посетителей, чтобы хоть как-то объективно оценить его работу. Однако, через несколько дней, я обнаружил, что сайт лежит. Упал он молча, в логах не было ничего подозрительного, но падению сопутствовала серия быстро идущих друг за другом http-запросов — это был чей-то робот. Эти запросы никак нельзя было назвать нагрузкой, многие роботы сканируют сайты с такой скоростью, и падать из-за этого он никак не должен. Я поднял сайт и протестировал его через утилиту siege. И действительно — сайт ложился даже на совсем маленьком количестве параллельных запросов, что совершенно не соответствовало моим ожиданиям. Логи молчали. Печаль наростала. Начались раскопки.
Эпизод 4: первый камень
Повторяя эксперимент, я следил за тем, что происходит с сервером и обнаружил проблему — процесс node выжирал всю доступную память и либо вырубался, либо зависал (переставал принимать http-запросы). Оговорюсь, что во время разработки я старался следить за расходом памяти, т.к. это один из самых опасных моментов в долго работающих приложениях. Лишние замыкания не делал, var не терял, в общем вёл себя аккуратно. В очередной раз перебрав свой код, я убедился, что ошибка не в нём и, честно-говоря, огорчился, т.к. там было бы проще всего её исправить. Отладчик для Node.JS существует, он довольно удобный, но отлаживать Node.JS приложение сложнее из-за его асинхронной работы. Каюсь, я не достиг 80-го уровня в работе с этим замечательным инструментом и вычислить утечку не смог. Так закончился мой отпуск. Времени на познание силы Node.JS стало гораздо меньше, и я решил отложить это дело до лучших времён. Не удовлетворённый результатом, я написал маленькую утилитку, которая перезапускала процесс каждые сутки. На таких костылях сайт проработал 4-5 месяцев. Тем временем, развитие Node.JS не стояло на месте. Новые версии выходили одна за другой, да и сторонние модули тоже развивались, избавляясь от детских болезней.
Эпизод 5: новая надежда
И вот, после довольно долгого перерыва, в change log’е Node.JS появились записи об исправленных утечках памяти (версии 0.6.6 — 0.6.7). Так же, начиная с версии 0.6.0, в стабильный релиз попал cluster api, который позволял избавиться от лишних плясок для запуска нескольких процессов node. Всё это добавило энтузиазма и заставило посмотреть на проект под новым углом. К этому времени я уже видел, какие части моего фреймворка не используются, чего в нём не хватает, что не удобно. Плюс ко всему, я решил заменить MySQL (изначально использовался он) на MongoDB.
Ещё раз проанализировав популярные фреймворки, я понял, что все они, по большому счёту, представляют из себя сборки различных модулей и небольшие доработки “от себя”, а также диктуют свои правила построения приложения. Всё это загоняет в жёсткие рамки при сомнительном выигрыше. Если необходимо обновить отдельный модуль, а фреймворк с ним конфликтует, то придётся ждать, когда обновлённая версия будет добавлена в него разработчиками. Или если Вы хотите использовать модуль, который данный фреймворк не поддерживает, например, любимый шаблонизатор. Что делать? Форкать и добавлять поддержку, а потом вручную мёрджить обновления в ожидании, пока разработчики фреймворка примут ваш pull request? Нет!
Модульная система Node.JS вполне позволяет не использовать фреймворки (читать — готовые сборки модулей), а работать с модулями напрямую. При этом дополнительный функционал, вместо заворачивания в фреймворк, нужно выносить в отдельный модуль. Такой подход сильно увеличивает гибкость системы и улучшает повторное использование кода.
- Отказаться от использования фреймворка, перейти к прямому использованию модулей;
- Выбрать из огромного количества модулей наиболее подходящие для решения моей задачи;
- Заменить MySQL на MongoDB;
- Для организации запуска нескольких процессов node использовать, теперь уже нативный, cluster api.
Эпизод 6: эпик вин
Не скажу, что «хабраэффект» был огромным. Пришло всего пара тысяч человек. Через пару часов сайт упал, но не из-за нагрузки, а из-за моей ошибки. Да-да, в одном труднодоступном месте я допустил опечатку в имени переменной, что и послужило причиной падения. В остальном никаких проблем не возникло. Странички отдавались очень быстро, процессор не напрягался, память не текла. Уже неделю я не перезапускал node, и сайт продолжает стабильно работать. Такой результат, после предыдущего печального опыта, очень радует.
Выводы
Нельзя писать на JavaScript только ради JavaScript. Выбирать язык по причине того, что он крутой/новый/популярный (нужное подчеркнуть) — глупо. Нужно чётко понимать, чего мы хотим от технологии и что она может нам дать, а также что она попросит взамен. Моей главной задачей было выявить все эти “что” и получить ответ на вопрос: «подходит ли Node.JS для разработки среднестатистических WEB-проектов». Мой ответ — да, подходит. Но, как и в любой другой технологии, существуют трудности, с которыми придётся столкнуться. Начну я, пожалуй, с минусов, чтобы закончить на позитивной ноте.
Хьюстон, у нас проблемы
-1
Первое, с чем придётся столкнуться при разработке на Node.JS — это отсутствие полноценной IDE, работающей из коробки. Конечно, существуют плагины для Eclipse и NetBeans, есть частичная поддержка и в других IDE. Но назвать их полноценными решениями на данный момент нельзя. Есть очень перспективная разработка Cloud9 IDE. Она представляет из себя IDE для разработки на JavaScript прямо в браузере. Эта IDE быстро развивается и уже активно используется многими Node.JS разработчиками, но при этом, по моему субъективному мнению, она пока не готова для работы над большими проектами, хотя для написания небольших модулей использовать её очень удобно. За время работы над проектом я сменил не одну IDE. Начал с notepad++, долгое время использвал Cloud9 IDE, пробовал и другие, названий которых уже не вспомню, но в конце концов вернулся к NetBeans. Хоть там и нет поддержки Node.JS API, но с чистым JavaScript там работать довольно удобно. Пока остаётся ждать и надеется на появления полноценной поддержки. Разработка такого плагина уже ведётся.
-2
Вторым неприятным моментом станет необходимость перезапуска приложения после внесения каждого изменения. Несмотря на существование утилит, автоматизирующих этот процесс, некоторое время на это всё равно уходит. Так же быстро, как на PHP, внести изменение и сразу увидеть результат не получится. Однако, приложение перезапускается достаточно быстро — от одной до нескольких секунд, в зависимости от используемых модулей. В этом Node.JS, несомненно, выигрывает у Java — там перезапуск серьёзного WEB-приложения происходит намного дольше.
-3
Следующей проблемой, с которой столкнутся начинающие Node.JS разработчики, будет, скорее всего, утечка памяти. За памятью надо следить всегда и везде, но быстро живущие PHP-скрипты или небольшой клиентский JavaScript сильно расслабляют. В таких приложениях многие разработчики особо не предают значения потере нескольких килобайт памяти, а некоторые вообще не следят за этим показателем. Node.JS таких поблажек не делает. Приложение на Node.JS работает долго, и в случае утечки, каждый запрос к сайту будет уносить с собой кусочек памяти, которая очень быстро закончится, что приведёт к известным последствиям. Специфика JavaScript также располагает к появлению этого типа ошибок. Одно лишнее замыкание в большой области видимости или один потерянный var могут подарить Вам незабываемые часы дебага. Но в этом есть и плюс — такой опыт заставит любого разработчика ценить память и контролировать её использование при программировании на других языках. Лично я не считаю эту особенность минусом.
-4
Ещё одна особенность, которая доставляет неудобства — это возврат ошибок из асинхронного кода. Для сравнения, в PHP весь код выполняется синхронно, поэтому отловить ошибку на любом уровне вложенности можно с помощью конструкции try-catch. Мы можем завернуть в неё работу контроллера и при возникновении исключительной ситуации сделать throw, и ошибка «всплывёт» к ожидающему её обработчику, который покажет пользователю красивую страничку позора. Несмотря на то, что в JavaScript тоже есть конструкция try-catch, нам она не поможет, т.к. большая часть кода работает асинхронно (операции ввода/вывода). При этом исключительные ситуации, как правило, возникают не при вызове метода, а при работе его callback`а, который выполняется уже вне конструкции try-catch. Для передачи информации об ошибках в Node.JS принято использовать первый параметр callback-функции. Т.е. если у нас возникла ошибка, мы вызываем callback-функцию либо с одним единственным параметром, описывающем её, либо первый параметр выставляем в undefined/null, а в последующих передаём результаты работы нашего функционала. В реальных приложениях вложенность вызовов может быть довольно большой и каждый раз передавать ошибку наверх очень неудобно. Полагаю, что проблему всё же можно решить, применив AOP, но это тема выходит за рамки данной статьи.
-5
Также заставят понервничать и самые простые ошибки, которые довольно часто добираются и до production-сервера. Опечатка в имени переменной в очень редко выполняемом блоке кода может привести к остановке всего сайта или одного из процессов, если используется cluser api. Чтобы избежать подобных неприятностей, можно использовать утилиты, мониторящие работу приложения и перезапускающие его при необходимости, но настоящие ниндзя просто хорошо тестируют свой код (хотя никто не застрахован от ошибки в стороннем модуле).
-6
Последнее, что хотелось бы добавить — сложные математические расчёты не для Node.JS. На эту тему на хабе уже был очень флеймовый топик и смысла повторять тут всё, что написано в нём и комментариях к нему я не вижу. Скажу только, что у автора топика (конечно же, я имею ввиду автора оригинала, а не перевода) проблемы с выбором технологии, либо он просто троль. В Node.JS всё же возможно производить сложные математические расчёты, путём разбиения задачи на короткие итерации, выполняемые за несколько витков event loop, но это уже извращения и фанатизм. Гораздо проще выносить такие задачи за пределы event loop или вообще выбрать другую технологию для разработки.
А ради чего всё это?
Если к этому времени у Вас не возник такой вопрос, значит Вы либо опытный JavaScript-разработчик, либо поисковый робот, либо Чак Норрис (здравствуй, Чак!). Для всех остальных я попытаюсь описать преимущества, которые даёт нам разработка WEB-проекта на Node.JS.
+1
- Сохранить сам комментарий;
- Обновить пользователя (например, количество комментариев у пользователя и дату его последнего комментария);
- Обновить статью (аналогично обновлению пользователя);
- Записать в лог результат запроса.
+2
Второй очень приятной возможностью является то, что ответ клиенту можно (и нужно) отправить сразу же, как он будет готов, не дожидаясь завершения работы всей логики запроса. Вернёмся к предыдущему примеру. При добавлении комментария мы записываем в БД некий лог. Эта операция нужна нам, но не нужна пользователю для получения ответа. С Node.JS мы можем сформировать и отправить ответ, а потом доделать то, что нужно нам: записать логи, очистить кеш и т.п. Время ожидания пользователя, соответственно, уменьшается.
+3
Третий положительный фактор — мы имеем одинаковый язык на сервере и на клиенте, это позволяет повторно использовать некоторый код (валидация форм, построение шаблонов на клиенте и т.п.). Да и в целом, это очень упрощает разработку, особенно, когда клиентская часть приложения сложная и требует серьёзной работы, а не обработки пары-тройки событий на кнопках.
+4
Процесс Node.JS живёт долго и обрабатывает все http-запросы внутри себя. Это значит, что для каждого нового запроса не выполняется инициализация, как, например, на PHP. Настройки загружены, соединения с БД и с кешем открыты, код скомпилирован и готов к работе. Благодаря такой архитектуре и гибкости JavaScript открывается огромный простор для различных техник оптимизации. Например, один раз разобрав шаблон, можно хранить его в виде функции, принимающей на вход данные и возвращающей готовый HTML. Или можно легко организовать локальное (для процесса) кеширование, наиболее часто используемых данных, что даст прирост в скорости работы с ними даже по сравнению с memcached. Да, для PHP есть решения, которые позволяют частично ускорить процесс инициализации — APC для op-code, поддержка постоянных соединений в FastCGI и т.п. Но при сравнении ускоренного процесса инициализации с его отсутствием в принципе — выигрыш всегда будет за последним.
+5
Вокруг Node.JS за его относительно короткую жизнь уже образовалась солидная экосистема, включающая сотни модулей и, соответственно, их разработчиков. Во многом благодаря удобству github сообщество имеет отличный инструмент для развития этой экосистемы, которое идёт семимильными шагами, и свой вклад в это развитие может внести любой желающий. С помощью таких инструментов, как The Node Toolbox и npm, процесс поиска, выбора и установки необходимых модулей становится простым и быстрым.
+6
- Код написан плохо;
- У Вашего сайта огромная посещаемость.
Заключение
Node.JS это не волшебная палочка. Это мощный инструмент со своими плюсами и минусами, который следует использовать только тогда, когда нужен именно он. Результатом своего эксперимента я доволен. Проект работает быстро, имеет простой и понятный код, который легко развивать и поддерживать. Несмотря на некоторые недостатки, Node.JS удобно использовать для разработки WEB-проектов и я верю в его развитие в этом направлении.
Продолжение следует
Во второй части я более подробно остановлюсь на архитектуре приложения. Расскажу, какие модули я использовал и как организовано взаимодействие между ними.
Спасибо всем, кто дочитал. Буду рад увидеть Ваши отзывы и мнения в комментариях.
- node.js
- web программирование
- web-разработка
Руководство для начинающих по Node.js и NPM
Сегодня я познакомлю вас с самыми основами Node.js и NPM, включая объяснения того, как разрабатывать для Интернета в целом. Сразу предупреждаю: если вы знакомы с основами веб-разработки и NPM, вы можете пропустить эту статью и узнать больше об очень полезном NPX здесь.
Ок, отлично! Давайте начнем!
Node.js
Если вы читаете это, вы, вероятно, уже загрузили Node.js + NPM и начали с того, что окунулись в воды Javascript. Но первые шаги уже могут показаться пугающими: «Я просто хочу написать небольшую программу на Javascript, зачем мне все остальное?». Это понятно, но на самом деле ничего страшного.
Давайте начнем с самого начала: вы можете просто создать файл Javascript на любом месте вашего компьютера, обозначенный суффиксом «.js». Этот файл может быть заполнен кодом любым удобным для вас способом, но при этом не хватает одной вещи: как вы на самом деле запускаете свою программу? Вот где Node.js вступает в игру.
Node.js — это среда выполнения, специально предназначенная для Javascript. Как следует из описания, Node может запускать ваш код Javascript в определенной среде, которую сам Node предоставляет. Процесс всегда один и тот же: сначала вы запускаете Node.js, а когда Node запускается (что означает, что он закончил запуск), вы можете предоставить ему свой код Javascript.
Есть два способа передать ваш Javascript в Node в качестве входных данных:
- Напрямую к запущенному Node-процессу, построчно, без файлов
- Сообщая Node, какой файл Javascript загружать, без какого-либо построчного ввода
node
Построчно
После того, как вы успешно установили Node.js (это просто загрузка + запуск установщика, описания есть на веб-сайте Node), вы можете запустить Node.js из любого места либо в своем терминале (macOS/Linux), либо в PowerShell (Windows) . Команда выглядит так.
Да, это все! Вы только что успешно запустили Node! Вы заметили, как быстро это произошло? Одна из причин популярности Node.js заключается именно в его невероятно быстрой загрузке (среди прочего).
Теперь, когда Node запущен и работает, мы можем определить наше Javascript-приложение построчно. Каждый ввод обрабатывается и сохраняется в памяти. Вот небольшой пример.
(Hit enter after every line end) const greet = (name) => console.log("Hello, " + name); greet("Tom"); let x = 10; x = x + 5; (enter the following line to terminate node) .exit
Теперь это все хорошо и модно, но написание больших приложений требует, чтобы мы сначала набросали их в файлах, прежде чем отправлять в Node. Следующую главу, пожалуйста!
Ввод через файлы
Для этого примера вам понадобится текстовый редактор. По сути, вы можете использовать любую программу, которая может работать с текстом (например, TextEdit в macOS или Editor в Windows). Я рекомендую VS Code с открытым исходным кодом от Microsoft, но вы можете выбрать то, что лучше всего подходит для вашей эргономики.
Чтобы предоставить файл в качестве входных данных, нам просто нужно его создать. Просто создайте обычный текстовый файл с суффиксом «js» в его имени. Мы назовем наш файл app.js. Теперь откройте выбранную вами командную строку (та, которая использовалась в нашем первом примере). Убедитесь, что вы открываете его из каталога, в котором сохранен файл, это важно.
Если вы используете VS Code, вы можете использовать его встроенную командную строку, просто щелкнув правой кнопкой мыши в представлении проводника и вызвав «Открыть в коде» (в Windows) или перетащив каталог, содержащий файл, на значок кода VS в доке (macOS). Затем вы можете открыть его терминал, как описано здесь.
Когда терминал будет готов, просто введите следующую команду.
node app.js
Как видите, произошло несколько вещей:
- Узел запущен напрямую, без пользовательского ввода
- Node прогнал весь ваш файл сверху вниз, пока не достиг его конца
- Сам узел завершился, так как конец файла также означал конец его процесса.
И для базового ознакомления с Node.js самое то! После того, как вы загрузили Node и впервые испытали использование командной строки для запуска собственного приложения Javascript, построчно или из файла, вы официально стали разработчиком Javascript! Добро пожаловать в клуб!
Теперь я познакомлю вас с основной концепцией NPM. После следующей главы мы быстро рассмотрим связь между Node.js, NPM и веб-разработкой. Если вы хотите узнать больше о Node.js, вы можете ознакомиться с нашими историями о Javascript, цепочках инструментов и обо всем, что связано с кодированием, здесь. Я также связал некоторые полезные ресурсы в конце этой статьи, чтобы узнать еще больше.
Хорошо, давайте переместим один!
NPM, менеджер пакетов узлов
Как вы видели, управлять собственным кодом не так уж и сложно. Приложение может быть сохранено в файле, внесенные вами изменения останутся. Но что, если вы захотите использовать чужой код, скажем, криптографическую библиотеку или библиотеку обработки изображений? Вы каким-то образом должны поместить этот код рядом с вашим собственным, сделать его пригодным для использования в вашем приложении и держать все под контролем.
Наивным подходом было бы просто загрузить внешний код непосредственно из источника, например. Github и скопируйте библиотеку файл за файлом в свой собственный проект. Но это приводит к нескольким проблемам:
- Как лучше всего обновить этот внешний код? Копирование вручную — не лучшее решение.
- Как вы отслеживаете весь внешний код?
- Что, если сам этот внешний код опирается на библиотеки, которые не установлены в вашем проекте?
Все эти проблемы решает NPM, менеджер пакетов для Node.js. Работа менеджера пакетов в основном состоит в том, чтобы дать вам надежное решение о том, как добавлять, отслеживать и удалять внешний код, также известный как зависимости. Вот несколько примеров NPM в действии.
npm install serve-static npm remove serve-static
Естественно, этому менеджеру нужно несколько специальных файлов, чтобы отслеживать все зависимости в вашем проекте. Вот почему приложения, использующие NPM, имеют как минимум два файла: package.json и package-lock.json. Вы можете вызвать следующую команду, чтобы быстро создать новый пакет NPM.
npm init -y
Примечание: как мы видели в первой части этой статьи, NPM не нужен для использования Node.js или Javascript. Его основное внимание уделяется управлению вашими зависимостями — ни больше, ни меньше. Через NPM вы можете загрузить код, опубликованный на npmjs.com. Все эти внешние модули хранятся в вашем проекте в специальной директории с именем node_modules. Вам практически никогда не придется изменять этот каталог, так как он полностью управляется NPM.
Package.json дает вам представление о ваших текущих зависимостях в проекте. package-lock.json — это специальный файл, в котором хранятся некоторые метаданные об изменениях, касающихся вашего package.json-файла или каталога node_modules, и его можно пока игнорировать.
Думаю, я завершу свое описание самой основной концепции NPM, что он делает и какие файлы/каталоги создает автоматически. Дополнительная информация по ссылке в конце статьи.
Arc для веб-разработки
Отлично, теперь вы знаете основы Node.js и NPM. Но с какой стати все это вообще необходимо изучать, если вы просто хотите начать создавать свой собственный современный веб-сайт?
Как мы только что видели, NPM позволяет нам загружать код из обширной коллекции библиотек (точнее, самой большой из существующих). Для веб-разработки вам понадобится сервер, который может разместить (то есть предоставить) ваше веб-приложение. Существует множество доступных сервисов, где вы можете загрузить свой веб-сайт-проект и использовать существующую инфраструктуру, включая серверы, чтобы сделать веб-сайт доступным в Интернете.
А для локальной разработки также требуется сервер, чтобы загружать ваши локальные файлы и делать их доступными только вам на вашем устройстве во время разработки. Благодаря Node.js вы можете просто сделать это: сделать свой сайт доступным локально через так называемый локальный хост. Node.js имеет встроенные инструменты, необходимые для запуска локального сервера, но с помощью NPM ваше приложение может быть обогащено проверенными в боевых условиях компонентами, которые помогут вам создавать очень большие сервисы за короткий промежуток времени.
Конечно, это только начало: NPM содержит так много кода для создания современных веб-приложений (известных как PWA, «прогрессивное веб-приложение»), а также сложных серверов. Но для первого знакомства, я думаю, это объяснение должно подойти.
Я надеюсь, что смог помочь вам разобраться с Node.js и NPM. Первые шаги всегда самые трудные, но первые дни разработки и (много) обучения будут вознаграждены вашими навыками, расширяющимися до разработки современных веб-приложений, что позволит вам создавать все, что вы хотите.
Node.js и Express как они есть
Здравствуйте, любители нашего хаброблога и прочие читатели!
Мы планируем вновь отметиться на поле неувядающего Node.js и рассматриваем возможность издания этой книги:
Поскольку вполне понятен читательский интерес «а как он впихнул все это в двести страниц, и зачем мне это нужно»? под катом предлагаем перевод доскональной статьи Томислава Капана о том, зачем на самом деле нужен Node.js.
Благодаря растущей популярности, язык JavaScript в наше время активно развивается, и современная веб-разработка драматически изменилась по сравнению с недавним прошлым. Те вещи, которые мы сегодня можем делать в Вебе при помощи JavaScript, работающего на сервере, а также в браузере, было сложно себе вообразить еще несколько лет назад – в лучшем случае, такие возможности существовали только в песочницах вроде Flash или Java Applets.
Прежде чем подробно поговорить о Node.js, можете почитать о преимуществах полностекового использования JavaScript. При этом тесно переплетаются сам язык и формат данных (JSON), что позволяет оптимально переиспользовать ресурсы разработки. Поскольку это достоинство присуще не столько Node.js, сколько JavaScript в целом, мы не будем подробно останавливаться на этой теме. Но в этом и заключается ключевое преимущество, которое вы приобретаете, внедряя Node в свой стек.
В Википедии читаем: “Node.js – это пакет, включающий движок JavaScript V8 от Google, уровень абстракции платформы – библиотеку libuv, а также базовую библиотеку, которая сама написана на JavaScript.” Кроме того, необходимо отметить, что Райан Даль, автор Node.js, стремился создавать сайты, работающие в реальном времени и оснащенные push-функцией, под впечатлением от таких приложений как Gmail”. В Node.js он предоставил программистам инструмент для работы с парадигмой неблокирующего, событийно-ориентированного ввода/вывода.
Спустя 20 лет господства парадигмы «веб-приложения без сохранения состояния на базе коммуникации запрос-отклик без сохранения состояния» у нас наконец-то есть приложения с двунаправленной связью в реальном времени.
Короче: Node.js блистает в приложениях реального времени, так как задействует push-технологию через веб-сокеты. Что же в этом такого революционного? Ну, как уже говорилось, спустя 20 лет использования вышеупомянутой парадигмы появились такие двунаправленные приложения, где связь может инициировать как клиент, так и сервер, а затем приступать к свободному обмену данными. Такая технология резко контрастирует с типичной парадигмой веб-откликов, где коммуникацию всегда инициирует клиент. Кроме того, вся технология основана на открытом веб-стеке (HTML, CSS и JS), работа идет через стандартный порт 80.
Читатель может возразить, что все это было у нас уже не один год — в виде Flash и Java-апплетов — но на самом деле это были просто песочницы, использовавшие Веб в качестве транспортного протокола для доставки данных клиенту. Кроме того, они работали изолированно и зачастую действовали через нестандартные порты, что могло требовать дополнительных прав доступа и т.п.
Node.js при всех его достоинствах в настоящее время играет ключевую роль в технологическом стеке многих выдающихся компаний, непосредственно зависящих от уникальных свойств Node.
В этой статье мы поговорим не только о том, как достигаются эти преимущества, но и почему вы можете предпочесть Node.js — или отказаться от него — взяв в качестве примеров несколько классических моделей веб-приложений.
Как это работает?
Основная идея Node.js: использовать неблокирующий событийно-ориентированный ввод/вывод, чтобы оставаться легковесным и эффективным при обращении с приложениями, обрабатывающими большие объемы данных в реальном времени и функционирующими на распределенных устройствах.
В сущности, это означает, что Node.js не является платформой на все случаи жизни, которая будет доминировать в мире веб-разработки. Напротив, это платформа для решения строго определенных задач. Понимать это абсолютно необходимо. Разумеется, не стоит использовать Node.js для операций, интенсивно нагружающих процессор, более того — применение Node.js в тяжелых вычислениях фактически аннулирует все его преимущества. Node.js действительно хорош для создания быстрых масштабируемых сетевых приложений, поскольку позволяет одновременно обрабатывать огромное количество соединений с большой пропускной способностью, что равноценно высокой масштабируемости.
Тонкости работы Node.js «под капотом» довольно интересны. По сравнению с традиционными вариантами веб-сервисов, где каждое соединение (запрос) порождает новый поток, нагружая оперативную память системы и, в конце концов, разбирая эту память без остатка, Node.js гораздо экономичнее: он работает в единственном потоке, при вызовах использует неблокирующий ввод/вывод, позволяет поддерживать десятки тысяч конкурентных соединений (которые существуют в цикле событий).

Простой расчет: допустим, каждый поток потенциально может затребовать 2 Мб памяти и работает в системе с 8 Гб оперативной памяти. В таком случае мы теоретически можем рассчитывать максимум на 4000 конкурентных соединений плюс издержки на переключение контекста между потоками. Именно с таким сценарием приходится иметь дело при использовании традиционных веб-сервисов. Node.js, избегая всего этого, может масштабироваться более чем до миллиона конкурентных соединений (в качестве эксперимента для подтверждения концепции).
Разумеется, возникает вопрос о разделении единственного потока между всеми клиентскими запросами, именно в этом заключается основная «западня» при написании приложений с применением Node.js. Во-первых, сложные вычисления могут забить единственный поток Node.js, что чревато проблемами для всех клиентов (подробнее об этом ниже), поскольку входящие запросы будут блокироваться вплоть до завершения запрошенного вычисления. Во-вторых, разработчики должны быть очень внимательны и не допускать всплывания исключений до базового (самого верхнего) цикла событий Node.js, поскольку в противном случае экземпляр Node.js завершится (фактически же, обрушится вся программа).
Чтобы избежать всплывания исключений до самой поверхности применяется следующий прием: ошибки передаются обратно вызывающей стороне как параметры обратного вызова (а не выбрасываются, как в других средах). На случай, если какое-то необработанное исключение проскочит и всплывет, существует множество парадигм и инструментов, позволяющих следить за процессом Node и выполнять необходимое восстановление аварийно завершившегося экземпляра (хотя, пользовательские сеансы при этом восстановить не удастся). Наиболее распространенными из них являются модуль Forever, либо работа с применением внешних системных инструментов upstart и monit.
NPM: Менеджер пакетов Node
Обсуждая Node.js, просто необходимо упомянуть существующую в нем встроенную поддержку управления пакетами, для которой применяется инструмент NPM, по умолчанию присутствующий в любой установке Node.js. Идея модулей NPM во многом схожа с Ruby Gems: это набор общедоступных компонентов для многократного использования, которые легко установить через онлайновый репозиторий; для них поддерживается управление версиями и зависимостями.
Полный список упакованных модулей находится на сайте NPM npmjs.org, а также доступен при помощи инструмента NPM CLI, который автоматически устанавливается вместе с Node.js. Экосистема модулей совершенно открыта, любой может опубликовать в ней собственный модуль, который появится в списке репозитория NPM. Краткое введение в NPM (немного староватое, но по-прежнему актуальное) находится на сайте howtonode.org/introduction-to-npm.
Некоторые из наиболее популярных современных NPM-модулей:
- express: Express.js, фреймворк для веб-разработки для Node.js, написанный в духе Sinatra, де-факто – стандартный для большинства существующих сегодня приложений Node.js.
- connect: Connect – это расширяемый фреймворк, работающий с Node.js в качестве HTTP-сервера, предоставляющий коллекцию высокопроизводительных «плагинов», известных под общим названием «связующее ПО» (middleware); служит основой для Express.
- socket.io и sockjs – серверная часть двух наиболее распространенных сегодня веб-сокетных компонентов.
- Jade – один из популярных шаблонизаторов, написанный в духе HAML, по умолчанию используется в Express.js.
- mongo и mongojs – обертки MongoDB, предоставляющие API для объектных баз данных MongoDB в Node.js.
- redis — клиентская библиотека Redis.
- coffee-script – компилятор CoffeeScript, позволяющий разработчикам писать программы с Node.js при помощи Coffee.
- underscore (lodash, lazy) – Самая популярная вспомогательная библиотека JavaScript, упакованная для использования с Node.js, а также две аналогичные ей библиотеки, обеспечивающие повышенную производительность, поскольку реализованы немного иначе.
- forever – Вероятно, самая распространенная утилита, обеспечивающая бесперебойное выполнение сценария на заданном узле. Поддерживает работоспособность вашего процесса Node.js при любых неожиданных сбоях.
Список можно продолжать. Существует множество общедоступных полезных пакетов, перечислить их все здесь просто невозможно.
В каких случаях следует использовать Node.js
Чат — это наиболее типичное многопользовательское приложение, работающее в реальном времени. От IRC (были времена), использующих разнообразные открытые и открытые протоколы, функционирующие через нестандартные порты, мы пришли к современности, когда все можно реализовать на Node.js с применением веб-сокетов, действующих через стандартный порт 80.
Программа-чат — действительно идеальный продукт для использования Node.js: это легковесное приложение с высоким трафиком, интенсивно обрабатывающее данные (однако почти не потребляющее вычислительных мощностей), работающее на множестве распределенных устройств. Кроме того, на нем очень удобно поучиться, так как при всей простоте оно охватывает большинство парадигм, которые может потребоваться использовать в типичном приложении Node.js.
Попробуем изобразить, как оно работает.
В простейшем случае у нас на сайте единственная комната для чата, куда пользователи приходят и обмениваются сообщениями в режиме «один к многим» (фактически — «ко всем»). Допустим, у нас на сайте три посетителя, и все они могут писать сообщения на нашем форуме.
На стороне сервера у нас простое приложение Express.js, в котором реализуются две вещи: 1) обработчик запросов GET ‘/’, обслуживающий веб-страницу, на которой располагается как форум с сообщениями, так и кнопка ‘Send’, инициализирующая новое введенное сообщение и 2) сервер веб-сокетов, слушающий новые сообщения, выдаваемые клиентами веб-сокетов.
На стороне клиента у нас есть HTML-страница, на которой настроено два обработчика: один из них слушает события щелчка по кнопке ‘Send’, которая подхватывает введенное сообщение и спускает его на веб-сокет, а другой слушает новые входящие сообщения на клиенте для обслуживания веб-сокетов (т.е., сообщения, отправленные другими клиентами, которые сервер собирается отобразить при помощи этого специального клиента).
Вот что происходит, когда один из клиентов отправляет сообщение:
- Браузер подхватывает щелчок по кнопке ‘Send’ при помощи JavaScript-обработчика, забирает значение из поля ввода (т.e., текст сообщения) и выдает сообщение веб-сокета, воспользовавшись клиентом веб-сокетов, подключенным к нашему серверу (этот клиент инициализируется вместе с веб-страницей).
- Серверный компонент веб-сокетного соединения получает сообщение и перенаправляет его всем остальным подключенным клиентам широковещательным методом.
- Все клиенты получают новое сообщение по принципу push при помощи веб-сокетного компонента, выполняющегося на веб-странице. Затем они подхватывают контент сообщения и обновляют веб-страницу, добавляя на форум новую запись.

Это простейший пример. Для более надежного решения можно использовать простой кэш, основанный на хранилище Redis. Еще более продвинутое решение — очередь сообщений, позволяющая обрабатывать маршрутизацию сообщений к клиентам и обеспечивающая более надежный механизм доставки, который позволяет компенсировать временные обрывы соединения или хранить сообщения для зарегистрированных клиентов, пока они находятся в оффлайне. Но независимо от того, какие оптимизации вы выполняете, Node.js все равно будет действовать в соответствии с теми же базовыми принципами: реагировать на события, обрабатывать множество конкурентных соединений, поддерживать плавность пользовательских взаимодействий.
API ПОВЕРХ ОБЪЕКТНОЙ БАЗЫ ДАННЫХ
Хотя Node.js особенно хорош в контексте приложений, работающих в реальном времени, он вполне подходит и для предоставления информации из объектных баз данных (напр. MongoDB). Данные, сохраненные в формате JSON, позволяют Node.js функционировать без потери соответствия и без преобразования данных.
Например, если вы используете Rails, то вам пришлось бы преобразовывать JSON в двоичные модели, а потом снова предоставлять их в виде JSON по HTTP, когда данные будут потребляться Backbone.js, Angular.js или даже обычными вызовами jQuery AJAX. Работая с Node.js, можно просто предоставлять ваши объекты JSON клиенту через REST API, чтобы клиент их потреблял. Кроме того, не приходится беспокоиться о преобразовании между JSON и чем угодно еще при считывании базы данных и записи в нее (если вы используете MongoDB). Итак, вы обходитесь без множества преобразований, используя универсальный формат сериализации данных, применяемый и на клиенте, и на сервере, и в базе данных.
ОЧЕРЕДИ ВВОДА
Если вы получаете большие объемы конкурентных данных, то база данных может стать узким местом. Как показано выше, Node.js с легкостью обрабатывает конкурентные соединения как таковые. Но поскольку обращение к базе данных является блокирующей операцией (в данном случае), у нас возникают проблемы. Решение в том, чтобы зафиксировать поведение клиента перед тем, как данные на самом деле будут записаны в базу.
При использовании такого подхода отзывчивость системы сохраняется и под высокой нагрузкой, что особенно полезно, если клиенту не требуется подтверждение о том, что запись данных прошла успешно. Типичные примеры: логирование или запись данных о пользовательской активности (user tracking), обрабатываемых по пакетному принципу и не используемых впоследствии; операции, итог которых должен отражаться мгновенно (например, обновление количества «лайков» в Facebook), где приемлема согласованность в конечном счете, так часто используемая в мире NoSQL.
Данные выстраиваются в очередь при помощи специальной инфраструктуры для кэширования и работы с очередями сообщений (напр., RabbitMQ, ZeroMQ) и перевариваются отдельным процессом базы данных, предназначенным для пакетной записи, либо специальными сервисами интерфейса базы данных, рассчитанных на интенсивные вычисления. Аналогичное поведение можно реализовать и при помощи других языков/фреймворков, но на ином аппаратном обеспечении и не с такой высокой и стабильной пропускной способностью.

Короче говоря, Node позволяет откладывать на потом операции записи в базу данных, продолжая работу в таком режиме, как если бы эти записи завершились успешно.
ПОТОКОВАЯ ПЕРЕДАЧА ДАННЫХ
На более традиционных веб-платформах HTTP-запросы и отклики трактуются как изолированные события; но фактически они представляют собой потоки. Этим моментом можно воспользоваться в Node.js для создания некоторых классных возможностей. Например, можно обрабатывать файлы, пока они еще закачиваются, поскольку данные поступают потоком, и мы можем работать с ними в онлайновом режиме. Это можно сделать, например, при кодировании видео или аудио в реальном времени, а также при установке прокси между различными источниками данных (подробнее см. в следующем разделе).
Node.js вполне можно использовать в качестве серверного прокси, и в таком случае он может обрабатывать большое количество одновременных соединений в неблокирующем режиме. Это особенно удобно при посредничестве между различными сервисами, у которых отличается время отклика, либо при сборе данных из множества источников.
Для примера давайте рассмотрим серверное приложение, обменивающееся информацией со сторонними ресурсами, собирающее информацию из различных источников или хранящее такие ресурсы, как изображения и видео, которые затем предоставляются сторонним облачным сервисам.
Хотя и существуют выделенные прокси-серверы, вместо них удобно использовать Node, особенно если прокси-инфраструктуры не существует, либо если вам нужно решение для локальной разработки. Здесь я имею в виду, что можно создать клиентское приложение, где будет применяться сервер разработки Node.js, где мы будем хранить ресурсы и делать прокси/заглушки для запросов к API, а в реальных условиях такие взаимодействия уже будут выполняться при помощи выделенного прокси-сервиса (nginx, HAProxy, т.д.)
ИНФОРМАЦИОННАЯ ПАНЕЛЬ БИРЖЕВОГО ТРЕЙДЕРА
Вернемся на уровень приложений. Еще один сегмент, где доминируют программы для ПК, но их можно с легкостью заменить веб-решением, работающим в реальном времени — это софт для биржевого трейдинга, где отслеживаются котировки, выполняются вычисления и технический анализ, вычерчиваются графики и диаграммы.
Если задействовать в таком случае веб-решение для работы в реальном времени, то пользующийся им брокер сможет легко переключаться между рабочими станциями или местами. Вскоре мы начнем замечать таких брокеров на пляжах Флориды… Ибицы… Бали.
ПАНЕЛЬ ДЛЯ МОНИТОРИНГА ПРИЛОЖЕНИЙ
Это еще один практический случай, для которого идеально подходит модель «Node+веб-сокеты». Здесь мы отслеживаем посетителей сайта и визуализируем их взаимодействия в реальном времени (если вас интересует такая идея, то она уже решается при помощи Hummingbird).
Можно собирать статистику о пользователе в реальном времени и даже перейти на более высокий уровень, дополнив программу целевыми взаимодействиями с посетителем, открывая канал связи, как только гость достигнет конкретной точки в вашей воронке (если вас интересует такая идея, то она уже решается при помощи CANDDi).
Представьте, как можно было бы оптимизировать бизнес, если бы вы могли в реальном времени узнавать, чем занимаются ваши пользователи – а также визуализировать их взаимодействия. Двунаправленные сокеты Node.js открывают перед вами такую возможность.
ИНФОРМАЦИОННАЯ ПАНЕЛЬ ДЛЯ ОТСЛЕЖИВАНИЯ СИСТЕМЫ
Теперь давайте поговорим об инфраструктурных аспектах. Допустим, есть SaaS-провайдер, желающий предложить пользователям страницу для отслеживания сервисов (скажем, статусную страницу GitHub). Имея цикл событий Node.js, можно создать мощный веб-интерфейс, где состояния сервисов будут асинхронно проверяться в реальном времени, а данные будут отправляться клиенту через веб-сокеты.
Такая технология позволяет сообщать о статусах как внутренних (внутрикорпоративных), так и общедоступных сервисов в реальном времени. Давайте немного разовьем эту идею и попытаемся представить сетевой операционный центр (NOC), отслеживающий работу приложений оператора связи, провайдера облачных сервисов/хостинг-провайдера или какой-нибудь финансовой организации. Все это работает в открытом веб-стеке на основе Node.js и веб-сокетов, а не Java и/или Java-апплетов.
Примечание: Не пытайтесь создавать на Node жесткие системы реального времени (т.e., требующие четко определенного времени отклика). Пожалуй, подобные приложения лучше разрабатывать на Erlang.
Где можно использовать Node.js
СЕРВЕРНЫЕ ВЕБ-ПРИЛОЖЕНИЯ
Node.js c Express.js также можно применять для создания классических веб-приложений на серверной стороне. Однако, пусть это и возможно, такая парадигма запрос/отклик, где Node.js будет переносить отображенный HTML, нетипична для данной технологии. Существуют аргументы как в пользу такого подхода, так и против него. Необходимо учитывать следующее:
- Если ваше приложение не выполняет интенсивных вычислений, нагружающих процессор, то его можно написать полностью на JavaScript, включая даже базу данных, если вы используете объектную базу данных (например, MongoDB) и JSON. Это значительно упрощает не только разработку, но и подбор специалистов.
- Поисковые роботы получают в ответ полностью отображенный HTML, что гораздо удобнее для поисковой оптимизации, чем, например, работа с одностраничными приложениями или веб-сокетным приложением, работающим на базе Node.js.
- Любые интенсивные вычисления, нагружающие процессор, будут блокировать динамичность Node.js, поэтому в таком случае лучше использовать многопоточную платформу. Также можно попробовать горизонтальное масштабирование вычислений [*].
- Использовать Node.js с реляционной базой данных по-прежнему довольно неудобно (подробнее см. ниже). Сделайте себе одолжение и выберите какую-нибудь другую среду, например, Rails, Django или ASP.Net MVC, если собираетесь заниматься реляционными операциями.
[*] В качестве альтернативы таким CPU-интенсивным вычислениям можно создать хорошо масштабируемую MQ-среду с обработкой на интерфейсе базы данных, чтобы Node оставался «на передовой» и асинхронно обрабатывал клиентские запросы.
В каких случаях не следует использовать Node.js
СЕРВЕРНОЕ ВЕБ-ПРИЛОЖЕНИЕ, ЗА КОТОРЫМ РАСПОЛОЖЕНА РЕЛЯЦИОННАЯ БАЗА ДАННЫХ
Сравнивая Node.js плюс Express.js с Ruby on Rails, мы уверенно выбираем второй вариант, если речь идет о доступе к реляционным данным.
Инструменты реляционных баз данных для Node.js по-прежнему находятся в зачаточном состоянии, работать с ними довольно неприятно. С другой стороны, Rails автомагически настраивает доступ к данным прямо при установке, плюс предоставляет инструменты для поддержки миграций схем баз данных и прочие Gems. Rails и соответствующие фреймворки обладают зрелыми и проверенными реализациями доступа к уровню данных (Active Record или Data Mapper), которых вам будет остро недоставать, если вы попытаетесь воспроизвести такую конструкцию на чистом JavaScript.[*]
Все-таки, если вы твердо намерены все делать на JavaScript, обратите внимание на Sequelize и Node ORM2— оба инструмента пока не лишены шероховатостей, но со временем могут и дозреть.
[*] Можно использовать Node исключительно в клиентской части (нередко так и делается), а машинный интерфейс выполнить на Rails, сохранив, таким образом, легкий доступ к реляционной базе данных.
СЛОЖНЫЕ СЕРВЕРНЫЕ ВЫЧИСЛЕНИЯ И ОБРАБОТКА
Когда речь заходит о сложных вычислениях, Node.js оставляет желать лучшего. Разумеется, вы не собираетесь программировать на Node сервер для вычислений Фибоначчи. В принципе, любые вычислительные операции, сильно нагружающие процессор, девальвируют выигрыш в пропускной способности, который в Node достигается благодаря событийно-ориентированному неблокирующему вводу/выводу. Дело в том, что любые входящие запросы будут блокироваться, пока единственный поток занят перевариванием чисел.
Как было указано выше, Node.js однопоточный и использует всего одно ядро процессора. Может потребоваться реализовать конкурентность на многоядерном сервере, для этого команда разработчиков ядра Node уже занимается подготовкой специального кластерного модуля. Кроме того, вы без труда могли бы запустить несколько экземпляров сервера Node.js за обратным прокси с использованием nginx.
При кластеризации сохраняется возможность выгрузить все сложные вычисления в фоновые процессы, работающие в более подходящей среде, и обеспечить коммуникацию между ними через сервер очереди сообщений, например, RabbitMQ.
Хотя изначально ваша фоновая обработка могла протекать все на том же сервере, такой подход обеспечивает очень высокую масштабируемость. Подобные службы фоновой обработки легко можно распределить на отдельные рабочие серверы без необходимости конфигурировать нагрузки «фронтальных» веб-серверов.
Разумеется, такой подход уместен и на других платформах, но в случае с Node.js приобретается та самая огромная пропускная способность, о которой мы говорили выше, поскольку каждый запрос — это маленькая задача, обрабатываемая очень быстро и эффективно.
Заключение
Мы обсудили Node.js с теоретической и практической точки зрения, начав с его целей и назначения и закончив разговором о всяческих вкусностях и подводных камнях. Если у вас возникнут проблемы с Node.js, то помните, что почти всегда они сводятся к следующему факту: блокирующие операции — причина всех бед. В 99% процентах случаев все проблемы начинаются из-за неправильного использования Node.
Помните: Node.js никогда не предназначался для решения проблемы масштабирования вычислений. Он создавался для масштабирования ввода/вывода, с чем действительно справляется очень хорошо.
Зачем использовать Node.js? Если стоящая перед вами задача не предполагает интенсивных вычислений и обращения к блокирующим ресурсам, то можно в полной мере воспользоваться преимуществами Node.js и наслаждаться быстрыми и легко масштабируемыми веб-приложениями.
Интеграция ChatGPT с Node.js: руководство для начинающих
ChatGPT — это платформа от OpenAI, которая позволяет создавать пользовательские чат-боты, используя языковую модель GPT-3.
Языковая модель GPT-3 (generative pre-training transformer 3, генеративный предварительно обученный трансформер 3-го поколения) — это крупнейшая продвинутая модель обработки естественного языка (NLP), разработанная OpenAI. Она обучена на огромном наборе данных из текстов, написанных человеком, и способна генерировать текст, близкий к человеческому, оперируя широким диапазоном языков и стилей.
Модель GPT-3 использует архитектуру трансформера — типа нейронной сети, оптимально подходящего для обработки последовательно передаваемых данных, таких как текст. GPT-3 способна выполнять различные задачи, связанные с языком, в том числе перевод, автоматическое реферирование и ответы на вопросы, а также генерировать текст, который трудно отличить от того, что создан человеком.
Платформа ChatGPT позволяет разработчикам использовать модель GPT-3 для создания чат-ботов, которые могут вступать в естественный диалог с пользователем. Она предоставляет разработчикам простой, интуитивно понятный интерфейс и настройки, что упрощает создание чат-ботов, которые можно интегрировать в различные приложения и платформы.
ChatGPT и Node.js
Чтобы интегрировать ChatGPT в приложение Node.js, нужно использовать API OpenAI, который предоставляет программный интерфейс для взаимодействия с моделью ChatGPT. Сначала нужно получить API-ключ OpenAI, а затем использовать клиентскую API-библиотеку, например npm-пакет openai , для выполнения запросов к API из кода Node.js.
Получение API-ключа OpenAI
Чтобы получить API-ключ для API OpenAI, зарегистрируйтесь на сайте OpenAI.
Для этого нажмите кнопку “Sign Up” в правом верхнем углу главной страницы, а затем следуйте подсказкам по созданию нового аккаунта. После регистрации учетной записи вы сможете получить API-ключ, посетив раздел “API” в настройках аккаунта.
В разделе “API” нажмите кнопку “Generate API Key”, чтобы сгенерировать новый API-ключ, который затем можно использовать для выполнения запросов к API OpenAI из приложения Node.js. Позаботьтесь о безопасности API-ключа: не передавайте его другим лицам.
Создание проекта Node.js и установка пакета openai
Зарегистрировавшись на сайте OpenAI и получив API-ключ, приступайте к настройке нового проекта Node.js и установке пакета openai.
Сначала создайте папку нового проекта:
$ mkdir chatgpt-nodejs
Сделайте следующее изменение в папке проекта:
$ cd chatgpt-nodejs
Создайте файл package.json с помощью следующей команды:
$ npm init -y
Теперь можно установить npm-пакет openai:
$ npm install openai
Библиотека OpenAI Node.js обеспечивает удобный доступ к API OpenAI из приложений Node.js. В следующих шагах эта библиотека будет использована для реализации приложения Node.js.
Также нужно установить пакет dotenv:
$ npm install dotenv --save
Чтобы приступить к реализации, создайте в папке проекта два новых файла: index.js и .env :
$ touch index.js .env
Откройте файл .env в текстовом редакторе и вставьте следующую переменную среды (эта переменная содержит API-ключ из вашего аккаунта OpenAI):
OPENAI_API_KEY="INSERT YOUR OPENAI API KEY HERE"
Откройте файл index.js и добавьте 2 оператора require в его начало:
const < Configuration, OpenAIApi >= require("openai");
require('dotenv').config()
Теперь можно создать новую конфигурацию OpenAI, инициализировав объект Configuration и передав объект в конструктор, содержащий свойство apiKey . Значение, которое необходимо присвоить apiKey , — это API-ключ OpenAI, который можно считать из файла .env с помощью process.env.OPENAI_API_KEY .
const configuration = new Configuration( apiKey: process.env.OPENAI_API_KEY,
>);
const openai = new OpenAIApi(configuration);
Далее реализуйте асинхронную функцию runCompletion :
async function runCompletion () const completion = await openai.createCompletion( model: "text-davinci-003",
prompt: "How are you today?",
>);
console.log(completion.data.choices[0].text);
>
Внутри этой функции используется метод openai.createCompletion для создания OpenAI Completion — типа языковой модели, способной генерировать текст на основе запросов пользователя. Чтобы определить модель Completion, нужно передать объект конфигурации, который содержит два свойства: model (модель) и prompt (запрос).
Свойство model используется для указания языковой модели OpenAI, генерирующей ответ на текст, который присваивается свойству prompt . Применяемая в этом случае языковая модель text-davinci-003 является той же самой языковой моделью, которая используется в фоновом режиме ChatGPT.
Ответ, полученный от OpenAI API, записывается в командную строку.
Вот полный код JavaScript для index.js :
const < Configuration, OpenAIApi >= require("openai");
require('dotenv').config()
const configuration = new Configuration( apiKey: process.env.OPENAI_API_KEY,
>);
const openai = new OpenAIApi(configuration);
async function runCompletion () const completion = await openai.createCompletion( model: "text-davinci-003",
prompt: "How are you today?",
>);
console.log(completion.data.choices[0].text);
>
runCompletion();
Попробуйте запустить сценарий Node.js, набрав:
$ node index.js
После этого ответ от OpenAI можно будет прочитать в командной строке:
- Как работает маршрутизация Express
- Обзор JavaScript на основе диалога с ChatGPT
- Настраиваем автоматизированную модерацию с помощью OpenAI
Читайте нас в Telegram, VK и Дзен
