본문으로 건너뛰기

Lerna 입문 가이드

무료2018-01-13#Tool#monorepo#lerna monorepo#babel lerna#lerna tutorial#lerna-changelog

간단하고 실용적인 monorepo 관리 도구, 더 이상 수동으로 changelog 를 정리할 필요가 없습니다

一.포지셔닝

Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.

멀티 패키지 관리 도구로, monorepo 유지 관리를 지원합니다

P.S.Lerna 는 Babel 이 일상적으로 사용하고 오픈소스화한 도구입니다. Why is Babel a monorepo? 참조

二.monorepo

monorepo(monolithic repository) 는 multirepo 에 대비되는 개념으로, 각각 단일 코드 리포지토리와 복수 코드 리포지토리 (one-repository-per-module) 를 지칭합니다

multirepo 는 전통적인 방식으로, 모듈별로 여러 코드 리포지토리로 분할하지만, 실천において 몇 가지 문제가 발견되었습니다:

  • issue 관리가 혼란스럽고, 자주 core repo 에서 module 문제를 제기해야 하며, Close this and track that 가 필요

  • changelog 통합이 어렵고, 모든 변경 리포지토리를 수동으로 정리하고 통합해야 함

  • core repo 버전 업데이트가 번거롭고, core repo 에 의존하는 모든 module 버전을 동기화하여 업데이트해야 함

monorepo 는 모든 관련 module 을 하나의 repo 에まとめ, 각 module 은 독립적으로 릴리스하지만, 해당 repo 와 통일된 버전 번호를 사용합니다 (예: BabelReact). issue 와 PR 은 모두 해당 repo 에 집중되며, changelog 는 하나의 commit 리스트에서 쉽게 정리할 수 있습니다 (さらに commit 규범으로 issue tag 를 관련지으면, 규범적인 changelog 를 자동 생성할 수 있습니다)

monorepo 도 몇 가지 문제가 있지만, 위의痛点ほど 강렬하지는 않습니다:

  • repo 体积가 较大하여, 버전 관리 문제를 초래할 수 있음 (Git 은 体积가 너무 큰 repo 관리에 적합하지 않음)

  • 통일 빌드 도구로, 빌드 도구에 더 높은 요구를 제기하며, 다양한 관련 module 을 빌드할 수 있어야 함

소스 코드 관리 관점에서 보면, multirepo 와 monorepo 는 두 가지 다른 이념입니다. 전자는 다원적인 발전을 허용하며, 각 module 은 자신의 방식 (빌드, 의존 관리, 유닛 테스트 등) 을 가질 수 있습니다. 후자는 집중 관리를 희망하며, 방식 차이로 인한 커뮤니케이션 비용을 줄입니다

monorepo 의 상징적인 특징은 디렉토리 구조로, 예를 들어 React:

react-16.2.0/
  packages/
    react/
    react-art/
    react-.../

각 module 은 자신의 의존 항목 (package.json) 을 가지며, 독립적인 npm package 로 릴리스할 수 있습니다. 소스 코드를 함께 유지 관리할 뿐입니다

전형적인 케이스:

P.S.이전 rollup 사용 시 문제 발생 시, 먼저 주 repo 에서 관련 issue 를 조회하고, 이후 단서에 따라 해당 plugin repo 를 찾아, 다시 관련 issue 를 조회했습니다. 항상 매우 번거롭다고 느꼈고, 어디가 잘못되었는지 말할 수 없었지만,原来是 소스 코드 조직 방식으로 인한 혼란이었습니다

三.lerna 체험

// 설치
npm install lerna -g
git init hoho-lerna && cd hoho-lerna
// 디렉토리 구조 초기화
lerna init

다음과 같은 구조를 얻습니다:

hoho-lerna/
  packages/
  lerna.json
  package.json

module 생성:

mkdir packages/hoho-lerna-core && cd packages/hoho-lerna-core
npm init

이렇게 하면 최종적으로一堆의 package 를 얻습니다:

packages/
  hoho-lerna-core/
    package.json
  hoho-lerna-module-a/
    package.json
  hoho-lerna-module-b/
    package.json
  module.../

실제로 하는 일은 모듈별로 package 로 분할하고, (module 레벨의 package.json 을 통해) 각 package 간의 의존 관계를 선언하는 것입니다

의존 관계 처리

moduleA 가 core 에 의존하는 경우, lerna bootstrap 명령으로 의존 관계를 처리한 후, moduleAnode_modules下に core 디렉토리를 가리키는 심볼릭 링크가 생성됩니다. 살아있는 예 가 있습니다

주의:npm 은 peerDependencies 를 자동 설치하지 않습니다. lerna 도 이 서비스를 제공하지 않습니다

lerna bootstrap 은 사전에 선언된 의존 관계에 따라, 심볼릭 링크를 확립하여 각 package 를 실제로 연계합니다

package 릴리스

packages 에まとめたので, 통일 관리가 용이하여, 모든 package 를 npm 에 원클릭으로 릴리스할 수 있습니다

P.S.먼저 npm 계정이 필요합니다 (스스로 등록 하고), npm adduser 로 로컬 설정에 추가합니다

준비가 되면,早速일석 n 조를 시작:

lerna publish

예상대로라면, 유사한 출력을 얻습니다:

lerna info version 2.7.0
lerna info current version 0.0.0
lerna info Checking for updated packages...
lerna info Comparing with initial commit.
lerna info Checking for prereleased packages...
? Select a new version (currently 0.0.0) Major (1.0.0)

Changes:
 - hoho-lerna-core: 1.0.0 => 1.0.0
 - hoho-lerna-module-a: 1.0.0 => 1.0.0
 - hoho-lerna-module-b: 1.0.0 => 1.0.0

? Are you sure you want to publish the above changes? Yes
lerna info publish Publishing packages to npm...
lerna info published hoho-lerna-module-b
lerna info published hoho-lerna-core
lerna info published hoho-lerna-module-a
lerna info git Pushing tags...
Successfully published:
 - hoho-lerna-core @1.0.0
 - hoho-lerna-module-a @1.0.0
 - hoho-lerna-module-b @1.0.0
lerna success publish finished

그 후, npm registry 에 3 개의 쓰레기 package 가 추가됩니다……

publish 의 대략적인 프로세스는:

  1. 로컬에서 태그를 打つ (예: git tag v1.0.0)

  2. 의존 항목 버전 번호 자동 업데이트 예시

  3. 이후 각 package 를 npm 에 릴리스

  4. 마지막으로 태그와 해당 commit 를 push

주의:npm 로 릴리스 단계에서 실패한 경우 (예:npm 계정을 설정하지 않음),次回 직접 lerna publish 해도 직접 릴리스할 수 없습니다. 로컬 태그가 이미 v1.0.0 이어서前回 릴리스 성공으로 간주되기 때문입니다. 이 태그를 수동으로 롤백해도 안 되며, .git 에 릴리스 상태가 기록되어 있을 수 있어, 롤백 후 commit hash 매칭 오류가 발생합니다. 여기는 그다지 친절하지 않습니다

P.S.더 많은 명령은 Lerna 참조

changelog 자동 생성

먼저 changelog 도구를 설치:

npm install lerna-changelog -g

그 후 lerna.json 에 해당 설정 항목 추가:

"changelog": {
  "repo": "ayqy/hoho-lerna",
  "labels": {
    "enhancement": ":rocket: Enhancement",
    "bug": ":bug: Bug Fix",
    "doc": "Refine Doc",
    "feat": "New Feature"
  },
  "cacheDir": ".changelog"
}

특히 주의:repo 는 필수로, 자동 추론할 수 있다고 하지만, 실제로는 그다지 신뢰할 수 없습니다. The 'repo' field automatically inferred failed, but no error occurred 참조

P.S.labels 에서, key 는 Github 에서 설정하는 라벨로, Issue/PR 을 분류하는 데 사용하며, value:bug: 는 장난꾸러기 emoji 로, changelog 내의该类 change 의 제목으로 사용됩니다

여기까지로 완료된 것이 아닙니다. Github repo 권한(Issue, PR 조회를 위해) 이 필요하며, token 을 환경 변수로 공개합니다 (자주 사용하는 경우, ~/.bash_profile 에 추가):

export GITHUB_AUTH="..."

설정 완료. "자동"을 달성하려면, 일상 개발 유지가약속된규범을 따르는 전제가 필요합니다.否则마지막에 도구는 반드시 changelog 를 추측할 수 없습니다. 규범이란:

  1. (권장)commit message 에서 해당 issue 를 관련짓기

  2. (필수)PR 생성 시 사전에 정의한 label 선택

도구는 github 에서 지정된 label 을 가진 PR 만을 정리하고, commit message 를 changelog 항목으로 하므로, commit message 에서 issue 를 관련짓는 것을 권장합니다. 생성된 changelog 는 해당 issue 에 링크할 수 있습니다:

Uses github PR/Issue names categorized by labels with configurable headings.

예를 들어:

git cm -m "feat: changelog, Close #1"

그 후 PR 을提交하고 label 을贴付:feat. merge 후, 로컬에서 pull 하여 lerna-changelog 를 시도:

## Unreleased (2018-01-13)

#### New Feature
* [#2](https://github.com/ayqy/hoho-lerna/pull/2) feat: changelog, Closes [#1](https://github.com/ayqy/hoho-lerna/issues/1). ([ @ayqy](https://github.com/ayqy))

#### Committers: 1
-  黯羽輕揚 ([ayqy](https://github.com/ayqy))

매우 깔끔:https://github.com/ayqy/hoho-lerna/releases/tag/v1.1.0

P.S.로컬에서 생성된 changelog 임시 파일을 .gitignore 에서 무시해야 합니다. 새 버전 릴리스 시에만 로컬에서 lerna-changelog 하고, 생성된 changelog 를 release note 에贴付합니다. release note 를 자동 릴리스하지 않는 것은 API 제한 또는 신중한 고려 때문일 것입니다.毕竟 release note 는 비교적 중요하니까요

さらに, 이 방식으로 자동으로 changelog 를 정리하는 것은, 실제로는개발 중 제약(PR 의 label 규범, commit message 를 changelog 항목으로 하는 규범) 에 의존하고 있으며, lerna 와는 그다지 관계가 없습니다. monorepo(Issue/PR) 를 모두 함께 두면, 이思路에 따라 Issue/PR 정보를 취득하여, changelog 를 정리할 수 있습니다

마지막으로 changelog 를 정리하는 거대한 작업량을 일상의 개발 유지에 분산시키는 것에 해당합니다. change 는 모두 PR 을経由하며, issue 기록이 필요합니다. 익숙하지 않은 경우 매우 번거롭습니다 (commit message 에 label 을 포함하여 PR 을経由하지 않는 요구 가 있으며, 이후 지원될 예정입니다)

四.적용 시나리오

어떤 시나리오에서 monorepo 를 채택할 수 있습니까 (lerna 로 관리)?

  • 너무 방대하지 않은 프로젝트. 함께 통합하면 100G 의 소스 코드가 있다면, 다시 고려하십시오

  • 다 모듈/플러그인화 프로젝트. 공식 유지 플러그인을 package 로 하는 것이 매우 적합

さらに 필요:

  • 기초 건설

  • 팀 신뢰

기초 건설이란 강력한 빌드 도구로, 모든 모듈의 build 수요를 충족할 수 있어야 합니다 (순수 프런트엔드 프로젝트의 경우, build 압력은 크지 않습니다)

monorepo 환경에서는, 타인의 코드를변경하는 것을 권장합니다. 한편으로 지속적 통합 메커니즘 (예: React - CircleCI) 으로 변경으로 인한 영향을 확인하고, 다른 한편으로 다른 팀 간의 상호 신뢰가 필요합니다.否则자주 하나의 팀의 변경이 다른 팀에 영향을 미치며, 타인의 변경을 롤백해야 하고,逆に 효율에 영향을 미칩니다

P.S.Lerna 는 오래전부터 나왔으며 (Babel 과 거의 동년배), 많은 프로젝트 가 사용하고 있습니다

참고 자료

댓글

아직 댓글이 없습니다

댓글 작성