автордың кітабын онлайн тегін оқу Веб-разработка с применением Node и Express. Полноценное использование стека JavaScript
Научный редактор Ю. Имбро
Переводчик К. Синица
Технический редактор Н. Гринчик
Литературный редактор М. Куклис
Художник В. Мостипан
Корректоры Е. Павлович, Е. Павлович
Верстка Г. Блинов
И. Браун
Веб-разработка с применением Node и Express. Полноценное использование стека JavaScript. 2-е издание. — СПб.: Питер, 2021.
ISBN 978-5-4461-0590-8
© ООО Издательство "Питер", 2021
Все права защищены. Никакая часть данной книги не может быть воспроизведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Эта книга посвящается моей семье: отцу Тому, привившему мне любовь к технике, маме Энн, пристрастившей меня к сочинительству, и сестре Мэрис — неизменной собеседнице.
Введение
Для кого эта книга
Эта книга предназначена для программистов, желающих создавать веб-приложения (обычные сайты, одностраничные приложения с использованием React, Angular или Vue, REST API или что-то среднее между ними) с помощью JavaScript, Node и Express. Разработка для Node, использующей доступный и гибкий JavaScript, привела к созданию абсолютно нового круга программистов, среди которых оказалось немало самоучек.
Никогда еще в истории информатики программирование не было таким доступным. Количество и качество онлайн-ресурсов для его изучения (и получения помощи в случае возникновения проблем) потрясает и вдохновляет. Так что приглашаю вас стать одним из этих новых (возможно, выучившихся самостоятельно) программистов.
Кроме того, конечно, есть программисты вроде меня, давно работающие в этой сфере. Подобно многим разработчикам моего времени, я начал с ассемблера и языка BASIC, а затем имел дело с Pascal, C++, Perl, Java, PHP, Ruby, C, C# и JavaScript. В университете я узнал о языках программирования более узкого применения, таких как ML, LISP и PROLOG. Многие из них близки и дороги моему сердцу, но ни один из этих языков не кажется мне столь многообещающим, как JavaScript. Так что я пишу эту книгу и для таких программистов, как я сам, с богатым опытом и, возможно, более философским взглядом на определенные технологии.
Опыт работы с Node вам не понадобится, а вот хотя бы небольшой навык владения JavaScript необходим. Если вы новичок в программировании, рекомендую Codecademy (http://www.codecademy.com/tracks/javascript). Если же вы опытный разработчик, советую книгу Дугласа Крокфорда «JavaScript: сильные стороны»1. Приведенные в ней примеры актуальны для любой операционной системы, на которой работает Node, включая Windows, OS X и Linux. Они предназначены для людей, работающих с командной строкой (терминалом), так что вам понадобится хотя бы элементарное ее знание в рамках вашей системы.
Самое главное: это книга для программистов-энтузиастов, с оптимизмом смотрящих в будущее Интернета и желающих участвовать в его развитии, а также для тех, кто полон энтузиазма в изучении новых технологий и подходов к разработке веб-приложений. Если, мой уважаемый читатель, вы еще не относите себя к этой категории, надеюсь, что станете таким, когда прочтете книгу до конца.
Примечание ко второму изданию
Я получил удовольствие от написания первого издания этой книги и по сей день доволен практическими рекомендациями, которые мне удалось дать, а также теплым приемом со стороны читателей. Первое издание было опубликовано одновременно с выходом бета-версии Express 4.0, и хотя версия Express по-прежнему 4.х, сопутствующие ему промежуточное программное обеспечение и инструменты претерпели значительные изменения. Кроме того, развивался сам JavaScript и даже в способе разработки веб-приложений произошел тектонический сдвиг: от чистого рендеринга на стороне сервера к одностраничным приложениям (single-page applications, SPA). Хотя многие принципы, приведенные в первом издании, все еще актуальны и используются, конкретные методы и инструменты изменились, поэтому было решено выпустить второе издание. В нем, ввиду возрастающей роли SPA, основное внимание уделено Express как серверу для API и статических ресурсов. В книгу также включен пример SPA.
Структура книги
Главы 1 и 2 познакомят вас с Node и Express, а также с инструментами, которые вы будете использовать по ходу чтения книги.
В главах 3 и 4 вы начнете использовать Express и строить каркас учебного сайта, используемого в качестве примера в книге.
В главе 5 обсуждаются тестирование и контроль качества, а в главе 6 описываются некоторые наиболее важные структурные компоненты Node, их расширение и использование в Express.
Глава 7 знакомит с шаблонизацией (использованием семантической системы веб-шаблонов Handlebars) и закладывает основы практического построения сайтов с помощью Express.
Главы 8 и 9 содержат информацию о cookies, сеансах и обработчиках форм, а также очерчивают круг тем, знание которых понадобится для построения сайтов с базовой функциональностью с помощью Express.
В главе 10 исследуется промежуточное ПО (middleware) — центральная концепция Express.
В главе 11 объясняется, как использовать промежуточное ПО для отправки сообщений электронной почты с сервера, а также обсуждаются шаблоны сообщений и относящиеся к электронной почте вопросы безопасности.
Глава 12 предлагает предварительный обзор вопросов, связанных с вводом в эксплуатацию. Хотя на этом этапе прочтения книги у вас еще не будет всей информации, необходимой для создания готового к использованию сайта, обдумывание ввода в эксплуатацию сейчас избавит вас от множества проблем в будущем.
В главе 13 рассказывается о персистентности данных с упором на MongoDB (одну из основных документоориентированных баз данных) и PostgreSQL (популярную свободно распространяемую реляционную систему управления базами данных).
В главе 14 мы углубимся в подробности маршрутизации в Express (в то, как URL сопоставляются с контентом), а в главе 15 рассмотрим, как создавать API с помощью Express.
В главе 16 проводится реорганизация кода примера с преобразованием его в одностраничное приложение с Express в качестве сервера, предоставляющего API, который был написан в главе 15.
Глава 17 описывает подробности представления статического контента с упором на максимизацию производительности.
В главе 18 обсуждается безопасность: как встроить в ваше приложение аутентификацию и авторизацию (с упором на использование стороннего провайдера аутентификации), а также как организовать доступ к сайту по протоколу HTTPS.
Глава 19 объясняет, как осуществить интеграцию со сторонними сервисами. В качестве примеров приводятся социальная сеть Twitter, картографический сервис Google Maps и американский сервис службы погоды National Weather Service.
Главы 20 и 21 готовят вас к важному моменту — запуску сайта. Они описывают отладку, благодаря которой вы сможете избавиться от каких-либо недостатков перед запуском, и процесс запуска в эксплуатацию.
Глава 22 рассказывает еще об одном важном этапе — сопровождении.
Завершает книгу глава 23, в которой указаны дополнительные источники информации на случай, если вы захотите продолжить изучение Node и Express, а также места, где можно получить помощь и консультацию.
Учебный сайт
Начиная с главы 3, на протяжении всей книги будет использоваться единый пример — сайт турфирмы Meadowlark Travel. Первое издание я написал сразу же после возвращения из поездки в Лиссабон. На тот момент у меня на уме были путешествия, поэтому сайт, выбранный для примера, предназначен для вымышленной туристической фирмы из моего родного штата Орегон (western meadowlark — западный луговой трупиал — певчая птица — символ штата Орегон). Meadowlark Travel связывает путешественников с местными экскурсоводами-любителями и сотрудничает с фирмами, выдающими напрокат велосипеды и мотороллеры и предлагающими туры по окрестностям с акцентом на экотуризме.
Сайт Meadowlark Travel — вымышленный, но это работающий пример, демонстрирующий множество проблем, с которыми сталкиваются реальные сайты (интеграция сторонних компонентов, геолокация, электронная коммерция, безопасность).
Поскольку в центре внимания книги находится инфраструктура серверной части, учебный сайт не будет завершенным. Он лишь послужит вымышленным примером реального сайта, чтобы обеспечить наглядность в рамках определенного контекста. Если вы работаете над собственным сайтом, то сможете использовать Meadowlark Travel в качестве шаблона.
Условные обозначения
В этой книге используются следующие условные обозначения.
Курсив
Применяется для обозначения новых понятий и терминов, которые автор хочет особо выделить.
Шрифт без засечек
Используется для обозначения адресов электронной почты и URL-адресов.
Моноширинный
Используется для текста (листингов) программ, а также внутри абзацев для выделения элементов программ: имен переменных или функций, названий баз данных, типов данных, имен переменных среды, инструкций и ключевых слов, имен файлов и каталогов.
Моноширинныйполужирный
Обозначает команды и другой текст, который должен быть набран пользователем.
Моноширинныйкурсив
Показывает в тексте те элементы, которые должны быть заменены значениями, подставляемыми пользователем или определяемыми контекстом.
Этот значок означает совет или предложение.
Такой значок указывает на примечание общего характера.
Этот значок обозначает предупреждение.
Использование примеров исходного кода
Дополнительные материалы (примеры кода, упражнения и т.п.) доступны для скачивания по адресу https://github.com/EthanRBrown/web-development-with-node-and-express-2e.
Эта книга призвана помочь вам в работе. Примеры кода из нее вы можете использовать в своих программах и документации. Если объем кода несущественный, связываться с нами для получения разрешения не нужно. Например, для написания программы, использующей несколько фрагментов кода из этой книги, разрешения не требуется. А вот для продажи или распространения компакт-диска с примерами из книг издательства O’Reilly нужно получить разрешение. Ответы на вопросы с использованием цитат из этой книги и примеров кода разрешения не требуют. Но для включения объемных примеров кода из этой книги в документацию по вашему программному продукту разрешение понадобится.
Мы не требуем ссылки на первоисточник, но ценим, если вы не забываете об этом. Ссылка на первоисточник включает название, автора, издательство и ISBN. Например, «Веб-разработка с применением Node и Express, Итан Браун, Питер, 2020. 978-1-492-05351-4».
Если вам покажется, что использование кода примеров выходит за рамки оговоренных выше условий и разрешений, свяжитесь с нами по адресу permissions@oreilly.com.
От издательства
Ваши замечания, предложения, вопросы отправляйте по адресу comp@piter.com (издательство «Питер», компьютерная редакция).
Мы будем рады узнать ваше мнение!
На веб-сайте издательства www.piter.com вы найдете подробную информацию о наших книгах.
1 Крокфорд Д. JavaScript: сильные стороны. — СПб.: Питер, 2013.
Опыт работы с Node вам не понадобится, а вот хотя бы небольшой навык владения JavaScript необходим. Если вы новичок в программировании, рекомендую Codecademy (http://www.codecademy.com/tracks/javascript). Если же вы опытный разработчик, советую книгу Дугласа Крокфорда «JavaScript: сильные стороны»1. Приведенные в ней примеры актуальны для любой операционной системы, на которой работает Node, включая Windows, OS X и Linux. Они предназначены для людей, работающих с командной строкой (терминалом), так что вам понадобится хотя бы элементарное ее знание в рамках вашей системы.
Крокфорд Д. JavaScript: сильные стороны. — СПб.: Питер, 2013.
Благодарности
В создании этой книги огромную роль сыграло множество людей. Она не появилась бы без тех, кто повлиял на мою жизнь и сделал меня тем, кто я сейчас.
Я хотел бы начать с благодарности всем сотрудникам Pop Art: работа в компании усилила мою страсть к разработке. Помимо этого, я многому научился у тех, кто здесь работает. Без их поддержки ничего бы не вышло. Я благодарен Стиву Розенбауму за создание столь воодушевляющего места для работы и Дэлу Олдсу — за приглашение в команду, радушный прием и благородство. Спасибо Полу Инману за неизменную поддержку и вдохновляющее отношение к разработке и Тони Алферезе — за содействие и за то, что помог найти время для написания книги без последствий для Pop Art. Наконец, спасибо всем тем выдающимся специалистам, с которыми я работал и поддержку которых ощущал: Джону Скелтону, Дилану Халлстрему, Грегу Юнгу, Куинну Майклсу, Си Джею Стритцелю, Колвину Фритц-Муру, Диане Холланд, Сэму Вилски, Кори Бакли и Демиону Мойеру.
Я в большом долгу перед командой из Value Management Strategies, Inc, с которой сейчас работаю. Роберт Стюарт и Грег Бринк познакомили меня с бизнес-стороной программного обеспечения, а от Эшли Карсон я невероятно много узнал о процессах коммуникации в команде, сотрудничестве и эффективности. Я благодарен Scratch Chromatic за неиссякаемую поддержку. Терри Хейс, Черил Крамер и Эрик Тримбл, спасибо вам за тяжелый труд и помощь! Я также благодарен Демьяну Йетеру, Тайлеру Брентону и Брэду Веллсу за проделанную работу по анализу требований и управлению проектом. Спасибо вам за талантливых и увлеченных разработчиков, которые трудились со мной не покладая рук в VMS: Адама Смита, Шейна Райана, Джереми Лосса, Дэна Мэйса, Майкла Миау, Джулиану Сойфер, Мата Накатани и Джейка Фельдмана.
Спасибо всем моим товарищам по группе в школе рока! Какое это было сумасшедшее путешествие и какая колоссальная творческая разрядка! Особая благодарность преподавателям, которые делятся своими знаниями и страстью к музыке: Джошу Томасу, Аманде Слоун, Дэйву Конильо, Дэну Ли, Дереку Блэкстоуну и Кори Уэст. Спасибо всем за предоставленную мне возможность стать рок-звездой!
Зак Мейсон, спасибо тебе за вдохновение. Это, может быть, и не «Утраченные книги “Одиссеи”», но это моя книга, и я не знаю, рискнул бы я писать ее, если бы не твой пример.
Элизабет и Эзра, спасибо за ваши подарки. Я буду любить вас вечно.
Абсолютно всем я обязан своей семье. Я не мог бы желать лучшего воспитания, чем то, что мне дали родители. Я вижу, как и в моей сестре отразилась их исключительная забота о детях.
Большое спасибо Саймону Сен-Лорану за предоставленный шанс и Брайану Андерсону за ободрение и редактуру. Спасибо всему коллективу O’Reilly за преданность делу и энтузиазм. Спасибо Алехандре Ольвера-Новак, Четану Каранду, Брайану Слеттену, Тамасу Пиросу, Дженнифер Пирс, Майку Вилсону, Рэю Виллалобосу и Эрику Эллиоту за детальные конструктивные рецензии.
Кэти Робертс и Ханна Нельсон, спасибо вам огромное за бесценные советы и критику моих сумасшедших идей. Вы помогли этой книге стать реальностью. Спасибо Крису Ковелл-Шаху за великолепный отзыв на главу о тестировании и контроле качества.
И наконец, спасибо моим дорогим друзьям, без которых я просто сошел бы с ума. Байрон Клейтон, Марк Буз, Кэти Роберс, Кимберли Кристенс — люблю вас всех.
Об авторе
Итан Браун — вице-президент компании VMS. Он отвечает за архитектуру и реализацию VMSPro. За плечами Итана более 20 лет программирования в разных предметных областях. Он считает стек JavaScript той платформой, которая обеспечит будущее веб-программирования.
1. Знакомство с Express
Революция JavaScript
Прежде чем начать повествование об основном предмете этой книги, я должен рассказать вам о предпосылках и историческом контексте вопроса, то есть поговорить о JavaScript и Node.
Поистине наступила эпоха JavaScript. Скромно начав свой путь в качестве языка скриптов, выполняемых на стороне клиента, JavaScript стал распространенным языком программирования серверных приложений. Эта его роль резко выросла благодаря Node.
Перспективы всецело основанного на JavaScript стека технологий очевидны: больше никаких переключений контекста! Вам теперь не нужно переключать свои мысли с JavaScript на PHP, C#, Ruby, Python или любой другой серверный язык программирования. Более того, такая особенность позволяет разработчикам клиентской части перейти к программированию серверных приложений. Не стоит думать, однако, что программирование серверных приложений состоит исключительно из языка программирования. Для этого необходимо изучить немало дополнительного материала, но с JavaScript препятствием не будет по крайней мере язык.
Эта книга для всех, кто видит перспективы стека технологий JavaScript. Возможно, вы разработчик клиентской части, который хочет получить опыт серверной разработки. Может быть, вы опытный разработчик клиентских приложений, как я, рассматривающий JavaScript в качестве жизнеспособной альтернативы традиционным серверным языкам.
Если вы пробыли разработчиком программного обеспечения столько, сколько я, вы были свидетелем того, как в моду входили разные языки программирования, фреймворки и API. Некоторые из них остались на плаву, другие морально устарели. Вы, вероятно, гордитесь своим умением быстро изучать новые языки и системы. Каждый новый встречающийся вам язык кажется немного знакомым: один вы изучали в университете, другим пользовались, когда несколько лет назад выполняли какую-то работу. Смотреть на вещи с такой точки зрения неплохо, однако утомительно. Иногда вам хочется просто что-то сделать без необходимости изучать целую новую технологию или вспоминать навыки, которые вы не использовали на протяжении нескольких месяцев или даже лет.
JavaScript на первый взгляд может показаться маловероятным победителем в этом состязании. Если бы в 2007 г. вы сказали мне, что я не только стану считать JavaScript предпочтительным для себя языком, но и напишу книгу о нем, я счел бы вас сумасшедшими. Я разделял все типичные предрассудки относительно JavaScript: думал, что это игрушечный язык программирования, что-то для любителей и дилетантов, чтобы все уродовать и делать неправильно. Ради справедливости скажу, что JavaScript действительно снизил планку для любителей. Это привело к огромному количеству сомнительного JavaScript-кода, что не улучшило репутацию языка.
Очень жаль, что у людей много предрассудков относительно JavaScript. Это мешает им понять, насколько силен, гибок и элегантен этот язык. Многие только сейчас начинают воспринимать его всерьез, хотя язык в нынешнем виде существует примерно с 1996 г. (правда, многие из наиболее привлекательных его возможностей были добавлены лишь в 2005 г.).
Однако, раз вы купили эту книгу, вы, вероятно, свободны от подобных предрассудков. Возможно, подобно мне, вы избавились от них или у вас их никогда и не было. В любом случае вам повезло, и мне не терпится познакомить вас с Express — технологией, которая стала возможной благодаря этому восхитительному и неожиданному языку.
В 2009 г., спустя годы после осознания программистами мощи и выразительности JavaScript как языка написания клиентских скриптов, Райан Даль разглядел потенциал JavaScript как серверного языка и создал Node.js. Это было плодотворное время для интернет-технологий. Ruby (а также Ruby on Rails) заимствовал немало отличных идей из теории вычислительной техники, объединив их с некоторыми собственными новыми идеями, и продемонстрировал миру более быстрый способ создания сайтов и веб-приложений. Корпорация Microsoft в героической попытке прийти в соответствие эпохе Интернета сделала с .NET удивительные вещи, учтя ошибки не только Ruby on Rails, но и языка Java.
Сегодня благодаря технологиям транскомпиляции, таким как Babel, веб-разработчики могут свободно использовать самые последние функции языка JavaScript, не боясь оттолкнуть пользователей с более старыми браузерами. Webpack стал универсальным решением для управления зависимостями в веб-приложениях и обеспечения производительности. Такие фреймворки, как React, Angular и Vue, меняют подход к веб-разработке, а библиотеки для работы с декларативной объектной моделью документов (DOM) (такие как jQuery) — это уже вчерашний день.
Сейчас чудесное время для приобщения к интернет-технологиям. Повсеместно появляются замечательные новые идеи (или воскрешаются прекрасные старые). В наши дни дух инноваций и пробуждения ощутим как никогда.
Знакомство с Express
Сайт Express характеризует Express как «минималистичный и гибкий фреймворк для веб-приложений Node.js, обеспечивающий набор возможностей для построения веб- и мобильных приложений». Что же это такое на самом деле? Разобьем описание на составные части.
•Минималистичный. Один из наиболее привлекательных аспектов Express. Много раз разработчики фреймворков забывали, что лучше меньше, да лучше. Философия Express заключается в обеспечении минимальной прослойки между вами и сервером. Это не говорит о слабой надежности фреймворка или недостаточном количестве его полезных возможностей. Просто он в меньшей степени становится у вас на пути, позволяя более полно выражать свои идеи. Express предоставляет вам минималистичный фреймворк, а вы можете добавлять необходимый функционал в разных его частях, заменяя то, что вам никогда не понадобится. Это глоток свежего воздуха, ведь многие фреймворки создают раздутые, непонятные и сложные проекты еще до того, как вы написали хотя бы одну строчку кода. Зачастую первой задачей становится отсечение ненужного функционала или замена того, который не соответствует требованиям. Express практикует другой подход, позволяя вам добавлять то, что нужно, там, где нужно.
• Гибкий. Механизм действия Express очень прост: он принимает HTTP-запрос от клиента (которым может быть браузер, мобильное устройство, другой сервер, десктопное приложение — одним словом, все, что использует HTTP) и возвращает HTTP-ответ. Этот базовый шаблон описывает практически все, связанное с Интернетом, что делает приложения Express чрезвычайно гибкими.
•Фреймворк для веб-приложений. Наверное, более точным описанием будет «серверная часть фреймворка для веб-приложений». На сегодня под «фреймворками для веб-приложений» обычно имеются в виду фреймворки одностраничных приложений, такие как React, Angular или Vue. Тем не менее, за исключением небольшой группы отдельных приложений, большинство веб-приложений должно обмениваться данными и взаимодействовать с другими сервисами. Обычно это происходит через веб-API, который можно рассматривать как серверный компонент фреймворка веб-приложений. Обратите внимание, что построение всего приложения с рендерингом только на стороне сервера по-прежнему возможно (а иногда и желательно). В этом случае Express вполне может быть фреймворком всего веб-приложения!
В дополнение к характеристикам Express, явно указанным в его описании, я бы добавил две собственные.
•Быстрый. Express, став одним из лучших фреймворков для платформы Node.js, привлек много внимания со стороны больших компаний с высокопроизводительными и сильно нагруженными веб-сайтами. Это вынудило команду по разработке Express сконцентрироваться на производительности, и теперь Express — лидер в этом сегменте.
•Некатегоричный. Одними из отличительных особенностей экосистемы JavaScript являются ее размер и разнообразие. Ввиду того что Express зачастую занимает центральную позицию в разработке веб-приложений в Node.js, существуют сотни (если не тысячи) страниц сообщества, где подробно рассматриваются приложения Express. Разработчики Express, в свою очередь, предоставили чрезвычайно гибкую систему разработки промежуточного ПО, которая упрощает использование выбранных вами компонентов при создании приложения. В процессе разработки можно заметить, что Express отключает встроенные компоненты в пользу настраиваемого промежуточного ПО.
Я упомянул, что Express является «серверной частью» фреймворка для веб-приложений, поэтому следовало бы рассмотреть взаимодействие между приложениями на стороне сервера и на стороне клиента.
Приложения на стороне сервера и на стороне клиента
В приложении на стороне сервера рендеринг страниц (включая HTML, CSS, изображения и другие мультимедийные объекты и JavaScript) происходит на сервере, и затем они отправляются клиенту. В приложении на стороне клиента, напротив, большая часть пользовательского интерфейса отображается из исходного кода приложения, отправка которого происходит однократно. То есть после получения начального (обычно очень минимального) HTML-кода браузер динамически преобразует DOM с помощью JavaScript. Отображение новых страниц не зависит от сервера, хотя необработанные данные по-прежнему поступают с него.
Приложения на стороне сервера были стандартом до 1999 г. Фактически термин «веб-приложение» был официально введен в этом году. Я считаю период между 1999 и 2012 гг. эпохой Web 2.0, во время которой происходило развитие технологий и технических средств, ставших в дальнейшем приложениями на стороне клиента. К 2012 г., когда смартфоны прочно вошли в обиход, отправка как можно меньшего объема информации через сеть стала общепринятым подходом, что способствовало развитию приложений на стороне клиента.
Приложения на стороне сервера часто называются приложениями с рендерингом на стороне сервера (server-side rendered, SSR), а приложения на стороне клиента — одностраничными приложениями (SPA). Приложения на стороне клиента полностью реализуются в таких средах, как React, Angular и Vue. Мне всегда казалось, что «одностраничные приложения» — не совсем точное название, ведь с точки зрения пользователя они могут состоять из множества страниц. Единственное отличие состоит в том, что страницы загружаются с сервера или динамически отображаются на стороне клиента.
На самом деле грань между приложениями на стороне сервера и на стороне клиента размыта. В большинстве приложений на стороне клиента есть 2–3 HTML-пакета, которые могут быть отправлены клиенту (например, открытый интерфейс авторизации или обычный интерфейс и интерфейс администратора). Кроме того, для увеличения производительности загрузки первой страницы и для поисковой оптимизации (search engine optimization, SEO) одностраничные приложения зачастую комбинируются с рендерингом на стороне сервера.
Как правило, если с сервера отправляется небольшое количество HTML-файлов (обычно от одного до трех), а интерфейс пользователя многофункциональный, с большим количеством страниц и основан на динамическом управлении объектной моделью документов, то применяется рендеринг на стороне клиента. Бо'льшая часть данных (обычно в формате JSON) и мультимедийных ресурсов для различных представлений по-прежнему загружается из сети.
Для Express не имеет значения, создаете вы приложение на стороне сервера или на стороне клиента: он хорош в обоих случаях. Для него безразлично, какое количество HTML-пакетов вы предоставляете: один или сотню.
Хотя преобладание архитектуры одностраничных веб-приложений неоспоримо, в начале книги приводятся примеры для приложений на стороне сервера. Они все еще актуальны, а разница между предоставлением одного или нескольких HTML-пакетов незначительна. Пример одностраничного приложения приведен в главе 16.
Краткая история Express
Создатель Express Ти Джей Головайчук описывает Express как веб-фреймворк, вдохновленный основанным на Ruby веб-фреймворком Sinatra. Ничего удивительного, что Express заимствует идеи у фреймворка, написанного на Ruby: последний, будучи нацеленным на бо'льшую эффективность веб-разработки, ее ускорение и упрощение ее сопровождения, стал источником множества замечательных подходов к веб-разработке.
Хотя Express был вдохновлен фреймворком Sinatra, он тесно переплетен с Connect — подключаемой библиотекой для Node. Connect использует термин «промежуточное ПО» (middleware) для описания подключаемых модулей Node, которые могут в различной степени обрабатывать веб-запросы. В 2014 г. в версии 4.0 Express была удалена зависимость от Connect, но этот фреймворк по-прежнему включает позаимствованную из Connect концепцию промежуточного ПО.
Express был подвергнут весьма существенной переработке между версиями 2.x и 3.0, а затем еще раз между 3.x и 4.0. Данная книга посвящена версии 4.0.
Node: новая разновидность веб-сервера
В некотором смысле у Node много общего с другими популярными веб-серверами, такими как разработанный Microsoft веб-сервер Internet Information Services (IIS) или Apache. Но интереснее узнать, в чем его отличия. Так что начнем с этого.
Аналогично Express подход Node к веб-серверам чрезвычайно минималистичен. В отличие от IIS или Apache, для освоения которых могут понадобиться годы, Node легок в установке и настройке. Это не значит, что настройка серверов Node на максимальную производительность в условиях промышленной эксплуатации тривиальна, просто конфигурационные опции проще и яснее.
Другое базовое различие между Node и более традиционными веб-серверами — однопоточность Node. Сначала это может показаться шагом назад, но впоследствии становится ясно, что это гениальная идея. Однопоточность чрезвычайно упрощает задачу написания веб-приложений, а если вам требуется производительность многопоточного приложения, можете просто запустить больше экземпляров Node и, в сущности, получить преимущества многопоточности. Дальновидный читатель, вероятно, посчитает это каким-то шаманством. В конце концов, разве реализация многопоточности с помощью серверного параллелизма (в противоположность параллелизму приложений) просто не перемещает сложность в другое место вместо ее устранения? Возможно, но мой опыт говорит о том, что сложность оказывается перемещенной именно туда, где она и должна быть. Более того, с ростом популярности облачных вычислений и рассмотрения серверов как обычных товаров этот подход становится более разумным. IIS и Apache, конечно, мощные веб-серверы, разработанные для того, чтобы выжимать из современного сильнейшего аппаратного обеспечения производительность до последней капли. Это, однако, имеет свою цену: чтобы добиться такой производительности, для их установки и настройки работникам необходима высокая квалификация.
Если говорить о способе написания приложений, то приложения Node больше похожи на приложения PHP или Ruby, чем на приложения .NET или Java. Движок JavaScript, используемый Node (V8, разработанный компанией Google), не только компилирует JavaScript во внутренний машинный код (подобно C или C++), но и делает это прозрачным образом2, так что с точки зрения пользователя код ведет себя как чистый интерпретируемый язык программирования. Отсутствие отдельного шага компиляции уменьшает сложность обслуживания и развертывания: достаточно просто обновить файл JavaScript, и ваши изменения автоматически станут доступны.
Другое захватывающее достоинство приложений Node — невероятная независимость Node от платформы. Это не первая и не единственная платформонезависимая серверная технология, но независимо от платформы важнее предлагаемое разнообразие платформ, чем сам факт ее наличия. Например, вы можете запустить приложение .NET на сервере под управлением Linux с помощью Mono, но это очень нелегкая задача ввиду разнородности документации и системной несовместимости. Аналогично можете выполнять PHP-приложения на сервере под управлением Windows, но их настройка обычно не так проста, как на машине с Linux. В то же время Node элементарно устанавливается на всех основных операционных системах (Windows, OS X и Linux) и облегчает совместную работу. Для команд веб-разработчиков смесь PC и компьютеров Macintosh вполне обычна. Определенные платформы, такие как .NET, задают непростые задачи разработчикам и дизайнерам клиентской части приложений, часто использующим компьютеры Macintosh, что серьезно сказывается на совместной работе и производительности труда. Сама идея возможности подключения работающего сервера на любой операционной системе за считаные минуты (или даже секунды!) — мечта, ставшая реальностью.
Экосистема Node
В сердцевине стека, конечно, находится Node. Это программное обеспечение, которое позволяет выполнять JavaScript-код на сервере без участия браузера, что, в свою очередь, позволяет использовать фреймворки, написанные на JavaScript, такие как Express. Другим важным компонентом является база данных, которая более подробно будет описана в главе 13. Все веб-приложения, кроме самых простых, потребуют базы данных, и существуют базы данных, которые лучше других подходят экосистеме Node.
Ничего удивительного, что имеются интерфейсы для всех ведущих реляционных баз данных (MySQL, MariaDB, PostgreSQL, Oracle, SQL Server): было бы глупо пренебрегать этими признанными китами. Однако наступление эпохи разработки под Node дало толчок новому подходу к базам данных — появлению так называемых NoSQL-баз данных. Не всегда полезно давать чему-либо определение через то, чем оно не является, так что я добавлю, что эти NoSQL-базы данных корректнее было бы называть документоориентированными базами данных или базами данных типа «ключ — значение». Они реализуют более простой с понятийной точки зрения подход к хранению данных. Таких баз данных множество, но MongoDB — одна из лидеров, и именно ее мы будем использовать в книге.
Поскольку создание работоспособного сайта зависит сразу от нескольких технологических составляющих, были придуманы акронимы для описания стека, на котором основан сайт. Например, сочетание Linux, Apache, MySQL и PHP именуется стеком LAMP. Валерий Карпов, программист из MongoDB, изобрел акроним MEAN: Mongo, Express, Angular и Node. Действительно легко запоминающийся, он имеет и свои ограничения: существует столько разных вариантов выбора баз данных и инфраструктуры разработки приложений, что MEAN не охватывает всего разнообразия экосистемы (а также оставляет за скобками то, что я считаю важным компонентом, — механизм рендеринга).
Придумывание включающего в себя все это акронима — интересная задача. Обязательный компонент, конечно, Node. Хотя есть и другие серверные JavaScript-контейнеры, Node становится преобладающим. Express тоже не единственный доступный фреймворк веб-приложений, хотя он и приближается к Node по распространенности. Два других компонента, обычно существенных для разработки веб-приложений, — сервер баз данных и механизм рендеринга (это либо шаблонизатор наподобие Handlebars, либо фреймворк одностраничных приложений типа React). Для двух последних компонентов очевидных лидеров нет, так что здесь, я полагаю, было бы неверно налагать какие-то ограничения.
Все эти технологии объединяет JavaScript, поэтому, чтобы включить все, я буду называть это стеком JavaScript. В данной книге это означает Node, Express и MongoDB (кроме того, в главе 13 приведен пример реляционной базы данных).
Лицензирование
При разработке веб-приложений Node вы можете обнаружить, что уделяете лицензированию больше внимания, чем когда-либо раньше (я определенно уделяю). Одно из преимуществ экосистемы Node — огромный набор доступных пакетов. Однако у каждого из этих пакетов свои правила лицензирования, хуже того, каждый пакет может зависеть от других пакетов, а значит, условия лицензирования различных частей написанного вами приложения могут оказаться запутанными.
Однако есть и хорошие новости. Одна из наиболее популярных лицензий для пакетов Node — лицензия MIT исключительно либеральна и позволяет вам делать практически все, что хотите, включая использование пакета в программном обеспечении с закрытым исходным кодом. Но не следует просто предполагать, что каждый используемый вами пакет лицензирован MIT.
В npm доступны несколько пакетов, которые могут попробовать выяснить лицензии для каждой зависимости в вашем проекте. Поищите в npm nlf или license-report.
Хотя MIT — самая распространенная лицензия, вы можете также увидеть следующие лицензии.
•Стандартная общественная лицензия GNU (GNU General Public License, GPL). GPL — распространенная лицензия для программного обеспечения с открытым исходным кодом, искусно разработанная для того, чтобы сохранить свободу программного обеспечения. Это значит, что, если вы используете лицензированный по GPL код в своем проекте, проект тоже обязан быть GPL-лицензированным. Естественно, это означает, что проект не может иметь закрытый исходный код.
• Apache 2.0. Эта лицензия, подобно MIT, позволяет использовать другую лицензию для проекта, в том числе лицензию с закрытым исходным кодом. Вы обязаны, однако, включить уведомление о компонентах, использующих лицензию Apache 2.0.
• Лицензия Университета Беркли для ПО (Berkeley Software Distribution, BSD). Подобно Apache, эта лицензия позволяет использовать для проекта какую угодно лицензию при условии включения уведомления об использующих лицензию BSD компонентах.
Программное обеспечение иногда бывает с двойным лицензированием (лицензировано под двумя различными лицензиями). Часто это происходит из-за желания разрешить использование программного обеспечения как в проектах GPL, так и в проектах с более либеральным лицензированием (чтобы можно было использовать компонент в GPL-лицензированном программном обеспечении, этот компонент сам должен быть GPL-лицензированным). Схема лицензирования, которую я часто использую в своих проектах, — двойное лицензирование GPL и MIT.
Наконец, если вы сами будете писать пакеты, вам следует подобрать лицензию для программного обеспечения и правильно ее задокументировать. Нет ничего более неприятного для разработчика, чем необходимость при использовании чужого пакета копаться в исходном коде, чтобы выяснить, каково лицензирование, или, что еще хуже, обнаружить, что он вообще не лицензирован.
Резюме
Надеюсь, что эта глава дала вам представление об Express и его месте в обширной экосистеме Node и JavaScript, а также внесла некоторую ясность во взаимосвязь между веб-приложениями на стороне сервера и на стороне клиента.
Не стоит беспокоиться, если вы все еще не уверены в том, что понимаете суть Express. Порой для того, чтобы понять что-то, стоит начать это использовать. Эта книга поможет вам начать создавать веб-приложения с Express, но сначала мы рассмотрим Node, ведь это важные базовые сведения, необходимые для понимания работы Express.
2 Это часто называется компиляцией на лету или JIT-компиляцией (от англ. just in time — «точно в срок»).
Это часто называется компиляцией на лету или JIT-компиляцией (от англ. just in time — «точно в срок»).
Если говорить о способе написания приложений, то приложения Node больше похожи на приложения PHP или Ruby, чем на приложения .NET или Java. Движок JavaScript, используемый Node (V8, разработанный компанией Google), не только компилирует JavaScript во внутренний машинный код (подобно C или C++), но и делает это прозрачным образом2, так что с точки зрения пользователя код ведет себя как чистый интерпретируемый язык программирования. Отсутствие отдельного шага компиляции уменьшает сложность обслуживания и развертывания: достаточно просто обновить файл JavaScript, и ваши изменения автоматически станут доступны.
2. Первые шаги с Node
Если у вас нет опыта работы с Node, эта глава для вас. Понимание Express и его полезности требует хотя бы минимальных знаний о Node. Если у вас есть опыт создания веб-приложений с помощью Node, спокойно пропускайте эту главу. В ней мы будем создавать веб-сервер с минимальной функциональностью, используя Node. В следующей главе мы увидим, как сделать то же самое с помощью Express.
Установка Node
Установить Node в вашу операционную систему проще простого. Команда разработчиков постаралась сделать так, чтобы процесс установки был максимально прост и ясен на всех основных платформах.
Зайдите на домашнюю страницу Node (http://nodejs.org/) и нажмите большую зеленую кнопку, на которой указан номер версии с пометкой «LTS (рекомендована для большинства пользователей)». Сокращение LTS расшифровывается как Long-Term Support, или «долгосрочная поддержка». Эта версия более стабильна, чем текущая, отмеченная как Current. Она имеет новый функционал и улучшенную производительность.
После выбора Windows или macOS загрузится инсталлятор, который проведет вас по процедуре установки. Если вы предпочитаете Linux, то быстрее будет, вероятно, использовать систему управления пакетами (http://bit.ly/36UYMxI).
Если вы пользователь Linux и хотите работать с системой управления пакетами, убедитесь, что следуете указаниям с вышеупомянутой веб-страницы. Многие дистрибутивы Linux могут установить очень старую версию Node, если вы не добавите соответствующий репозиторий пакетов.
Можно также скачать автономную программу установки (https://nodejs.org/en/download). Она будет полезна, если вы используете Node для работы в организации.
Использование терминала
Я убежденный поклонник терминала (он же — консоль, или командная строка), и не перестаю восхищаться его мощи и производительности. Все примеры в этой книге предполагают его использование. Если вы не очень дружите с терминалом, настоятельно рекомендую потратить некоторое время на ознакомление с предпочтительным для вас вариантом. У многих утилит, упомянутых в этой книге, есть графический интерфейс, поэтому, если вы категорически против использования терминала, у вас есть выбор, но вам придется разбираться с этим самостоятельно.
Если вы работаете на macOS или Linux, можете выбрать одну из нескольких хорошо зарекомендовавших себя командных оболочек (интерпретаторов командной строки). Наиболее популярная — bash, хотя и у zsh есть свои сторонники. Главная причина, по которой я тяготею к bash (помимо длительного знакомства с ней), — повсеместная распространенность. Сядьте перед любым компьютером, использующим Unix, и в 99 % случаев командной оболочкой по умолчанию будет bash.
Если вы пользователь Windows, дела обстоят не так радужно. Компания Microsoft никогда не была заинтересована в удобстве работы пользователей с терминалом, так что вам придется немного потрудиться. Git любезно включает командную оболочку Git bash, предоставляющую возможности Unix-подобного терминала (в ней есть только небольшое подмножество обычно доступных в Unix утилит командной строки, однако оно весьма полезно). Хотя Git bash предоставляет вам минимальную командную оболочку bash, этот терминал все равно использует встроенную консоль Windows, что приводит лишь к расстройству (даже простые функции вроде изменения размеров окна консоли, выделения текста, вырезания и вставки интуитивно не понятны и выполняются неуклюже). Поэтому я рекомендую установить более продвинутый терминал, такой как ConsoleZ (https://github.com/cbucher/console) или ConEmu (https://conemu.github.io/). Для опытных пользователей Windows, особенно разработчиков .NET, а также для системных или сетевых администраторов есть другой вариант: PowerShell от Microsoft. PowerShell вполне оправдывает свое название3: с ее помощью можно делать потрясающие вещи. Опытный пользователь PowerShell может посоревноваться с гуру командной строки Unix. Но, если вы переходите с macOS/Linux на Windows, я все равно рекомендую использовать Git bash из соображений совместимости.
Если у вас Windows 10 или более поздней версии, вы можете установить Ubuntu Linux прямо на Windows! Это не многовариантная загрузка или виртуализация, а отличная работа по интеграции Linux в Windows, проведенная по поручению команды Microsoft по разработке программного обеспечения с открытым исходным кодом. Вы можете установить Ubuntu на Windows через Microsoft App Store (http://bit.ly/2KcSfEI).
Последним вариантом для пользователей Windows является виртуализация. При мощности и архитектуре современных компьютеров производительность виртуальных машин (ВМ) практически не отличается от производительности реальных. Мне когда-то очень повезло с бесплатным VirtualBox от Oracle.
Наконец, независимо от того, в какой операционной системе вы работаете, существуют такие замечательные среды разработки приложений в облаке, как Cloud9 (теперь выпускается AWS) (https://aws.amazon.com/cloud9/). Cloud9 ускорит развертывание новой среды разработки Node, и начать быстро работать с Node будет чрезвычайно просто.
Как только вы выбрали командную оболочку, которая вас устраивает, рекомендую потратить немного времени на изучение основ. Так вы сбережете нервы. В Интернете можно найти немало замечательных руководств (https://guide.bash.academy/). Как минимум вам нужно знать, как передвигаться по каталогам, копировать, перемещать и удалять файлы, а также выходить из программы командной строки (обычно нажатием сочетания клавиш Ctrl+C). Если вы хотите стать ниндзя командной строки, я предлагаю выучить, как осуществлять поиск текста в файлах, поиск файлов и каталогов, объединять команды в последовательность (старая философия Unix) и перенаправлять вывод.
Во многих Unix-подобных системах сочетание клавиш Ctrl+S имеет специальное назначение: его нажатие «замораживает» терминал (когда-то этот прием использовался, чтобы быстро остановить прокрутку страницы). Поскольку это весьма распространенная комбинация клавиш для сохранения (Save), ее легко нажать случайно, что приводит к ситуации, сбивающей с толку большинство людей (со мной это случалось гораздо чаще, чем хотелось бы). Чтобы «разморозить» терминал, просто нажмите Ctrl+Q. Таким образом, если вы когда-нибудь окажетесь сбитыми с толку внезапно замершим терминалом, попробуйте нажать сочетание Ctrl+Q и посмотрите, поможет ли это.
Редакторы
Немногие темы вызывают столь ожесточенные споры среди программистов, как выбор текстового редактора, и на то есть причины. Текстовый редактор — это ваш основной рабочий инструмент. Я предпочитаю редактор vi4 (или редактор, у которого есть режим vi). vi — редактор не для всех (мои сотрудники обычно смотрят на меня большими глазами, когда я рассказываю им, как удобно было бы сделать в vi то, что они делают), но если вы найдете мощный редактор и научитесь им пользоваться, ваши производительность и, осмелюсь утверждать, удовольствие от работы значительно возрастут. Одна из причин, по которым я особенно люблю vi (хотя вряд ли самая главная), — то, что, как и bash, он есть везде. Если у вас есть доступ к Unix — у вас есть vi. У большинства популярных текстовых редакторов есть режим vi, который позволяет использовать команды клавиатуры vi. Как только вы к нему привыкнете, вам будет трудно представить себя использующим что-либо другое. vi непрост в освоении, но результат себя оправдывает.
Если, как и я, вы видите смысл в знакомстве с повсеместно доступным редактором, для вас есть еще один вариант — Emacs. Я почти не имел с ним дела (обычно вы или сторонник Emacs, или сторонник vi), но безоговорочно признаю его мощь и гибкость. Рекомендую обратить внимание на Emacs, если модальный подход к редактированию vi не для вас.
Хотя знание консольного текстового редактора, такого как vi или Emacs, может быть полезным, вы, вероятно, захотите использовать более современный редактор. Популярностью пользуется Visual Studio Code (https://code.visualstudio.com/) (не стоит путать его с Visual Studio без Code). Я рекомендую его, ведь это хорошо спроектированный, быстрый и эффективный текстовый редактор, подходящий для разработки в Node и на JavaScript. Другой часто используемый редактор — Atom (https://atom.io/). Он также популярен в сообществе JavaScript. Оба этих редактора бесплатны и поддерживаются Windows, macOS и Linux (и в них обоих есть режим vi!).
Теперь, когда у нас есть хорошее средство для редактирования кода, давайте переключим внимание на npm. С его помощью можно получать пакеты, написанные другими разработчиками, что позволит воспользоваться преимуществом большого и активного сообщества JavaScript.
npm
npm — повсеместно распространенная система управления пакетами для Node (именно таким образом мы получим и установим Express). В отличие от PHP, GNU, WINE и других, образованных странным способом сокращений, npm — не акроним (именно поэтому пишется строчными буквами). Это скорее рекурсивная аббревиатура для «npm — не акроним».
В целом двумя основными задачами системы управления пакетами являются установка пакетов и управление зависимостями. npm — быстрая и эффективная система управления пакетами, которой, как мне кажется, экосистема Node обязана своим быстрым ростом и разнообразием.
У npm есть успешный конкурент, использующий ту же базу данных, — менеджер пакетов Yarn. Мы будем применять его в главе 16.
npm устанавливается при инсталляции Node, так что, если вы следовали перечисленным ранее шагам, она у вас уже есть. Так приступим же к работе!
Основная команда, которую вы будете использовать с npm (что неудивительно), — install. Например, чтобы установить nodemon (популярную утилиту для автоматической перезагрузки программы Node после внесения изменений в исходный код), можно выполнить следующую команду в консоли:
npm install -g nodemon
Флаг -g сообщает npm о необходимости глобальной установки пакета, означающей его доступность по всей системе. Это различие будет понятнее, когда мы рассмотрим файлы package.json. Пока же примем за эмпирическое правило, что утилиты JavaScript, такие как nodemon, обычно будут устанавливаться глобально, а специфические для вашего веб-приложения пакеты — нет.
В отличие от таких языков, как Python, который претерпел коренные изменения между версиями 2.0 и 3.0, что потребовало наличия возможности удобного переключения между различными средами, платформа Node достаточно нова, так что, вероятно, вам следует всегда использовать последнюю версию Node. Но если потребуется поддержка нескольких версий Node, загрузите nvm (https://github.com/creationix/nvm) или n (https://github.com/tj/n), который позволит переключаться между средами. Вы можете узнать, какая версия Node установлена на вашем компьютере, набрав node --version.
Простой веб-сервер с помощью Node
Если вы когда-либо создавали статический сайт или работали с PHP или ASP, вероятно, вам привычна идея веб-сервера (например, Apache), выдающего статические файлы таким образом, что браузер может видеть их по сети. Например, если вы создаете файл about.html и помещаете его в соответствующий каталог, то можете затем перейти по адресу http://localhost/about.html. В зависимости от настроек веб-сервера вы можете даже опустить .html, но связь между URL и именем файла очевидна: веб-сервер просто знает, где на компьютере находится файл, и выдает его браузеру.
localhost в полном соответствии со своим названием относится к компьютеру, за которым вы работаете. Это распространенный псевдоним для кольцевых адресов 127.0.0.1 (IPv4) и ::1 (IPv6). Часто вместо него применяют 127.0.0.1, но в этой книге я буду использовать localhost. Если вы работаете на удаленном компьютере (с помощью SSH, например), помните, что переход по адресу localhost не соединит вас с ним.
Node предлагает парадигму, отличную от той, что имеет обычный веб-сервер: создаваемое вами приложение и является веб-сервером. Node просто обеспечивает вас фреймворком для создания веб-сервера.
Возможно, вы скажете: «Но я же не хочу писать веб-сервер!» Это вполне естественная реакция: вы хотите писать приложение. Однако Node превращает написание этого веб-сервера в простейшее действо (иногда всего несколько строк), и контроль над вашим приложением, который вы получаете взамен, более чем стоит того.
Вы уже установили Node, освоились с терминалом и теперь самое время приступить к делу.
Hello World!
Я всегда сожалел, что каноническим вводным примером программирования является вывод на экран скучной фразы «Hello World!». Тем не менее будет святотатством бросить вызов столь могучей традиции, так что начнем с этого примера, а после перейдем к чему-то более интересному.
В своем любимом редакторе создайте файл под названием helloworld.js (ch02/00-helloworld.js в прилагаемом к книге репозитории):
const port = process.env.PORT || 3000
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Hello world!')
})
server.listen(port, () => console.log(`сервер запущен на порте ${port}; ` +
'нажмите Ctrl+C для завершения...'))
В зависимости от того, где и когда вы изучали JavaScript, вас может смутить тот факт, что в данном примере нет точек с запятой. Раньше я был ярым сторонником этого знака препинания и скрепя сердце, перестал его использовать после того, как стал больше разрабатывать в React, где точку с запятой принято опускать. Спустя некоторое время пелена спала с моих глаз и я стал недоумевать, почему вообще точка с запятой вызывала у меня такой энтузиазм! Как покажут примеры в этой книге, я не отношусь к числу решительных противников точки с запятой. Это личный выбор каждого, и вы вольны использовать этот знак препинания, если вам так нравится.
Убедитесь, что вы находитесь в той же папке, что и helloworld.js, и наберите nodehelloworld.js. Затем откройте браузер, перейдите на http://localhost:3000, и — вуаля! — ваш первый веб-сервер. Конкретно этот веб-сервер не выдает HTML-код, скорее он просто показывает сообщение Hello world! в вашем браузере в виде неформатированного текста. Если хотите, можете поэкспериментировать с отправкой HTML вместо этого: просто поменяйте text/plain на text/html и замените 'Helloworld!' строкой, содержащей корректный HTML-код. Я не буду этого делать, поскольку стараюсь избегать написания HTML-кода внутри JavaScript (причины детально описаны в главе 7).
Событийно-ориентированное программирование
Базовым принципом Node является событийно-ориентированное программирование. Для вас как программиста это означает необходимость понимать, какие события вам доступны и как на них реагировать. Многие люди знакомятся с событийно-ориентированным программированием в процессе реализации пользовательского интерфейса: пользователь что-то нажимает — и вы обрабатываете событие клика. Это хороший способ, но очевидно, что программист не контролирует момент, когда пользователь что-то нажимает или собирается нажать, поэтому событийно-ориентированное программирование должно быть интуитивно понятным. Мысленный переход к реагированию на события на сервере может оказаться чуть более сложным, но и здесь принцип прежний.
В предыдущем примере кода событие неявное: обрабатываемое событие — HTTP-запрос. Метод http.createServer принимает функцию в качестве аргумента, она будет вызываться каждый раз при выполнении HTTP-запроса. Наша простая программа просто устанавливает в качестве типа содержимого неформатированный текст и отправляет строку Helloworld!.
Как только вы начнете думать, опираясь на термины событийно-ориентированного программирования, вы будете видеть события повсюду. Одним из таких событий является переход пользователя с одной страницы или области приложения на другую. То, как приложение отвечает на этот переход, называется маршрутизацией.
Маршрутизация
Маршрутизация относится к механизму выдачи клиенту контента, который он запрашивал. Для клиент-серверных веб-приложений клиент определяет желаемый контент в URL, а именно путь и строку запроса (составные части URL будут подробнее рассмотрены в главе 6).
По сложившейся традиции серверная маршрутизация напрямую зависит от пути и строки запроса, хотя доступна и другая информация: заголовки, домен, IP-адрес и т.д. Благодаря этому сервер может учитывать, например, приблизительное физическое местоположение пользователя или предпочитаемый им язык.
Расширим наш пример с «Hello world!» так, чтобы происходило что-то более интересное. Создадим минимальный сайт, состоящий из домашней страницы, страниц О нас и Не найдено. Пока будем придерживаться предыдущего примера и просто начнем выдавать неформатированный текст вместо HTML-кода (ch02/01-helloworld.js в прилагаемом к книге репозитории):
const port = process.env.PORT || 3000
const server = http.createServer((req,res) => {
// Приводим URL к единому виду, удаляя
// строку запроса, необязательную косую черту
// в конце строки и переводя в нижний регистр.
const path = req.url.replace(/\/?(?:\?.*)?$/, '').toLowerCase()
switch(path) {
case '':
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('Homepage')
break
case '/about':
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end('About')
break
default:
res.writeHead(404, { 'Content-Type': 'text/plain' })
res.end('Not Found')
break
}
})
server.listen(port, () => console.log(`сервер запущен на порте ${port}; ` +
'нажмите Ctrl+C для завершения...'))
Если вы запустите это, то обнаружите, что можете переходить на домашнюю страницу (http://localhost:3000) и страницу О нас (http://localhost:3000/about). Любые строки запроса будут проигнорированы, так что http://localhost:3000/?foo=bar вернет вас на домашнюю страницу, а любой другой URL — на страницу Не найдено.
Раздача статических ресурсов
Теперь, когда заработала простейшая маршрутизация, раздадим какой-нибудь реальный HTML-код и логотип. Они носят название статических ресурсов, поскольку обычно не изменяются (в отличие, например, от тикера5: каждый раз, когда вы перезагружаете страницу, биржевые котировки меняются).
Раздача статических ресурсов с помощью Node подходит для нужд разработки и небольших проектов. В проектах побольше вы, вероятно, захотите использовать для этих целей прокси-сервер, такой как Nginx или CDN. Смотрите главу 17 для получения более подробной информации.
Если вы работали с Apache или IIS, то, вероятно, просто создавали HTML-файл, переходили к нему и автоматически открывали в браузере. Node работает иначе: нам придется выполнить работу по открытию файла, его чтению и отправке его содержимого браузеру. Так что создадим в нашем проекте каталог public (в следующей главе станет понятно, почему мы не называем его static). В нем создадим home.html, about.html, 404.html, подкаталог с названием img и изображение с именем img/logo.jpg. Выполните эти шаги самостоятельно: раз вы читаете эту книгу, то, вероятно, знаете, как создать HTML-файл и найти картинку. В ваших HTML-файлах ссылайтесь на логотип следующим образом: <imgsrc="/img/logo.jpg"alt="logo">.
Теперь внесем изменения в файл helloworld.js (ch02/02-helloworld.js в репозитории, прилагаемом к книге):
const fs = require('fs')
const port = process.env.PORT || 3000
function serveStaticFile(res, path, contentType, responseCode = 200) {
fs.readFile(__dirname + path, (err, data) => {
if(err) {
res.writeHead(500, { 'Content-type': 'text/plain' })
return res.end('500 — Внутренняя ошибка')
}
res.writeHead(responseCode, { 'Content-type': contentType })
res.end(data)
})
}
const server = http.createServer((req,res) => {
// Приводим URL к единому виду, удаляя
// строку запроса, необязательную косую черту
// в конце строки и переводя в нижний регистр.
const path = req.url.replace(/\/?(?:\?.*)?$/, '').toLowerCase()
switch(path) {
case '':
serveStaticFile(res, '/public/home.html', 'text/html')
break
case '/about':
serveStaticFile(res, '/public/about.html', 'text/html')
break
case '/img/logo.png':
serveStaticFile(res, '/public/img/logo.png', 'image/png')
break
default:
serveStaticFile(res, '/public/404.html', 'text/html', 404)
break
}
})
server.listen(port, () => console.log(`сервер запущен на порте ${port}; ` +
'нажмите Ctrl+C для завершения...'))
В этом примере мы проявили не слишком много изобретательности в вопросе маршрутизации. Если перейдете по адресу http://localhost:3000/about, получите файл public/about.html. Путь и файл можно поменять на любые, какие только пожелаете. Например, если у вас есть отдельная страница О нас на каждый день недели, у вас могут быть файлы public/about_mon.html, public/about_tue.html и т.д., а логика маршрутизации может быть построена так, чтобы выдавать соответствующую страницу при переходе пользователя по адресу http://localhost:3000/about.
Обратите внимание, что мы создали функцию-хелпер, serveStaticFile, выполняющую большой объем работы. fs.readFile — асинхронный метод для чтения файлов. Существует синхронная версия этой функции — fs.readFileSync, но чем быстрее вы начнете мыслить асинхронно, тем лучше. В функции fs.readFile используется шаблон под названием «обратный вызов» (callbacks). Вы предоставляете функцию обратного вызова (callback function), и после того, как работа выполнена, происходит вызов этой функции (так сказать, она «вызывается обратно»). В этом случае fs.readFile читает содержимое указанного файла и выполняет функцию обратного вызова по завершении чтения файла. Если файла не существует или были проблемы с правами доступа при чтении файла, устанавливается значение переменной err и функция возвращает код состояния HTTP500, указывающий на ошибку сервера. Если файл был прочитан успешно, он отправляется клиенту с заданным кодом ответа и типом содержимого. Коды ответа подробнее рассмотрены в главе 6.
Запись __dirname будет соответствовать каталогу, в котором находится выполняемый скрипт. Если ваш скрипт размещен в /home/sites/app.js, __dirname будет соответствовать /home/sites. Использовать такую удобную глобальную переменную везде, где возможно, — хорошая идея. Если этого не сделать, можно получить трудно диагностируемые ошибки при запуске приложения из другого каталога.
Вперед к Express
Вероятно, Node еще сильнее вас впечатлил. Мы, по сути, повторили то, что Apache или IIS делают автоматически, однако теперь вы понимаете, как работает Node и насколько вы можете им управлять. Мы пока не сделали ничего впечатляющего, но вы могли увидеть, как все это можно использовать в качестве отправного пункта для реализации более сложных вещей. Если продолжать движение по данному пути, создавая более сложные приложения Node, можно прийти к чему-то очень похожему на Express.
К счастью, нам не нужно этого делать: Express уже существует и спасает вас от реализации огромного количества трудоемкой инфраструктуры. Так что теперь, когда у нас за плечами есть небольшой опыт работы с Node, мы готовы перейти к изучению Express.
3 От англ. power shell — «производительная командная оболочка». — Примеч. пер.
4 В настоящее время vi фактически является синонимом vim (vi improved, усовершенствованный vi). В большинстве систем vi прячется под псевдонимом vim, однако я предпочитаю набирать vim для уверенности, что использую именно его.
5 Биржевой инструмент, передающий котировки ценных бумаг. — Примеч. пер.
Если вы пользователь Windows, дела обстоят не так радужно. Компания Microsoft никогда не была заинтересована в удобстве работы пользователей с терминалом, так что вам придется немного потрудиться. Git любезно включает командную оболочку Git bash, предоставляющую возможности Unix-подобного терминала (в ней есть только небольшое подмножество обычно доступных в Unix утилит командной строки, однако оно весьма полезно). Хотя Git bash предоставляет вам минимальную командную оболочку bash, этот терминал все равно использует встроенную консоль Windows, что приводит лишь к расстройству (даже простые функции вроде изменения размеров окна консоли, выделения текста, вырезания и вставки интуитивно не понятны и выполняются неуклюже). Поэтому я рекомендую установить более продвинутый терминал, такой как ConsoleZ (https://github.com/cbucher/console) или ConEmu (https://conemu.github.io/). Для опытных пользователей Windows, особенно разработчиков .NET, а также для системных или сетевых администраторов есть другой вариант: PowerShell от Microsoft. PowerShell вполне оправдывает свое название3: с ее помощью можно делать потрясающие вещи. Опытный пользователь PowerShell может посоревноваться с гуру командной строки Unix. Но, если вы переходите с macOS/Linux на Windows, я все равно рекомендую использовать Git bash из соображений совместимости.
Теперь, когда заработала простейшая маршрутизация, раздадим какой-нибудь реальный HTML-код и логотип. Они носят название статических ресурсов, поскольку обычно не изменяются (в отличие, например, от тикера5: каждый раз, когда вы перезагружаете страницу, биржевые котировки меняются).
В настоящее время vi фактически является синонимом vim (vi improved, усовершенствованный vi). В большинстве систем vi прячется под псевдонимом vim, однако я предпочитаю набирать vim для уверенности, что использую именно его.
Биржевой инструмент, передающий котировки ценных бумаг. — Примеч. пер.
От англ. power shell — «производительная командная оболочка». — Примеч. пер.
Немногие темы вызывают столь ожесточенные споры среди программистов, как выбор текстового редактора, и на то есть причины. Текстовый редактор — это ваш основной рабочий инструмент. Я предпочитаю редактор vi4 (или редактор, у которого есть режим vi). vi — редактор не для всех (мои сотрудники обычно смотрят на меня большими глазами, когда я рассказываю им, как удобно было бы сделать в vi то, что они делают), но если вы найдете мощный редактор и научитесь им пользоваться, ваши производительность и, осмелюсь утверждать, удовольствие от работы значительно возрастут. Одна из причин, по которым я особенно люблю vi (хотя вряд ли самая главная), — то, что, как и bash, он есть везде. Если у вас есть доступ к Unix — у вас есть vi. У большинства популярных текстовых редакторов есть режим vi, который позволяет использовать команды клавиатуры vi. Как только вы к нему привыкнете, вам будет трудно представить себя использующим что-либо другое. vi непрост в освоении, но результат себя оправдывает.
3. Экономия времени благодаря Express
В главе 2 вы узнали, как создать простой веб-сервер с помощью лишь одного Node. В этой главе мы воссоздадим этот же сервер с помощью Express, что станет отправной точкой для работы с книгой и познакомит с основами Express.
Скаффолдинг
Скаффолдинг6 — идея не новая, но многие люди, включая меня самого, впервые познакомились с этой концепцией благодаря Ruby. Идея проста: большинству проектов требуется определенное количество так называемого шаблонного, или стандартного, кода, а кому хочется заново писать этот код при создании каждого нового проекта? Простой способ решения проблемы — создать черновой каркас проекта и всякий раз, когда необходимо, просто копировать этот каркас, иначе говоря, шаблон.
Ruby on Rails развивает эту концепцию, обеспечивая программу, автоматически генерирующую скаффолдинг. Преимущество данного подхода в том, что этим способом можно сгенерировать более совершенный фреймворк, чем тот, что получается при обычном выборе из набора шаблонов.
Express следует примеру Ruby on Rails и предоставляет вспомогательную программу для генерации начального скаффолдинга для вашего проекта Express.
Хотя утилита скаффолдинга Express полезна, на мой взгляд, настройку Express стоит изучить с нуля. Вы не только лучше его узнаете, но и получите больше контроля над структурой вашего проекта и над тем, что будет установлено. К тому же утилита скаффолдинга Express приспособлена под генерацию HTML на стороне сервера и менее значима для API и одностраничных приложений.
Хотя мы и не будем использовать утилиту скаффолдинга, рекомендую обратить на нее внимание, прочитав данную книгу: к тому времени вы будете вооружены всеми знаниями, необходимыми для оценки того, подходит ли вам генерируемый ею скаффолдинг. За более подробной информацией обращайтесь к документации по генератору приложе
