概要
monorepoなライブラリをnpmに公開するための構成を調査、検討する。
検証リポジトリ
以下にこの記事で検証したリポジトリを示す。
動作環境
macOS Ventura バージョン13.6.6 Node 21.4.0
前提となる構成
turborepo
turboを使ってmonorepoを構成する
changeset
turborepoによると、@changesets/cli - npmを推奨している。
verdaccio
localで動作するnpm registry。 実験でpublishしまくるので公式のregistryは流石に使いにくい。
Verdaccioの構築
docker imageを使うのがお手軽そうなので、取得して立ち上げる。
以下の点に注意。 * portの指定忘れると開けない * volumeの指定しないと再起動でデータが消える
$ docker pull verdaccio/verdaccio:nightly-master $ docker run -it -p4873:4873 --rm verdaccio/verdaccio:nightly-master (node:8) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead. (Use `node --trace-deprecation ...` to show where the warning was created) info -=- local storage path /verdaccio/storage/data/.verdaccio-db.json info -=- no private database found, recreating new one on /verdaccio/storage/data/.verdaccio-db.json info --- using htpasswd file: /verdaccio/storage/htpasswd info --- http address http://0.0.0.0:4873/ info --- version: 7.0.0-next-7.13 info --- server started
指定したportをブラウザで開く。
open http://0.0.0.0:4873/
ひとまず初期画面が表示される。
検証用のリポジトリを作成
こちらに作成しました。作成の意図としては - nodejs で動作するpackageをイメージ - turborepoで構成 - 複数のpackageを構成
changesetの導入
packageにインストール
$ npm -w packages/core i -D @changesets/cli $ npm -w packages/express i -D @changesets/cli
coreとexpressのpackage.jsonにchangeset
スクリプトを追加
diff --git a/packages/core/package.json b/packages/core/package.json index f8facde..c7876fd 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -7,12 +7,14 @@ "scripts": { "build": "tsup src/*", "lint:eslint": "eslint --max-warnings 0 --ext .ts,.tsx .", - "lint:prettier": "prettier './src/**/*.{ts,tsx,js,json,css}' --check" + "lint:prettier": "prettier './src/**/*.{ts,tsx,js,json,css}' --check", + "changeset": "changeset" diff --git a/packages/express/package.json b/packages/express/package.json index f8facde..c7876fd 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -7,12 +7,14 @@ "scripts": { "build": "tsup src/*", "lint:eslint": "eslint --max-warnings 0 --ext .ts,.tsx .", - "lint:prettier": "prettier './src/**/*.{ts,tsx,js,json,css}' --check" + "lint:prettier": "prettier './src/**/*.{ts,tsx,js,json,css}' --check", + "changeset": "changeset"
changesetの初期化
$ npm -w packages/core run changeset init $ npm -w packages/express run changeset init
publishのaccessをpublicに変更
diff --git a/packages/core/.changeset/config.json b/packages/core/.changeset/config.json index 91b6a95..fce1c26 100644 --- a/packages/core/.changeset/config.json +++ b/packages/core/.changeset/config.json @@ -4,7 +4,7 @@ "commit": false, "fixed": [], "linked": [], - "access": "restricted", + "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", "ignore": [] diff --git a/packages/core/package.json b/packages/core/package.json index 5f59f4d..1987880 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -14,5 +14,8 @@ "@changesets/cli": "^2.27.1", "@example-monorepo/dev-config": "*", "tsup": "^8.0.2" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/express/.changeset/config.json b/packages/express/.changeset/config.json index 91b6a95..fce1c26 100644 --- a/packages/express/.changeset/config.json +++ b/packages/express/.changeset/config.json @@ -4,7 +4,7 @@ "commit": false, "fixed": [], "linked": [], - "access": "restricted", + "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", "ignore": [] diff --git a/packages/express/package.json b/packages/express/package.json index c7876fd..586fd64 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -19,5 +19,8 @@ "@types/express": "^4.17.21", "express": "^4.19.2", "tsup": "^8.0.2" + }, + "publishConfig": { + "access": "public" } }
changesetの設定を行う
$ npm -w packages/core run changeset [branch:main](untracked)[~/project/example-monorepo] > @example-monorepo/core@0.0.0 changeset > changeset 🦋 Which packages would you like to include? · @example-monorepo/core, @example-monorepo/express 🦋 Which packages should have a major bump? · No items were selected 🦋 Which packages should have a minor bump? · No items were selected 🦋 The following packages will be patch bumped: 🦋 @example-monorepo/core@0.0.0 🦋 @example-monorepo/express@0.0.0 🦋 Please enter a summary for this change (this will be in the changelogs). 🦋 (submit empty line to open external editor) 🦋 Summary · the first update 🦋 🦋 === Summary of changesets === 🦋 patch: @example-monorepo/core, @example-monorepo/express 🦋 🦋 Note: All dependents of these packages that will be incompatible with 🦋 the new version will be patch bumped when this changeset is applied. 🦋 🦋 Is this your desired changeset? (Y/n) · true 🦋 Changeset added! - you can now commit it 🦋 🦋 If you want to modify or expand on the changeset summary, you can find it here
bump up
version, publishへのエイリアスを作成する。
diff --git a/package.json b/package.json index 106fd31..3f6c163 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,8 @@ "build": "turbo run build", "lint:eslint": "turbo run lint:eslint", "lint:prettier": "turbo run lint:prettier", + "version": "turbo run version", + "publish": "turbo run publish", "format": "prettier --write \"**/*.{ts,tsx,md}\"" }, "devDependencies": { diff --git a/packages/core/package.json b/packages/core/package.json index 1987880..74c6f4a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -8,7 +8,9 @@ "build": "tsup src/*", "lint:eslint": "eslint --max-warnings 0 --ext .ts,.tsx .", "lint:prettier": "prettier './src/**/*.{ts,tsx,js,json,css}' --check", - "changeset": "changeset" + "changeset": "changeset", + "version": "changeset version", + "publish": "changeset publish" }, "devDependencies": { "@changesets/cli": "^2.27.1", diff --git a/packages/express/package.json b/packages/express/package.json index 586fd64..531b6b9 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -8,7 +8,9 @@ "build": "tsup src/*", "lint:eslint": "eslint --max-warnings 0 --ext .ts,.tsx .", "lint:prettier": "prettier './src/**/*.{ts,tsx,js,json,css}' --check", - "changeset": "changeset" + "changeset": "changeset", + "version": "changeset version", + "publish": "changeset publish" }, "dependencies": { "@example-monorepo/core": "*" diff --git a/turbo.json b/turbo.json index 8402ed6..c3df47b 100644 --- a/turbo.json +++ b/turbo.json @@ -18,6 +18,15 @@ "dev": { "cache": false, "persistent": true + }, + "version": { + "cache": false, + "persistent": true + }, + "publish": { + "cache": false, + "persistent": true } + } }
versionを上げる
$ npm run version
commit 62802584c2bbc5be7fec65d73d33d2efc12b01c3 Author: mizuki_r <ry.mizuki@gmail.com> Date: Mon Apr 29 15:40:07 2024 +0900 bump 0.0.1 diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md new file mode 100644 index 0000000..726ce34 --- /dev/null +++ b/packages/core/CHANGELOG.md @@ -0,0 +1,7 @@ +# @example-monorepo/core + +## 0.0.1 + +### Patch Changes + +- the first update diff --git a/packages/core/package.json b/packages/core/package.json index 74c6f4a..8b1b54c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@example-monorepo/core", - "version": "0.0.0", + "version": "0.0.1", "private": true, "main": "build/index.js", "types": "src/index.ts", diff --git a/packages/express/CHANGELOG.md b/packages/express/CHANGELOG.md new file mode 100644 index 0000000..07d956c --- /dev/null +++ b/packages/express/CHANGELOG.md @@ -0,0 +1,9 @@ +# @example-monorepo/express + +## 0.0.1 + +### Patch Changes + +- the first update +- Updated dependencies + - @example-monorepo/core@0.0.1 diff --git a/packages/express/package.json b/packages/express/package.json index 531b6b9..1d38dc0 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -1,6 +1,6 @@ { "name": "@example-monorepo/express", - "version": "0.0.0", + "version": "0.0.1", "private": true, "main": "build/index.js", "types": "src/index.ts",
verdaccioとの接続
verdaccioのURLをnpmrcに登録
diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..30fb789 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +registry=http://0.0.0.0:4873
adduserしてverdaccioにユーザを登録
$ npm adduser npm notice Log in on http://0.0.0.0:4873/ Username: mizuki_r Email: (this IS public) XXXXX@gmail.com Logged in on http://0.0.0.0:4873/.
いざ、publish、とおもったのに....
$ npm run publish > example-monorepo@0.0.0 publish > turbo run publish • Packages in scope: @example-monorepo/core, @example-monorepo/dev-config, @example-monorepo/express • Running publish in 3 packages • Remote caching disabled @example-monorepo/core:publish: cache bypass, force executing 6d170e85bb8ec0a1 @example-monorepo/express:publish: cache bypass, force executing 97213dc3ac891ae0 @example-monorepo/express:publish: @example-monorepo/express:publish: > @example-monorepo/express@0.0.1 publish @example-monorepo/express:publish: > changeset publish @example-monorepo/express:publish: @example-monorepo/core:publish: @example-monorepo/core:publish: > @example-monorepo/core@0.0.1 publish @example-monorepo/core:publish: > changeset publish @example-monorepo/core:publish: @example-monorepo/express:publish: 🦋 warn No unpublished projects to publish @example-monorepo/core:publish: 🦋 warn No unpublished projects to publish Tasks: 2 successful, 2 total Cached: 0 cached, 2 total Time: 701ms
packageがprivate: trueだったからです。
diff --git a/packages/core/package.json b/packages/core/package.json index 8b1b54c..cc96e00 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,7 +1,7 @@ { "name": "@example-monorepo/core", "version": "0.0.1", - "private": true, + "private": false, "main": "build/index.js", "types": "src/index.ts", "scripts": { diff --git a/packages/express/package.json b/packages/express/package.json index 1d38dc0..df29381 100644 --- a/packages/express/package.json +++ b/packages/express/package.json @@ -1,7 +1,7 @@ { "name": "@example-monorepo/express", "version": "0.0.1", - "private": true, + "private": false, "main": "build/index.js", "types": "src/index.ts", "scripts": {
今度こそpublish
$ npm run publish > example-monorepo@0.0.0 publish > turbo run publish • Packages in scope: @example-monorepo/core, @example-monorepo/dev-config, @example-monorepo/express • Running publish in 3 packages • Remote caching disabled @example-monorepo/express:publish: cache bypass, force executing 95f6040856482a97 @example-monorepo/core:publish: cache bypass, force executing 304ea4a437f8c0b8 @example-monorepo/express:publish: @example-monorepo/express:publish: > @example-monorepo/express@0.0.1 publish @example-monorepo/express:publish: > changeset publish @example-monorepo/express:publish: @example-monorepo/core:publish: @example-monorepo/core:publish: > @example-monorepo/core@0.0.1 publish @example-monorepo/core:publish: > changeset publish @example-monorepo/core:publish: @example-monorepo/express:publish: 🦋 info npm info @example-monorepo/core @example-monorepo/core:publish: 🦋 info npm info @example-monorepo/core @example-monorepo/core:publish: 🦋 info npm info @example-monorepo/express @example-monorepo/express:publish: 🦋 info npm info @example-monorepo/express @example-monorepo/core:publish: 🦋 warn Received 404 for npm info "@example-monorepo/core" @example-monorepo/express:publish: 🦋 warn Received 404 for npm info "@example-monorepo/express" @example-monorepo/express:publish: 🦋 warn Received 404 for npm info "@example-monorepo/core" @example-monorepo/express:publish: 🦋 info @example-monorepo/core is being published because our local version (0.0.1) has not been published on npm @example-monorepo/express:publish: 🦋 info @example-monorepo/express is being published because our local version (0.0.1) has not been published on npm @example-monorepo/express:publish: 🦋 info Publishing "@example-monorepo/core" at "0.0.1" @example-monorepo/express:publish: 🦋 info Publishing "@example-monorepo/express" at "0.0.1" @example-monorepo/core:publish: 🦋 warn Received 404 for npm info "@example-monorepo/express" @example-monorepo/core:publish: 🦋 info @example-monorepo/core is being published because our local version (0.0.1) has not been published on npm @example-monorepo/core:publish: 🦋 info @example-monorepo/express is being published because our local version (0.0.1) has not been published on npm @example-monorepo/core:publish: 🦋 info Publishing "@example-monorepo/core" at "0.0.1" @example-monorepo/core:publish: 🦋 info Publishing "@example-monorepo/express" at "0.0.1" @example-monorepo/core:publish: 🦋 error an error occurred while publishing @example-monorepo/express: E409 409 Conflict - PUT http://0.0.0.0:4873/@example-monorepo%2fcore - this package is already present @example-monorepo/express:publish: 🦋 error an error occurred while publishing @example-monorepo/express: E409 409 Conflict - PUT http://0.0.0.0:4873/@example-monorepo%2fexpress - this package is already present @example-monorepo/core:publish: 🦋 error npm notice Publishing to http://0.0.0.0:4873 with tag latest and public access @example-monorepo/core:publish: 🦋 error npm ERR! code E409 @example-monorepo/core:publish: 🦋 error npm ERR! 409 Conflict - PUT http://0.0.0.0:4873/@example-monorepo%2fcore - this package is already present @example-monorepo/core:publish: 🦋 error @example-monorepo/core:publish: 🦋 error @example-monorepo/express:publish: 🦋 error npm notice Publishing to http://0.0.0.0:4873 with tag latest and public access @example-monorepo/express:publish: 🦋 error npm ERR! code E409 @example-monorepo/express:publish: 🦋 error npm ERR! 409 Conflict - PUT http://0.0.0.0:4873/@example-monorepo%2fexpress - this package is already present @example-monorepo/express:publish: 🦋 error @example-monorepo/express:publish: 🦋 error @example-monorepo/express:publish: 🦋 success packages published successfully: @example-monorepo/core:publish: 🦋 success packages published successfully: @example-monorepo/express:publish: 🦋 @example-monorepo/core@0.0.1 @example-monorepo/express:publish: 🦋 Creating git tag... @example-monorepo/core:publish: 🦋 @example-monorepo/core@0.0.1 @example-monorepo/core:publish: 🦋 Creating git tag... @example-monorepo/express:publish: 🦋 New tag: @example-monorepo/core@0.0.1 @example-monorepo/core:publish: 🦋 New tag: @example-monorepo/core@0.0.1 @example-monorepo/core:publish: 🦋 error packages failed to publish: @example-monorepo/core:publish: 🦋 @example-monorepo/express@0.0.1 @example-monorepo/express:publish: 🦋 error packages failed to publish: @example-monorepo/express:publish: 🦋 @example-monorepo/express@0.0.1
あー、個別にpublishするとだめなのか。 一応publishできているけど、多分rootに入れれば動くっぽい
rootにchangesetを設定する
$ npm install -D @changesets/cli $ npm run changeset init $ npm run changeset $ npm run changeset version $ npm run changeset publish > example-monorepo@0.0.0 publish > changeset publish 🦋 info npm info @example-monorepo/core 🦋 info npm info @example-monorepo/express 🦋 info @example-monorepo/core is being published because our local version (0.0.2) has not been published on npm 🦋 info @example-monorepo/express is being published because our local version (0.0.2) has not been published on npm 🦋 info Publishing "@example-monorepo/core" at "0.0.2" 🦋 info Publishing "@example-monorepo/express" at "0.0.2" 🦋 success packages published successfully: 🦋 @example-monorepo/core@0.0.2 🦋 @example-monorepo/express@0.0.2 🦋 Creating git tags... 🦋 New tag: @example-monorepo/core@0.0.2 🦋 New tag: @example-monorepo/express@0.0.2
まとめ
- turborepo x changesetsで良さそう
- changesetsはrootに置く
- 必要なパッケージを選択式でpublishできる
- 変更をstackしてまとめてbumpできる
- publishも一括でやってくれる
- パッケージ作成実験にverdaccioは便利