Обратите внимание, что Koa 2 наделала много шума в пространстве NodeJS. В статье есть ссылки на подробные сведения о промисах, генераторах и подходах async/await.

В качестве отказа от ответственности я хотел бы упомянуть, что за последние 5–6 лет я запускал множество производственных приложений для платформ электронной коммерции на основе Rails, с автоматизацией от Chef, Ansible до AWS OpsWorks (и это лишь некоторые из них); Я работал над решениями для Raden.com, Autoglym.com и многими другими.

Большая часть этих систем полагалась на Spree (теперь Solidus) для аспекта электронной коммерции, с индивидуальной адаптацией процесса оформления заказа и процессов интеграции платежей (обычно через ActiveMerchant) и интеграцией API с выбранными клиентами ERP — от Microsoft Dynamics NAV до SAP и т. д. .

Почти 6 месяцев назад ко мне обратился стартап, чтобы помочь с их обязательством помочь с их MVP — и, как и у большинства стартапов, в этой кодовой базе было написано «CHURN». Пресловутая телега действительно была впереди лошади тогда, и остается такой же даже сегодня.

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

Поскольку местные таланты состоят из гораздо большего числа разработчиков «Javascript» — тех, кто немного знает PHP и использует jQuery в качестве опоры (или смешивает ванильный JS и jQuery ad-hoc!) — проект продолжается в NodeJS.

Это краткий обзор некоторых из самых больших препятствий, которые возникли.

1. NPM: Пакет «шведский стол» — бесплатно для всех.

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

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

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

Тем не менее, новичкам рекомендуется разобраться с самыми популярными зависимостями, такими как PassportJS, который оказался превосходным.

NPM также приводит к раздуванию зависимостей, когда авторы библиотек склонны опираться даже на 10–20-строчные «библиотеки» только потому, что удобнее (правда?) добавить в свою библиотеку пакет из 10–20 строк, а не включать тот же самый пакет. код как функция полезности.

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

2. NodeJS/Express: голые кости и собственная безопасность.

Это будет самой большой проблемой, особенно когда NodeJS размахивают теми, у кого мало опыта.

Кодовая база, о которой я упоминал ранее, начиналась без каких-либо включенных пакетов безопасности, и хотя я добавил lusca в качестве зависимости, по независящим от меня причинам это приложение работает в рабочей среде без какой-либо защиты CSRF или CORS ( пропуская и другие уровни базовой безопасности).

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

Я начал ценить уровень безопасности, предлагаемый Rails из коробки, и это напомнило мне об отличном выступлении Иегуды Каца Почему Rails это сложно, где он объясняет, что существует уровень неизвестных угроз безопасности, которые постоянно исправляются и обрабатываются в Rails (и поддерживаются!) сообществом — это имеет огромную ценность для тех, кто использует Rails, поскольку это означает, что тем, кто внедряет решения Rails, не обязательно тратить столько времени на погружение в пространство безопасности для защиты своих приложений (хотя я настоятельно рекомендую вам сделать это, если у вас есть время).

3. Антипаттерны Callback Hell

Это забавно, и чтобы обойти это, наша кодовая база представляет собой загроможденную смесь вызовов на основе query('SELECT * FROM ...', function(err, rows) { ... }) старой школы.

Я позаботился о том, чтобы использовать Promises на ранней стадии, используя Bluebird, так как это единственная спасительная мера, пока Node 7 не будет принят для async/await. Это довольно хорошо, быстро и делает хорошую работу, чтобы все просто работало.

Есть и другие варианты, такие как co генераторы, а также асинхронный пакет.

Конечно, промисы сами по себе не панацея, особенно когда речь идет об обработке ошибок.

4. Обработка исключений (или ошибок). ЛОЛВУТ?

Удачи с этим. Да серьезно. Вот цитата из Гэвина -

Исходя из других языков, таких как Python, Ruby или PHP, вы ожидаете, что генерация и перехват ошибок или даже возврат ошибки из функции будет простым способом обработки ошибок. Не так с Node. Вместо этого вы можете передавать свои ошибки в своих обратных вызовах (или промисах) — правильно, никаких исключений. Это работает до тех пор, пока вы не сделаете несколько обратных вызовов в глубину и не попытаетесь отследить трассировку стека. Не говоря уже о том, что если вы забудете вернуть свой обратный вызов при ошибке, он продолжит работать и вызовет другой набор ошибок после того, как вы вернули первоначальный. Вам нужно будет удвоить свои клиентские счета, чтобы компенсировать время отладки.

На данный момент я пытался сочетать использование Honeybadger везде, где есть блок try/catch или блок promise.then().catch() для промиса, чтобы обеспечить дополнительный контекст вместе с трассировкой стека. Это все еще борьба, и, черт возьми, я скучаю по исключениям Rails сейчас!

5. Миграции — нужны ли они вам?

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

Вот краткий обзор ценности миграции:

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

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

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

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

Таким образом, наш текущий рабочий процесс восходит к 1980-м (или более ранним) подходам к копированию таблиц и данных из базы данных разработки в рабочую среду — это абсолютно болезненный процесс, и целостность данных… ну, на данный момент ее нет. . Хорошо, что это стартап, верно? #shithappens #двигатьсябыстро

6. Объекты доступа к данным (DAO) и реляционные преобразователи объектов (ORM)

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

Тем не менее, я слышал, что Kraken.js имеет опции для DAO, поэтому, пока я не проверял его тщательно, я бы посоветовал вам сделать это вместе с Knex.js и Sequelize.

Узел в производстве

Подход, который я использовал, заключается в создании стека в AWS, который реализует разгрузку TLS/SSL и запускает экземпляр приложения NodeJS в контейнере Docker, при этом Nginx направляет трафик в контейнер приложения и обслуживает/кеширует статические ресурсы.

Сам экземпляр Node управляется PM2.

Мысли о Node/Express

Хотя у Node есть свои недостатки, как и у всех языков, фреймворков и стеков, есть некоторые замечательные аспекты. Например, нам нужно было сгенерировать несколько PDF-файлов, и PDFkit отлично справился с этой конкретной задачей.

Тем не менее, я бы не рекомендовал его для крупномасштабных продуктов, если только вы не можете —

  • Выделите время для планирования базовой кодовой базы, включая зависимости и т. д.
  • Курировать зависимости, решения безопасности с нуля.
  • Не торопитесь придумывать свое решение.
  • Также используйте методы модульного тестирования и BDD (Selenium/PhantomJS + пользовательские истории).
  • Тестируйте и тестируйте снова (и автоматизируйте все).
  • CI/CD/развертывания с нулевым временем простоя являются обязательными. Ведь это 2017 год.

Хотя у Rails тоже есть свои демоны, я бы подумал о том, чтобы Rails запускал бэкэнд как приложение на основе API, и спроектировал внешний интерфейс с помощью NodeJS, выполняющего вызовы API к бэкенду Rails. Какого черта вам использовать Node.js? предлагает не использовать NodeJS для веб-приложений с реляционным бэкендом.

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

ActiveRecord будет считаться проверенным временем ORM, учитывая его использование в производстве в Basecamp, и потенциально обладает более полным набором функций, чем варианты ORM в NPM-land.