こんにちは、木瓜丸です。
最近、関わっている新規のプロダクトや個人開発で、pnpm-workspaceを使っています。 pnpm-workspaceを使うと、monorepoを割と簡単にセットアップできます。
monorepoを使っていると、一つのプロダクトで複数のサイトを配信する時(例えば、管理画面やLPなどを別環境で配信したい時)にコンポーネントを共通化したい時があります。
今回、コンポーネントを共通化させる上で、Sass Modulesを使えるようにするのに軽くハマったため、そのセットアップ方法をまとめておきます。
共通化する上で困ること
コンポーネントを共通化する上で、Sass変数の扱いが課題になります。
例えば、Next.jsでサイト全体で扱うカラーパレットを変数にまとめることがあると思います。 このような時、共通化されたパッケージからもその変数の色を使えなければなりません。
monorepo設計
monorepoのディレクトリ構成は以下の通りです。
.
├── apps
│ └── app1 --> Next.js
├── node_modules
├── package.json
├── packages
│ ├── tsconfig
│ │ ├── package.json
│ │ └── tsconfig.base.json
│ └── ui --> 共通化したコンポーネント
├── pnpm-lock.yaml
└── pnpm-workspace.yaml
apps
配下には、デプロイするパッケージをまとめます。また、packages
にはapps
が依存する共通化したパッケージなどを入れます。
このようにディレクトリを切ることで、触るべきコードが分かりやすくなったり、依存関係が整理されたりすると思います。
今回、扱う共通化されたコンポーネントはui
パッケージから読み込みます。
monorepo管理を行うため、pnpm-workspace.yaml
にパッケージ一覧を書いておきましょう。
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
Next.jsからuiを使う
さて、Next.jsからui
パッケージを読み込むため、まずは依存関係を定義しましょう。
{
...
"dependencies": {
...
"ui": "workspace:*"
}
}
これに加え、Next.jsから他のパッケージのtsxを読むためにはnext.config.js
を書き換える必要があります。
transpilePackages
にui
などpackages
配下のパッケージ名を書きましょう。
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["ui"],
}
module.exports = nextConfig
共通のSass変数もuiパッケージに入れちゃう
上記のapp1
で使う変数をui
でも使う...というのは多分良くないので、ui
に使い回す全ての変数を定義してapp1
から読み込みます。
/* packages/ui/colors.scss */
$primary: #ffb3d9;
$base: #444444;
$text: #ffffff;
app1
側のSassでは、先頭に~
を付けることによって、他のパッケージからscssを読むことができます。
/* apps/app1/src/app/global.scss */
@import "~ui/colors.scss";
これで、Sass変数も共通化することができました。
まとめ
今回は、Sassを使ったコンポーネントを共通化してNext.jsで使い回す方法を書きました。
CSS in JSだと割と簡単にデザインを共通化することができますが、Sass Modulesではどのようにするべきかあまりシェアされていない気がしたので、お役に立てればいいなと思っています。
今後、共通化したコンポーネントでWasmやAudio Workletを使う方法を模索する予定なので、まとまったらそれも記事にしようと思います。