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

Итак, мы представили TypeScript. Этот шаг был легким, и его можно было быстро выполнить с помощью новой задачи Grunt и некоторых изменений в структуре папок.

В Sails.js есть только одна вещь, которая делает TypeScript менее мощным . Он делает все контроллеры, службы и модели доступными для переменной GLOBAL. Это ограничивает возможности TypeScript, поскольку Sails.js всегда ожидает

module.exports = {
   ...
}

быть установленным.

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

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

Класс выглядел так:

Итак, после некоторых попыток и ошибок оказалось, что ключевое слово export будет работать для Sails.js, и мы можем использовать необходимые функции из TypeScript .

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

Это привело меня к идее удаления Sails.js и реализации Express.js в сочетании с подходом, основанным на полном классе, для нашей базы кода.

Это имело еще одно огромное преимущество.

Наконец-то мы смогли сгруппировать файлы в подпапки. Это было невозможно, поскольку Sails.JS просто считывает первый уровень папок, с которыми он работает (службы, контроллеры, модели).

Руководство по миграции

Итак, как мы в итоге переехали?

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

Пользовательские файлы app.js и server.ts (js)

Итак, первым шагом является создание настраиваемого файла входа для приложения.

Сначала мы создали новые файлы app.js и server.ts. server.ts был создан где-то в исходном каталоге и, будучи файлом TypeScript, имеет преимущества проверки компилятором.

Файл app.js в корневой папке просто вызовет скомпилированную версию файла server.ts для запуска приложения.

Файл server.ts будет выглядеть как обычный файл Express.js, за исключением того, что вы должны добавить туда немного дополнительных, чтобы он работал как Sails.js в начале.

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

Есть несколько вещей, которые необходимо сделать:

Глобальный объект Sails.js

Sails.js делает глобально доступным объект, который содержит такие функции, как ведение журнала, объект конфигурации, i18n.

Чтобы запустить код, проще всего было смоделировать такое поведение:

Установите все промежуточное ПО

  • CSRF
  • CORS
  • Местные (переводы)
  • хочетJSON (который имеет то же поведение, что и Sails.js)
  • Шкипер (загрузка файлов)
  • Методы ответа по умолчанию (res.ok () / res.serverError () /…)

Маршрутизация и политики

В Sails.js и маршрутизация, и политики устанавливаются с помощью файлов, а не в самом коде. Это делает миграцию довольно трудоемкой, если вам нужно переписать каждый маршрут и его политики в код для настройки маршрутизатора Express.js.

Если приложение небольшое, это не будет большой проблемой. Однако наше приложение содержит 700 маршрутов REST и эквивалентное количество политик.

В итоге я написал два парсера. Один для настройки маршрута, который будет анализировать routes.js, и другой, для политик, который будет анализировать файл policy.js.

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

Движок шаблонов

Sails.js по умолчанию использует механизм шаблонов EJS.

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

После некоторых экспериментов я обнаружил, что он правильно работает с пакетом express-ejs-layouts.

Это была настройка в файле сервера:

Также нужно было изменить методы рендеринга.

Sails.js реализует поведение, которое на основе контроллера определяет правильный файл шаблона.

Миграция будет происходить из:

to:

А как насчет уровня базы данных?

Sails.js использует собственный письменный коннектор базы данных, Waterline.

Это немного усложнило задачу, поскольку Waterline запускается внутри Sails.js. Теперь, когда Sails.js больше нет, как бы вы запустили запуск? Документация на странице Github не дает много информации о том, как работать с Waterline в вашем собственном проекте.

После некоторой отладки документации я придумал класс, который воспроизводит поведение Sails.js.

Метод запуска будет вызываться во время запуска Express.js.

Я придумал это:

Также я сделал возможным доступ к модели через импорт и функции Waterline (find () / remove () / save () /…).

Теперь модель может выглядеть так:

Socket.IO

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

Чтобы запустить socket.io, мы сначала запускаем экспресс-сервер. Экземпляр, который мы получаем от экспресс-сервера, затем используется для запуска экземпляра socket.io.

Здесь мы используем адаптер Redis для синхронизации нескольких экземпляров нашего приложения.

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

После этого запускается экземпляр Socket.io, и на заключительном этапе к экземпляру Socket.io применяется некоторое промежуточное программное обеспечение.

В мониторе вы можете следить за поступающими событиями.

Как видите, этот метод отличается от подхода к отображению контроллеров в реализации Sails.js Socket.io. Не должно быть слишком сложно адаптироваться к подходу прослушивания событий Socket.io.

Последние слова

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

Следующим шагом на будущее будет миграция от Ватерлинии к Мангусту.

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