React
create-react-app
AtomicDesign
PearDay 6

Reactで複数のプロジェクトで共通のコンポーネントを扱う方法[create-react-app]


TL;DR


  • ReactでAtomicDesignなどを採用していて、コンポーネントを再利用性を加味しながら作成していて、複数のプロジェクトで共通のコンポーネントを使いたい場合がある。(e.g. User用Admin用を別のプロジェクトとして作成し、共通のコンポーネントを扱う、等)


  • create-react-appでプロジェクトを始めた場合はデフォルトの設定では難しいため、不可逆な操作であるyarn eject (or npm run eject)を行い、手動で設定を行うことで実現した。
    movie.gif


Pros & Cons


Pros


  • create-react-appの恩恵を受けれる(簡単に構築できる)

  • ホットリロードしてくれるので、共通コンポーネントの修正などが爆速でできる


Cons


  • monorepoな構成になるため、はじめてコードを見た人にとっては威圧的になる

  • 複数プロジェクトを同一のpackage.jsonで管理するため、複数のプロジェクトで同一のパッケージを使う場合はバージョンを揃える必要がある


  • npm run ejectを行うため、create-react-appのバージョンアップに追従できない


方法


  1. yarn eject


  2. config/paths.jsを編集


  3. src/,public/のディレクトリ構成を修正


  4. package.jsonを編集


前提

create-react-app ( ver1.3.1 )

サンプル(Github)

commit


1. yarn eject

$ yarn eject

 注意このコマンドを実行すると(git操作以外では)元に戻すことができなくなります


2. config/paths.jsを編集


paths.js

 ~ 省略 ~ 

// デフォルトは'user' 
const ENTRY_NAME = process.env.ENTRY_NAME || 'user' //追加

module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp('build/' + ENTRY_NAME), //
appPublic: resolveApp('public/' + ENTRY_NAME), //
appHtml: resolveApp(`public/${ENTRY_NAME}/index.html`), //  編集
appIndexJs: resolveModule(resolveApp, `src/${ENTRY_NAME}/index`), //
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
publicUrl: getPublicUrl(resolveApp('package.json')),
servedPath: getServedPath(resolveApp('package.json')),
};



3. src/, public/のディレクトリ構成を修正

config

scripts
public
index.html
favicon.ico
manifest.json
src
index.js
index.css
package.json

config

scripts
public
admin
index.html
favicon.ico
manifest.json
   user  
index.html
favicon.ico
manifest.json
src
admin
index.js
index.css
user
index.js
index.css
shared
MySharedComponent.jsx
package.json


4. package.jsonを編集


package.json

  "scripts": {

"start": "node scripts/start.js",
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"start:admin": "ENTRY_NAME='admin' node scripts/start.js",
"build:admin": "ENTRY_NAME='admin' node scripts/build.js",
"test:admin": "ENTRY_NAME='admin' node scripts/test.js"
},