前回までのあらすじ
前回はnpm workspaces
に再入門したうえで、Turborepo
との違いを確認した。
今回はnpm workspaces
とpnpm workspaces
の違いを見ることにする。
特に共通で使っているモジュールをうまくバンドルしてくれるか否かに着目する。
pnpm workspacesを構築していく
pnpm
でプロジェクトを作る。
pnpm init
package.json
が出来上がったら、pnpm
以外のパッケージコマンド(npm
, yarn
)を禁止する設定を入れる。package.json
と.npmrc
ファイルに以下のように記述する。
{ "name": "pnpm-workspaces", "version": "1.0.0", "description": "", "main": "index.js", "engines": { "pnpm": "10.7.1", "npm": "please_use_pnpm_instead" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "packageManager": "pnpm@10.7.1"}
engine-strict=true
次にworkspaceの設定をする。pnpm
の場合はpnpm-workspace.yaml
にワークスペースを定義する。
packages: - 'packages/*'
前回と同じくa
=ofetch
, b
=axios
でGitHubのissueを取得する。pnpm
にはworkspaceを指定するオプションがないので、-F
で特定のパッケージを絞るコマンドを用意するといろいろ捗る。
{ "name": "pnpm-workspaces", "version": "1.0.0", "description": "", "main": "index.js", "engines": { "pnpm": "10.7.1", "npm": "please_use_pnpm_instead" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "a": "pnpm -F \"a\"", "b": "pnpm -F \"b\"" }, "keywords": [], "author": "", "license": "ISC", "packageManager": "pnpm@10.7.1"}
packageをそれぞれa
, b
として用意。
TypeScriptを使えるようにする。
pnpm add typescriptnpx tsc --init
ルートのpackage.jsonに入った。
a
にofetch
を追加してみる。
pnpm a add ofetch
packages/a
にnode_modules
が出来上がった。
比べてもこの通り。
引き続きb
にaxios
、プロジェクト全体にzod
を入れて前回の記事と同じ状況を作る。ソースは前と同じものをコピペして持ってきている。
pnpm-workspaces % pnpm b add axiospnpm-workspaces % pnpm add zod
jsにトランスパイルする。
pnpm-workspaces % tsc
と、各ディレクトリにjsを吐き出してくれた。
中を見てみる。
"use strict";var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); });};Object.defineProperty(exports, "__esModule", { value: true });const ofetch_1 = require("ofetch");const types_1 = require("../types");const fetchIssue = () => __awaiter(void 0, void 0, void 0, function* () { const url = "https://api.github.com/repos/unjs/citty/issues?state=open"; const data = yield (0, ofetch_1.ofetch)(url, { method: "GET", headers: { Accept: "application/vnd.github.v3+json", }, }); const issues = data; console.log("Fetched issues:", issues); const parsedIssues = issues.map((issue) => (0, types_1.parseGitHubIssueResponse)(issue)); console.log("Parsed issues:", parsedIssues);});fetchIssue();
pnpm
の場合、node_modules
はそれぞれのディレクトリにできるのでこれでよい。が、packages
以下のディレクトリで結局ルートにinstallしてる依存関係を使うためには結局バンドルしてあげないとダメそう。
ということで、pnpm
を使ってもやはりバンドラがないとモノレポとしてうまく機能しなさそうだ。
結論
- ワークスペース機能は、ベースとして使いたいパッケージマネージャに依存する
- npmでもpnpmでも依存関係を切り分けて管理できることには違いない
ts
をjs
に吐き出してるのはtsc
。だから、パッケージマネージャがそこをいい感じに書き換えたりとかはするわけない。当たり前のことだ。