Лучшие практики для рабочего пространства Lerna + пряжа + проекты Monorepo

Yarn

1.управление моноскладом

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

В настоящее время многие крупные проекты с открытым исходным кодом приняли этот метод, напримерBabel,React, Meteor, Ember, Angular,Jest, Umijs, Vue, а также create-react-appreact-router Ждать. Почти все репозитории, с которыми мы знакомы, без исключения используют метод монорепозитория.Видно, что содержимое каталога первого уровня этих проектов в основном является скаффолдингом, а основное содержимое управляется в каталоге пакетов и делится на несколько пакетов. .

Структура каталогов следующая:

├── packages
|   ├── pkg1
|   |   ├── package.json
|   ├── pkg2
|   |   ├── package.json
├── package.json

Основным преимуществом монорепозитория являетсяЕдиный рабочий процесса такжеCode Sharing. Например, если я хочу увидеть код пакета и понять определенную часть логики, мне не нужно искать его репозиторий, достаточно найти его в текущем репозитории; когда определенное требование требует изменения нескольких пакетов, я этого не делаю. Не нужно переходить в соответствующий репозиторий, чтобы модифицировать, тестировать, выпускать или ссылаться на npm, изменять непосредственно в текущем репо, единообразно тестировать и выпускать. Пока вы создаете набор строительных лесов, вы можете управлять (собирать, тестировать, выпускать) несколькими пакетами.

Одна картинка стоит тысячи слов:

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

Хотя разделение подрепозиториев и пакетов под-npm является естественным решением для изоляции проекта, когда содержимое репозитория связано, нет более эффективного метода отладки, чем объединение исходного кода.

В сочетании с реальными сценариями и бизнес-потребностями портала магазина-сервиса, естественное MonoRepo!Идеальная среда разработки может быть абстрагирована следующим образом:

«Заботьтесь только о бизнес-коде, вы можете напрямую повторно использовать его в бизнесе, не заботясь о методе повторного использования, и весь код находится в исходном коде при отладке».

В среде фронтенд-разработки несколько репозиториев Git и несколько npm являются идеальными сопротивлениями, что приводит к необходимости заботиться о номере версии для повторного использования и ссылке npm для отладки. И это самые большие преимущества MonoRepo.

Инструменты, связанные с использованием, упомянутые на картинке выше, — это сегодняшняя главная героиня Lerna!Lerna — самый известный инструмент управления Monorepo в отрасли с полным набором функций.

2. Lerna

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

2.1 Установка

Рекомендуется глобальная установка, поскольку часто используется команда lerna.

npm i -g lerna

2.2 Инициализация проекта

lerna init

Где package.json и lerna.json выглядят следующим образом:

// package.json
{
  "name": "root",
  "private": true, // 私有的,不会被发布,是管理整个项目,与要发布到npm的解耦
  "devDependencies": {
    "lerna": "^3.15.0"
  }
}
 
// lerna.json
{
  "packages": [
    "packages/*"
  ],
  "version": "0.0.0"
}

2.3 Создание пакета npm

Добавьте два пакета

lerna create @mo-demo/cli
lerna create @mo-demo/cli-shared-utils

2.4 Зависимое от модуля увеличение

Добавить зависимые модули в соответствующий пакет соответственно

lerna add chalk // 为所有 package 增加 chalk 模块 
lerna add semver --scope @mo-demo/cli-shared-utils // 为 @mo-demo/cli-shared-utils 增加 semver 模块 
lerna add @mo-demo/cli-shared-utils --scope @mo-demo/cli // 增加内部模块之间的依赖

2.5 Выпуск

lerna publish

2.6 Управление пакетами зависимостей

Вышеупомянутые шаги 1-5 уже охватывают весь жизненный цикл Lerna, но когда мы поддерживаем этот проект, после извлечения кода из репозитория нам нужно установить зависимости для каждого пакета.

Мы также обнаружили на шаге 4 lerna add, что пакет, установленный для пакета, помещается в каталог пакета.node_modulesПод содержанием. Таким образом, пакеты, от которых зависит несколько пакетов, будут устанавливаться несколько раз несколькими пакетами и поддерживаться в каждом пакете.node_modules, не освежает. Поэтому мы используем --hoist для продвижения зависимостей каждого пакета в корневую директорию проекта, чтобы снизить стоимость установки и управления.

lerna bootstrap --hoist

Чтобы каждый раз не вводить параметр --hoist, его можно настроить в lerna.json:

{
  "packages": [
    "packages/*"
  ],
  "command": {
    "bootstrap": {
      "hoist": true
    }
  },
  "version": "0.0.1-alpha.0"
}

После настройки, в случае, если предыдущие пакеты зависимостей были установлены под каждым пакетом, нам нужно только очистить установленные зависимости:

lerna clean

Затем запустите lerna bootstrap, чтобы увидеть, что зависимости пакетов установлены в корневом каталоге.node_modulesбинго.

3. Лучшие практики Lerna + Monorepo

Lerna не отвечает за такие задачи, как сборка и тестирование.. Он предлагает модель каталогов для централизованного управления пакетами и предоставляет набор автоматизированных процедур управления, так что разработчикам не нужно копаться в конкретных компонентах для обслуживания контента, и они могут быть глобально доступны. в корневом каталоге проекта.Управление, основанное на сценариях npm, позволяет пользователям выполнять построение компонентов, форматирование кода и другие операции. Далее давайте рассмотрим лучшие практики создания проекта Monorepo на основе Lerna и его сочетания с другими инструментами.

В настоящее время наиболее распространенным решением MONOREPO - это рабочие пространства Lerna и пряжи, основанные на рабочем процессе Monorepo Lerna и Yarn Workspace. Поскольку пряжа и Лерна имеют много совпадений в функции, мы принимаем метод, официально рекомендованный пряжей, используйте пряжу, чтобы справиться с проблемами зависимости и использовать Lerna для решения проблем с выпуском. Используйте пряжу, если вы можете сделать это с пряжей

3.1 yarn workspace

3.1.1 Строительная среда

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

  • monorepo: существуют зависимости между различными библиотеками. Например, A зависит от B, поэтому нам обычно нужно связать B с node_module A. При наличии большого количества хранилищ вручную управлять этими операциями связывания очень обременительно, поэтому автоматические операции связывания обязательно. Свяжите каждую зависимость в соответствии с топологической сортировкой

Решение: при использовании рабочего пространства программа yarn install автоматически поможет решить проблемы с установкой и связыванием.

yarn install # 等价于 lerna bootstrap --npm-client yarn --use-workspaces

3.1.2 Очистка окружающей среды

Очищайте зависимости, когда зависимости испорчены или проекты испорчены

  • Обычный проект: напрямую удаляйте node_modules и скомпилированные продукты.

  • monorepo: нужно не только удалить скомпилированные продукты root_modules root, но также необходимо удалить node_modules и скомпилированные продукты в каждом пакете

Решение: используйте lerna clean, чтобы удалить все node_modules, используйте рабочие области yarn run clean, чтобы выполнить очистку всех пакетов.

lerna clean # 清理所有的node_modules
yarn workspaces run clean # 执行所有package的clean操作

3.1.3 Установить|Удалить зависимости

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

  • монорепозиторий: обычно делится на три сценария

    • Установите зависимости для пакета: yarn workspace packageB add packageA Установите packageA как зависимость от packageB

    • Установите зависимости для всех пакетов: используйте рабочие области пряжи, добавьте lodash для установки зависимостей для всех пакетов.

    • Установите зависимости для root: общедоступные инструменты разработки устанавливаются в root, такие как typescript, мы используем yarn add -W -D typescript для установки зависимостей для root

Соответствующие три сценария удаляют зависимости следующим образом.

yarn workspace packageB remove packageA
yarn workspaces remove lodash
yarn remove -W -D typescript

3.1.4 Строительство проекта

  • Обычный проект: создайте скрипт сборки npm, используйте сборку пряжи для завершения сборки проекта.

  • Монорепозиторий: В отличие от обычных проектов, между пакетами существуют взаимозависимости, например, пакет B может быть собран только после того, как будет собран пакет A, иначе произойдет ошибка, которая фактически требует от нас сборки с правилом топологического упорядочения.

Правила топологической сортировки мы можем построить сами.К сожалению, yarn workspace не поддерживает выполнение команд в соответствии с правилами топологической сортировки.Хотя rfc принят, он еще не реализован.К счастью, lerna поддерживает выполнение команд в соответствии с правилами топологической сортировки, - Параметр -sort может управлять выполнением команд в топологическом порядке.

lerna run --stream --sort build

3.1.5 Обновление версии и выпуск пакета

После завершения тестирования проекта он включает выпуск версии, который обычно включает следующие шаги.

  • Условная проверка: Пройден ли проверочный тест, есть ли незафиксированный код, выполняется ли операция выпуска версии на основной ветке

  • version_bump: номер версии должен быть обновлен, когда версия выпущена.В настоящее время, как обновить номер версии является проблемой.Как правило, все будут следовать семантике semVer.

  • Список изменений: Чтобы легко проверить, какие функции решает каждая версия каждого пакета, нам нужно создать журнал изменений для каждого пакета, чтобы пользователи могли просматривать функциональные изменения каждой версии.

  • сгенерировать git-тег: Чтобы облегчить последующие проблемы с откатом и устранение неполадок, обычно необходимо создать тег git для каждой версии.

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

  • Опубликовать пакет npm: После публикации git нам также необходимо опубликовать обновленную версию в npm для использования внешними пользователями.

Мы сочли это громоздким и подверженным ошибкам делать это вручную, к счастью, lerna может помочь нам с этими проблемами.

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

Lerna предоставляет публикацию и версию для поддержки обновления и выпуска версии.Функция публикации может включать в себя работу над версией или просто выполнять операцию публикации.

3.2 Элегантный коммит

3.2.1 commitizen && cz-lerna-changelog

commitizenИнструмент для форматирования сообщений коммитов git, который предоставляет вопросительный способ получить необходимую информацию коммита.

cz-lerna-changelogЭто спецификация подачи, специально разработанная для проекта Lerna.В процессе запроса будет аналогичный выбор пакетов, которые будут затронуты. следующим образом:

Мы используемcommitizenа такжеcz-lerna-changelogЧтобы стандартизировать отправку, подготовьтесь к автоматическому созданию журналов позже.

Поскольку это зависит от разработки всего проекта, установите его в корневой каталог:

yarn add  -D commitizen
yarn add  -D cz-lerna-changelog

После завершения установки вpackage.jsonДобавьте поле конфигурации вcz-lerna-changelogнастроен наcommitizen. В то же время, потому чтоcommitizenНе является глобально безопасным, поэтому необходимо добавить сценарий сценариев для выполнения git-cz.

{
  "name": "root",
  "private": true,
  "scripts": {
    "commit": "git-cz"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-lerna-changelog"
    }
  },
  "devDependencies": {
    "commitizen": "^3.1.1",
    "cz-lerna-changelog": "^2.0.2",
    "lerna": "^3.15.0"
  }
}

Затем его можно использовать в обычной разработке.yarn run commitПриходите и введите шаг за шагом в соответствии с подсказкой, чтобы завершить отправку кода.

3.2.2 commitlint && husky

Выше мы использовали commitize для стандартизации представления, но это зависит от сознательного использования разработки.yarn run commit. Что, если вы забудете об этом или отправите его напрямую с помощью git commit? Ответ заключается в проверке представленной информации при подаче, и если она не соответствует требованиям, она не будет подана, а будет дана подсказка. Работу по проверке выполняет commitlint, а сроки проверки уточняет хаски. Husky наследует все хуки от Git. Когда хук срабатывает, хаски может предотвратить незаконные коммиты, пуши и т. д.

Установка Приятель и нормы, которые необходимо соблюдать

yarn add -D @commitlint/cli @commitlint/config-conventional

Добавьте файл конфигурации для приятеля в корневом каталоге проектаcommitlint.config.jsдляcommitlintУкажите соответствующую спецификацию

module.exports = { 
	extends: ['@commitlint/config-conventional'] 
}

Установитьhusky

yarn add -D husky

существуетpackage.jsonДобавьте следующую конфигурацию в

 "husky": { 
 		"hooks": { 
    		"commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 
     }
 }

«commit-msg» — это хук для проверки информации о коммите, когда git фиксирует, и он будет использовать commitlit для проверки, когда он запускается. После завершения установки и настройки, когда вы хотите отправить через git commit или другие сторонние инструменты, вы не можете отправить, пока информация об отправке не соответствует спецификациям. Это вынуждает разработчиков использовать фиксацию запуска пряжи для фиксации.

3.2.3 eslint && lint-staged

В дополнение к стандартизации информации о представлении, сам код также должен полагаться меньше на стандарт, чтобы объединить стиль.

Установить

yarn add  -D standard lint-staged

Eslint — это полный набор спецификаций кода JavaScript (машинописи) с собственным линтером и автоматическим исправлением кода. Автоматически форматировать и исправлять код, заранее находить проблемы со стилем и программой, а также поддерживать проверку спецификации кода машинописного текста,eslintrc.jsonКонфигурация:

{
    "extends": [
        "yayajing",
        "plugin:@typescript-eslint/recommended"
    ],
    "parser": "typescript-eslint-parser",
    "plugins": ["@typescript-eslint"],
    "rules": {
        "eqeqeq":"off",
        "@typescript-eslint/explicit-function-return-type": "off",
        "no-template-curly-in-string": "off"
    }
  }

lint-staged stagedэто концепция в Git, представляющая область временного хранения,lint-stagedУказывает, что проверяются и исправляются только файлы в промежуточной области. С одной стороны, это может повысить эффективность проверки, а с другой стороны, может принести большое удобство старым проектам.

Конфигурация package.json

// package.json
{
  "name": "root",
  "private": true,
  "scripts": {
    "c": "git-cz"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-lerna-changelog"
    }
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "lint-staged": {
    "*.ts": [
      "eslint --fix",
      "git add"
    ]
  },
  "devDependencies": {
    "@commitlint/cli": "^8.1.0",
    "@commitlint/config-conventional": "^8.1.0",
    "commitizen": "^3.1.1",
    "cz-lerna-changelog": "^2.0.2",
    "husky": "^3.0.0",
    "lerna": "^3.15.0",
    "lint-staged": "^9.2.0"
  }
}

После завершения установки вpackage.jsonДобавьте конфигурацию lint-staged, как показано выше, чтобы выполнить файл js в промежуточной области.eslint --fixПроверить и исправить автоматически. Когда вы это проверите, вы будете использовать хаски, установленный выше, и добавить его в конфигурацию хаски.pre-commitХук используется для выполнения поэтапных операций проверки.

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

3.3 Публикация автоматически сгенерированных журналов

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

3.3.1 версия lerna обновленная версия

  • Найдите пакеты, которые изменились с момента последнего выпуска

  • Предложите разработчику определить номер версии для выпуска

  • Обновите поле версии package.json во всех обновленных пакетах.

  • Обновите номер версии зависимости в пакете, который зависит от обновленного пакета.

  • Обновите поле версии в lerna.json

  • Отправьте указанную выше модификацию и нажмите на тег

  • отправить в репозиторий git

3.3.2 Используйте lerna publish для отправки новой версии в npm

CHANGELOGОчевидно, что она соответствует версии одна за другой, поэтому вам нужно найти путь в версии lerna.Посмотрев подробное описание команды версии lerna, вы увидите параметр конфигурации--conventional-commits. Верно, пока мы отправляем в соответствии со спецификацией, CHANGELOG текущей версии будет автоматически сгенерирован во время процесса версии lerna. Для удобства, не вводя каждый раз параметры, можно настроитьlerna.json, следующим образом:

{
  "packages": [
    "packages/*"
  ],
  "command": {
    "bootstrap": {
      "hoist": true
    },
    "version": {
      "conventionalCommits": true
    }
  },
  "ignoreChanges": [
    "**/*.md"
  ],
  "version": "0.0.1-alpha.1"
}

lerna versionИзменения с момента выпуска предыдущей версии будут обнаружены, но есть некоторые отправленные файлы, которые мы не хотим инициировать изменения версии.Например, изменение файлов .md фактически не вызывает изменений в логике пакета и не должно запускать версию изменения. в состоянии пройтиignoreChangesНастроить исключения. Как указано выше.

действительныйlerna versionРедко используется напрямую, потому что он включен вlerna publishВ, использовать напрямуюlerna publishДостаточно.

3.4 Идеальные тестовые случаи

монорепозиторий: есть два способа проверить

  • Использование унифицированной тестовой конфигурации jest удобно для глобального запуска jest. Преимущество состоит в том, что можно легко подсчитать охват тестами всех кодов. Недостатком является то, что если пакеты относительно разнородны (например, небольшие программы, интерфейсы, серверы узлов, д.), унифицированное тестирование Конфигурация не очень хорошо написана

  • Каждый пакет поддерживает команду тестирования отдельно.Используйте рабочее пространство пряжи для запуска теста.Недостаток заключается в том, что непросто собрать тестовое покрытие всех кодов унифицированным образом.

Если вы используете jest для написания тестовых случаев и поддержки typescript, вам необходимо инициализировать конфигурацию jest.config.js:

module.exports = {
  preset: 'ts-jest',
  moduleFileExtensions: ['ts'],
  testEnvironment: 'node'
}

4 Краткий обзор практики

На данный момент, в основном, мы построилиlernaа такжеyarn workspaceЛучшие наработки проекта монорепозитория, функции имеют:

  • Идеальный рабочий процесс

  • поддержка машинописного текста

  • Единое кодирование

  • полный модульный тест

  • Механизм публикации в один клик

  • идеальный журнал изменений

...

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

Большая часть этой статьи воспроизведена из:Tickets.WeChat.QQ.com/Yes/NL на7 и 0i…