Проблема
В нашей компании мы строим проект на основе микросервисной архитектуры. Классическая проблема, с которой вы столкнулись во время разработки: вы хотели бы избежать некоторых проблем, прежде чем отправлять изменения в удаленный репозиторий git. Эти проблемы в основном связаны с ошибками lint и тестов. Если вы измените что-то в одном сервисе и захотите отправить свои изменения в удаленную ветку, все скрипты линтеров и тестов для всех сервисов запустятся. Эта проблема вызвана установкой хаски в каждом сервисе. В документации Husky сказано: «используйте lerna».
Вторая проблема, с которой мы столкнулись, это то, что мы начали устанавливать lerna слишком поздно. После года разработки пришла lerna. Настроила ее в самом начале.
Весь код (мы используем его в нашем проекте, но некоторая конфиденциальная информация скрыта) и приведенный ниже текст основаны на моем опыте включения lerna в наш проект.
Настройка лерны
- Запустите скрипт 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).
Вот сценарий:
- запустить локальную базу данных (он запускается как сценарий оболочки через сценарий npm)
- запустить интеграционные тесты
- остановить локальную БД
- это необходимо повторять последовательно, а не параллельно для всех служб, иначе тесты не пройдут, потому что они работают с одним и тем же образом базы данных.
начиная с [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, но в нашем случае он нам не нужен.