【Vercel】Monorepoでコンポーネントプロジェクトを作る方法

2021-11-25

今回のやり方がまったく正しい保証はありません。

あくまで「動いた」に過ぎないので、十分気をつけて参考にしてもらえればと思います。


前提

  • npm Workspaces
  • Next.js
  • Vercel

Next.js は問いません。

サンプル

workspace-test

消しちゃったら申し訳ないです。

ソースコード

サイト側の package.json

{
  ...,
  "dependencies": {
    ...,
    "piyo": "../piyo/dist/",
    ...,
  },
  ...,
   "scripts": {
    "preinstall": "cd ../piyo && npm i && npm run build && cd ../hoge",
  },
  ...
}

ここの書き方がすでに怪しいです。

preinstall については Vercel 上で deploy を行う際にライブラリー側で install と build が必要なのでこんな書き方になっています。

多分もっと良い書き方があると思います。

サイト側のコンポーネント

import Piyo, { PiyoProps } from "piyo";
import React from "react";

type MogeProps = Pick<PiyoOneProps, "piyo">;

function Moge({ piyo }: MogeProps): JSX.Element {
  return <Piyo piyo={piyo} />;
}

export default Moge;

よしなにです。

ライブラリー側の package.json

{
  "dependencies": {
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
  "devDependencies": {
    "@types/react": "17.0.36",
    "typescript": "4.5.2"
  },
  "main": "dist/index.js",
  "name": "piyo",
  "private": true,
  "scripts": {
    "build": "rm -rf dist && tsc",
    "build:watch": "rm -rf dist && tsc --watch"
  },
  "types": "dist/index.d.ts",
  "version": "1.0.0"
}

ここらへんも合っているのかあまり自信がないです。

ライブラリー側の tsconfig.json

{
  "compilerOptions": {
    "declaration": true,
    "declarationMap": true,
    "esModuleInterop": true,
    "jsx": "react",
    "lib": ["es2017", "dom"],
    "outDir": "dist",
    "sourceMap": true
  },
  "include": ["src/index.ts"]
}

最低限にとどめています。

懸念事項

  • watch モードで実行すると dist の中身が荒れる
  • 複数のコンポーネントを export した場合に import 先のパスが複数設定可能になってしまう
  • 全体的に汚い

『こんなので動くのか』と思いますが、意外とすんなり動くのでびっくりしました。

開発時は watch モードで起動するとホットリロードが効くので、開発的に困ることはそこまでないのかなと。

とはいえおそらく実装的にはよくないところもかなり多いと思うので、少しずつ綺麗にしていきたいです。