Как вы делитесь локальными пакетами npm с другими командами в одном репозитории?

#javascript #node.js #npm #npm-install #npm-scripts

#javascript #node.js #npm #npm-install #npm-скрипты

Вопрос:

Сценарий

Рассмотрим следующую структуру папок:

 /my-service
  /src
  /bin
  /other-package
    /src
    package.json
  package.json
  

Есть 2 пакета npm: один для my-service и один для other-package .

my-service зависит от other-package .

my-service принадлежит team A и other-package принадлежит team B .

Имейте в виду, что команде B все равно потребуется развертывание my-service при other-package изменениях. Вот почему мы рассматриваем общий репозиторий.

Вопрос

Как вы структурируете эту зависимость таким образом, чтобы опыт разработчиков для обеих команд был разумным?

В идеале команде B нужно только установить и собрать other-package , и она может делать все, что им нужно, в этом каталоге.

Аналогично, команда A должна иметь возможность использовать последнюю версию other-package с минимальными трудностями при локальной разработке.

Опции

В настоящее время я рассматриваю 2 варианта решения этой проблемы, но не знаю, есть ли лучшие варианты.

Зависимость от локального файла

В этом варианте my-service имеет package.json вид, который выглядит следующим образом:

   "dependencies": {
    "other-package": "./other-package"
  },
  "scripts": {
    "build": "npm run build:other-package amp;amp; npm run build",
    "build:other-package": "cd other-package amp;amp; npm i amp;amp; npm run build amp;amp; cd .."
  }
  

Локальная зависимость от хранилища

В этом варианте my-service имеет package.json вид, который выглядит следующим образом:

   "dependencies": {
    "other-package": "./other-package/other-package-0.0.1.tgz"
  }
  

В этом случае команда B должна нести ответственность за запуск npm pack в other-package каталоге, когда новая версия будет готова, обновите package.json in my-service и зафиксируйте это в git.

Ответ №1:

Поместите оба пакета в отдельные репозитории, а в package.json файл первого поместите зависимость от репозитория git второго. Это выглядит следующим образом:

 "dependencies": {
  "my-other-package": "git://github.com/user/project.git#commit-ish"
}
  

Для получения подробной информации о доступных параметрах синтаксиса см. Документацию npm .

Таким образом, обе команды могут работать над своими пакетами индивидуально и независимо друг от друга. В то же время можно ссылаться на пакет через его URL-адрес git, и вы даже можете закрепить определенную ветку, тег или коммит, указав его commit-ish .

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

 "dependencies": {
  "my-other-package": "user/project#commit-ish"
}
  

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

Поскольку вы упомянули, что зависимая команда хочет использовать последнюю версию без особых проблем, вы можете просто захотеть использовать что-то вроде #master commit-ish. Затем для каждого npm install вы получаете последнюю версию, которая привязана к главной ветке.

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

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

Если по какой-либо причине это абсолютно обязательно должен быть единый репозиторий, и вы не можете использовать подход, который я описал, вас может заинтересовать термин «monorepo». По сути, это концепция наличия единого (моно) репозитория для нескольких пакетов. Одним из инструментов для управления таким monorepo является Lerna, и вы, возможно, захотите поближе познакомиться с ним.

Комментарии:

1. Имейте в виду, что команде B все равно потребуется развертывание my-service при other-package изменениях. Вот почему мы рассматриваем общий репозиторий.

Ответ №2:

Те, которые давно разделены, должны быть объединены; те, которые давно объединены, должны быть разделены.

Недавно я помог своей команде перейти на monorepo, объединив более 10 репозиториев в один. У Monorepo есть некоторые недостатки, он оказывает давление на средства контроля версий, когда он становится действительно большим (например, у Google). С другой стороны, это облегчает совместное использование кода, повторное использование сценариев сборки, потоков ci, пакетной обработки истории и файлов git и т. Д.

Типичный подход monorepo одинаково относится к подпроектам.

 /monorepo
  /node_modules <-- shared top level node_modules
  /packages
    /my-service
    /other-package
  

Если не по особой причине, я предлагаю вам сохранить оба пакета как родственные, а не родительско-дочерние.

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

 # in /monorepo
ln -s packages/other-package node_modules
  

Если вы хотите попробовать подобный инструмент lerna.js , он поможет вам справиться с этой рутиной.

Теперь вы можете указать свой my-service/package.json обычный

   "dependencies": {
    "other-package": "latest"
  }