[React.js]monorepo環境を構築する+typescript

[React.js]monorepo環境を構築する+typescript

Reactプロジェクトが2つあり、共通のモジュールをcommonというプロジェクトで集約して使うことを想定してmonorepoベースのプロジェクトを構築します。

monorepoとは

1 つのリポジトリの中に複数のパッケージを同梱するリポジトリの運用方法

モノレポ入門 – Gutenberg が採用するリポジトリ戦略

yarnでmonorepo環境を構築する

yarnでmonorepoを使っていく場合は、

yarn workspace

を使います。

subprojectにパッケージをインストールする時は

yarn workspace subproject-name add package-name

となります。

projectの作成

root,subprojectをcreate-react-appで作っていきます。

# root projectを作る
npm init
# create-react-appをinstall
npm install create-react-app
# sub projectを作る
npx create-react-app packages/project1 --typescript
npx create-react-app packages/project2 --typescript
npx create-react-app packages/common --typescript

root project の設定

ルートプロジェクトのpackage.jsonを修正

以下の設定を追加します。

{
  ...
  "private": true,
  "workspaces": {
    "packages": ["packages/*"],
    "nohoist": ["**/react-scripts", "**/react-scripts/**", "**/@generated", "**/@generated/*"]
  }
  ...
}

project 共通のtsconfig.jsonをルートプロジェクトに作成

tsconfig.jsonを作成します。

{
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  }
}

ここまで

sub projectの設定(project1,project2)

パッケージのインストール

monorepo化に必要なパッケージをインストールします。

yarn workspace project1 add react-app-rewired
yarn workspace project1 add -D customize-cra

yarn workspace project2 add react-app-rewired
yarn workspace project2 add -D customize-cra

package.json修正

以下の設定に修正します。
react-scriptsによる実行コマンドからreact-app-rewiredによる実行に変えてます。

    ```json
    {
      ...
      "scripts": {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build"
      }
      ...
    }
    ```

tsconfig.json修正

以下の設定を追加します。

    {
      "extends": "./tsconfig.path.json",
      ...
    }

tsconfig.path.jsonの作成

tsconfig.path.jsonを作成します。
共通モジュール用のディレクトリを「@common」という名前で認識できるようにします。

    {
      "extends": "../../tsconfig.json",
      "compilerOptions": {
        "baseUrl": "./",
        "paths": {
          "@common/*": ["../common/src/*"]
        }
      }
    }

config-overrides.jsの作成

config-overrides.jsを作成します。

    const { removeModuleScopePlugin, override, babelInclude } = require('customize-cra');
    const path = require('path');

    function addAlias(config) {
      config.resolve = {
        ...config.resolve,
        alias: { '@common': path.resolve(__dirname, '../    common/src') },
      };
      return config;
    }

    module.exports = override(
      addAlias,

      //remove limitations of create-react-app
      removeModuleScopePlugin(),
      babelInclude([path.resolve('src'), path.resolve('../    common/src')])
    );

ここまで(sub projectの中)

sub projectの設定(common)

いらないものを削っていきます。

  • srcディレクトリ配下のソース全部消す
  • publicディレクトリも消す
  • create-react-appコマンドで作られた不必要なファイルを消す

最終的に残るもの

  • srcディレクトリ
  • package.json
  • readme.json
  • tsconfig.json

後始末

各 project のnode_modulesyarn.lockを消して再インストールし直しておきます。

これでmonorepo環境の構築は完了です。

commonのソースをsub projectで使う

common project に共通的に使いたいファイルを作る

common/src/Hello.tsx

    import React, { ReactElement } from 'react';

    interface Props {}

    function Hello({}: Props): ReactElement {
      return <div>view from Common packages!</div>;
    }
    export default Hello;

sub project 内で import する

import Hello from '@common/Hello'で import
project1/src/app.tsx

    import React from 'react';
    import logo from './logo.svg';
    import './App.css';
    import Hello from '@common/Hello';

    function App() {
      return (
        <div className='App'>
          <header className='App-header'>
            <img src={logo} className='App-logo' alt='logo' />
            <p>
              Edit <code>src/App.tsx</code> and save to reload.
            </p>
            <a className='App-link' href='https://reactjs.org' target='_blank' rel='noopener noreferrer'>
              Learn React
            </a>
            <Hello></Hello>
          </header>
        </div>
      );
    }

    export default App;

yarn start

yarn workspace project1 start

下段にcommonモジュールに作成した Helllo.tsx の「view from Common packages!」が表示されています。

関連

SonarQubeとprojectの連携方法(monorepo+React + TypeScript)

参考

yarn workspaceでmonorepo+TypeScript+Lint環境をつくる

React.jsカテゴリの最新記事