Проблема

В нашей компании мы строим проект на основе микросервисной архитектуры. Классическая проблема, с которой вы столкнулись во время разработки: вы хотели бы избежать некоторых проблем, прежде чем отправлять изменения в удаленный репозиторий git. Эти проблемы в основном связаны с ошибками lint и тестов. Если вы измените что-то в одном сервисе и захотите отправить свои изменения в удаленную ветку, все скрипты линтеров и тестов для всех сервисов запустятся. Эта проблема вызвана установкой хаски в каждом сервисе. В документации Husky сказано: «используйте lerna».

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

Весь код (мы используем его в нашем проекте, но некоторая конфиденциальная информация скрыта) и приведенный ниже текст основаны на моем опыте включения lerna в наш проект.

Настройка лерны

  1. Запустите скрипт lerna init. Он создает новый репозиторий lerna с:

а) lerna.json

  • npm используется по умолчанию, но вместо него вы можете использовать клиент пряжи.
  • содержит все пакеты (я буду называть их службами), которыми должна управлять lerna.
  • вы можете выбрать между заблокированным/независимым режимом.
{
"npmClient": "npm",
"packages": ["frontend-service","identity-service","neo4j-  service","project-service","reference-model-service"],
"version": "independent"
}

б) папка с пакетами

Вы можете поместить все свои сервисы в эту папку или выбрать, какой из них будет управляться lerna, как в моем примере. Некоторыми сервисами lerna мы не управляем или не можем управлять по разным причинам (например: это не сервисы node.js). Если у вас есть все службы в папке пакетов и вы хотите исключить некоторые из них, проверьте документ.

c) корневой package.json (подъем зависимостей)

Lerna держит там поднятые devDependencies (см. главу common devDependencies в lerna doc). Используйте команду lerna link convert, чтобы «извлечь» общие модули узлов в корневой package.json.

Например, мы подняли пакеты eslint npm, которые мы используем во всех сервисах. Здесь мы также установили пакет husky (как это рекомендуется в документации husky). Туда же можно поместить пакеты, которые используются не всеми сервисами, а большинством из них.

Иногда вы можете столкнуться с некоторыми проблемами с поднятыми зависимостями:

Первая проблема:

У нас есть реагирующие сценарии в нашей внешней службе в качестве зависимости от продукта, и у нас был корневой модуль package.json @hapi/lab (тестовая библиотека для сервера hapi для наших внутренних служб). Скрипты React начали кричать, что используют другую версию eslint как @hapi/lab. Итак, мы переместили @hapi/lab в package.json каждой серверной службы вместо того, чтобы держать его в корневом package.json.

Вторая проблема:

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

Помещение общих пакетов npm в корневой package.json не всегда может быть хорошим решением.

Наш корневой package.json:

{
  "name": "root",
  "private": true,
"devDependencies": {
   
   "btoa": "1.2.1",
   "eslint": "6.8.0",
   "eslint-config-airbnb-base": "14.0.0",
   "eslint-config-prettier": "6.10.0",
   "eslint-plugin-import": "2.2.0”,
   "eslint-plugin-jsx-a11y": "6.2.3”,
   "eslint-plugin-prettier": "3.1.2”,
   "eslint-plugin-react": "7.19.0",
   "husky": "4.2.3",
   "kafka-node": "3.0.1",
   "lerna": "3.20.2",
   "lint-staged": "9.5.0",
   "lodash": "4.17.15",
   "nodemon": "2.0.2",
   "nyc": "14.1.1",
   "prettier": "1.19.1",
   "typescript": "3.8.3”
},
"husky": {
 "hooks": {
  "pre-commit": "lerna run lint-staged — concurrency 1 — since dev",
  "pre-push": "lerna run prepush — stream — concurrency 1 — since dev"
  }
},
"dependencies": {
  "frontend": "file:frontend",
  "identity-service”: "file:identity-service",
  "project-service": "file:project-service",
  "reference-model-service": "file:reference-model-service",
  "neo4j-service": "file:neo4j-service"
  }
}

Хаски с Лерной

Мы используем хаски-хуки pre-commit и pre-push с флагами concurrency - 1 и с тех пор - dev. Сейчас я объясню эти флаги:

параллелизм 1

В нашем проекте есть интеграционные тесты, которые работают с тестовой базой данных postgresql, запущенной через docker-compose как образ докера. Все сервисы запускают одну и ту же БД (кроме neo4j-сервиса, который использует neo4j graph db).

Вот сценарий:

  1. запустить локальную базу данных (он запускается как сценарий оболочки через сценарий npm)
  2. запустить интеграционные тесты
  3. остановить локальную БД
  • это необходимо повторять последовательно, а не параллельно для всех служб, иначе тесты не пройдут, потому что они работают с одним и тем же образом базы данных.

начиная с [ref]

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

Когда вы запускаете команду lerna bootstrap, она должна установить все зависимости, определенные в корневом package.json для каждой службы. Не ожидайте, что вы увидите эти зависимости в node_modules в каждом сервисе. Это одна из сил лерны:

уменьшить требования к времени и пространству для многочисленных копий пакетов в средах разработки и сборки, «подняв» зависимости до самых верхних модулей node_modules уровня lerna-project.

Вам по-прежнему необходимо установить остальные зависимости с помощью npm i для каждой службы независимо (зависимости для производства, а также devDependencies, специфичные для данной службы, если они у вас есть).

Если вы попали в беду:

  • используйте команду lerna clean для удаления модулей node_modules из всех служб (убедитесь, что все модули node_modules были удалены, если не удалите их вручную) и переустановите их.
  • удалите package-lock.json и node_modules в корне.
  • не забудьте установить lerna глобально для доступа к CLI.

У Лерны есть и другие команды. Один из самых важных, который здесь не упоминался, — это lerna publish, но в нашем случае он нам не нужен.