Reactコンポーネントをnpmに公開したい
ゴール
複数のリポジトリで使われる共通のコンポーネントをnpmで公開する
Lerna
複数npmパッケージを一つのリポジトリで管理できるもの
Lernaでpublishする前に当然npmログインしとくこと
lerna init
--independent
それぞれのパッケージでバージョンを個別に管理する
---exact
TODO: exactオプションの説明追記
monorepoでPR中のコードをnpmパッケージとしてcanary releaseするGitHub Actions
independent modeでのリリースフロー
- バージョン更新
- パッケージ公開
- GitHub Release書く
これ使うとGHANGELOGから変更点コピーするの楽だよ
lernaはConventional Commits
でコミットメッセージを書くと自動で次のバージョンを推論してくれる
コミットメッセージのテンプレート
<type>[optional scope]: <description>
[optional body]
[optional footer]
patchになるもの
- fix: A bug fix
minorになるもの
- feat: A new feature
- docs: Documentation only changes
- style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
- refactor: A code change that neither fixes a bug nor adds a feature
- perf: A code change that improves performance
- test: Adding missing or correcting existing tests
- chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
major
BREAKING CHANGE
がtypeかbodyに含まれているもの?
BREAKING CHANGEをコミット文に入力してもmajorアプデはされなかったのでコマンド作った方が良さそう
"versionup:major": "lerna version major --conventional-commits",
lerna version -m "commit message"
でcommit時のメッセージを設定できる(lerna.jsonからでもいける)
lerna run --parallel
とlerna run --stream
の違い
parallelの方は並行して実行
streamは順番通りに実行してくれる
TODO
この記事に記載されてる手順をやってみる
リポジトリ作ってLernaインストールLerna と Yarn Workspacesを共存する設定にするroot直下に必要そうなパッケージ入れる(typescript, eslint, prettier, jest)npmパッケージをLernaで新しく作るtsの関数をnpmに公開するcliをnpmに公開するreact, storybook等コンポーネント開発に必要なパッケージを入れるサンプルのコンポーネント作るnpmにパブリッシュする- CICD入れる
packages間で依存関係作ってみる
やったこと
- リポジトリ作った
- node-versionとかyarn init
yarn add -W --dev lerna
yarn lerna init --independent
- lerna.jsonの設定変更
-
yarn lerna create
でパッケージ作成 - commit messageをConventional Commitsで書く
- packageのcommitしたら
lerna version --conventional-commits
-
npm login
でnpmにログインしとく - 公開するパッケージのpackage.jsonにpublischConfigを追加してaccessをpublicにする(scopedなモジュールの場合)
-
lerna publish from-package
でnpmに公開する
TypeScriptで書いたものをpublishする
- rootに必要なパッケージをインストール
yarn add -W --dev typescript prettier eslint
- rootのtsconfigの設定
- packagesのtsconfigの設定
- typescriptのビルド
-
lerna version --conventional-commits
でpackageのバージョンを上げる -
lerna publish from-package
でnpmに公開する
cliをnpmに公開する
- nodejsで実行するscriptをtsで書く
-
#!/usr/bin/env node
を1行目に追記する
-
- pacakge.jsonのbinにビルド後のscriptのjsファイルのパスを指定する
reactのコンポーネントをnpmに公開する
- 必要なパッケージをrootにインストール
yarn add -W --dev react react-dom @types/react vite @vitejs/plugin-react-refresh vite-react-jsx tailwindcss postcss autoprefixer postcss-nested
- 雛形を作る
yarn create vite p-component --template react-ts
- rootのdevDependenciesに必要なパッケージはインストールしたので、pacakge側のdependenciesは削除
- tailwindcssに必要なpostcss.config.jsとtailwind.config.jsを追加
yarn tailwindcss init -p
- Viteは何の設定もなしにCSS Modulesが書ける
- package.jsonをnpmで公開するように変更
- index.d.tsファイルがビルド後に作成されるように修正する
vite build && tsc -p ./tsconfig.build.json
- 公開したコンポーネントを使う側でスタイルを適応させたければビルド後のcssファイルをimportするようにする
Yarn Workspaces
package.jsonのプロパティ
bin
実行したいスクリプト(cli)を名前をつけて設定できる感じっぽい
{
"bin": {
"myapp": "./cli.js"
}
}
でnpm run-scriptとかからmyappで./cli.jsの内容を実行できそう
main
エントリーポイント
このエントリーポイントで指定されたpathのファイルがexportしたものがpackageとしてexportしたものになる
publishConfig
registry
の設定でnpmjs以外でjsライブラリを管理したい場合に使う
独自の npm registry を使う
files
package.jsonプロパティ全集
参考pacakge
tsdx
tsconfig.json
target
どの動作環境に向けてトランスパイルするか指定する
tsconfig/bases
をみてるとReact、Next.jsでES5
を使っていて、NodejsではそれぞれのバージョンにあったESバージョンを使っている
recommended.json
ではES2015/ES6
が選択されている
Can I UseでみたES6の各ブラウザの対応状況ではIE11が部分的にサポート、Opera Miniがサポートしていない状況
なので、ReactやNext.jsのtsconfigではES5を使ってる感じかな
動作環境として指定できる値
Default:
ES3
Allowed:
ES3 (default),
ES5,
ES6/ES2015 (synonymous),
ES7/ES2016,
ES2017,
ES2018,
ES2019,
ES2020,
ESNext
※トランスパイルとPolyfillの違い
トランスパイル
ある言語で書かれたコードを元に別の言語のコードを生成すること
Polyfill
古いブラウザでは実現できないAPIを、古いブラウザでも同等の機能を使用できるように補うための小さなライブラリのようなもの
module
どのモジュールパターンでTypeScriptをJavaScriptに変換するか指定する
tsconfig/bases
のReactやNext.jsではesnext
が指定されている
(webpackの中でTypeScriptを扱ってる場合はesnext
を指定することでTree Shakingなどの最適化ができる https://gist.github.com/azu/56a0411d69e2fc333d545bfe57933d07)
指定できるモジュールパターン
Allowed:
CommonJS (default if target is ES3 or ES5),
ES6,
ES2015,
ES2020,
None,
UMD,
AMD,
System,
ESNext
lib
TypeScriptには標準であるMathなどの関数の型定義やブラウザで見られるDOMの型定義などがデフォルトで含まれている
状況に応じて使う型定義を変更するときにlibで指定する
tsconfig/bases
ではReactやNext.js環境の場合
"lib": ["dom", "dom.iterable", "esnext"],
が指定されている
ブラウザで使用する型定義と最新のjs apiが使えるesnextを指定している
references
Shopifyでlernaで管理されているモノレポのpacakgeのrootのtsconfigの設定
モノレポの場合、配下の各プロジェクトの依存関係をreferencesで指定できる
composite
参照される(referencesで指定されてるパス直下の)tsconfig.jsonにはcompositeをつける
jsx
指定された値によってどのようにコンパイルされるかはこのexampleで確認する
react-jsx
はreact17から出てきたtransformに対応してる
(import React from 'react';
しなくてよくなったやつ)
react17だけが対象ではなく、一応16.14.0とかにも対応してる
React 17 RC already includes support for the new transform, so go give it a try! To make it easier to adopt, we’ve also backported its support to React 16.14.0, React 15.7.0, and React 0.14.10.
指定できる値
Allowed:
react,
react-jsx,
react-jsxdev,
react-native,
preserve
emitDeclarationOnly
.d.tsファイルだけ出力する
テストの実行環境作る
- 必要なパッケージをroot直下でインストール
yarn add -W --dev jest @types/jest ts-jest
- pacakges配下でjest.config.jsファイルの生成
- scriptsにtestコマンドの追加
共通のlinter formatterの設定をする
ぐぐると色々な思想の設定が出てきすぎるのでシンプルなやつをベースにする
yarn add -W --dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-config-prettier eslint-plugin-prettier
- eslint用のtsconfigを作成する
tsxで作ったReactコンポーネントをnpmで公開する
viteの環境構築ざっくりメモ
- 必要なパッケージをrootにインストール
yarn add -W --dev react react-dom @types/react @types/react-dom @vitejs/plugin-react-refresh vite
- 必要なパッケージは
yarn create vite p-component --template react-ts
で作られたpacakge.jsonに記載されているもの - 全てのパッケージをdevDependenciesに入れたのはshopifyのリポジトリを参考にした
- Lybrary Modeのviteの設定する
- entry point用のindex.tsファイルを作る
- ビルドしてみる
- react17以降のtransformしてくれなかったので、
vite-react-jsx
使う? yarn add -W --dev vite-react-jsx
- react17以降のtransformしてくれなかったので、
- tailwindcssを入れる
-
yarn add -W --dev tailwindcss postcss autoprefixer
-
yarn add -W --dev postcss-nested
(好み)
-
- 該当pacakgeの配下で
yarn tailwindcss init -p
(-pはpostcss.config.jsを自動的に作成するオプション)
-
- css modulesの設定入れる
- pacakge.jsonをnpmで公開するように変更する
- dist配下にd.tsファイルをビルドする
-
Cannot find module './styles.module.css' or its corresponding type declarations.
怒られる - https://github.com/vitejs/vite/issues/2049#issuecomment-799533435
- 上記コメントを参考にbuild用のtsconfigを用意して
vite build && tsc -p ./tsconfig.build.json
にした
-
- いい感じにindex.d.tsもできたが別リポジトリで公開されたパッケージを使ってみるとstyleが当たってない
- tailwindcss使わずにビルドしてもstyle当たらなかったし、ビルド時の問題?
ビルドして、npmに公開したコンポーネントのスタイルは
import { Button } from '@nus3/p-component2'
import '@nus3/p-component2/dist/style.css'
みたく、dist配下のstyle.cssをimportすれば適応される
pacakge間で依存関係を作ってみる
- 別packageをimportする場合はtsconfigの
references
に該当packageのpathを追加 - importされるpackageはtsconfigのcomplilerOptionsにcompositeをtrueで追加する
- 該当pacakgeでyarn add {pacakge-name}してdependencies(or devDependencies)に追加する
referencesて指定するpacakgeのtsconfigでnoEmit
をtrueにするとエラーが出る?
Referenced_project_0_may_not_disable_emit_6310: 参照されたプロジェクト '{0}' は、生成を無効にできません。
Viteのvanilla-tsのtemplateをLibrary modeで試してみる
-
yarn create vite {project-name} --template vanilla-ts
でテンプレートから作成する - vite configをLibrary modeになるようにする
- pacakge.jsonの設定をする
- build用のtsconfig(tsconfig.build.json)の設定する
- yarn devした際に定義した関数の動作が確認できるようにする(console.logするとか)
React Testing Library入れる
CICDをGitHub Actionsで作る
フロー例(azu/lerna-monorepo-github-actions-release)
-
release/
のブランチを作成する - yarn run versionup(git tagは打たない)
- プルリクエスト作成
- プルリクエストのbodyにrelease noteをかく
- プルリクエストのマージ
- git tagの作成・github releaseの作成・npmへのpublish
./lerna.jsonのversionを見てるからindependentではない想定っぽい
shopifyの見てるとrelease全部自動化してないな
release作業は手作業でやってそう
(デプロイに関してはShipitっていう多分自作のツール使ってやってそうだけど)
shopifyのgithub actions
onでpull_requestとpush指定すればciを起動したいタイミングのはできそう
- ciはプルリクエスト作成とかに実行する
- mainでプルリクエストマージ
- mainからreleaseブランチを生やす
- releaseブランチで
lerna version --conventional-commits
して各packageをversion upする - プルリクエストのbodyにrelease noteをかく
- relaseブランチからmainにマージされたらgithubのreleaseを作る + npmへpublishする
TODO: この流れでGitHub Actions作ってみる