MonoRepo란 하나의 저장소에서 여러 컴포넌트 또는 module packages를 가지는 것을 의미합니다. 즉 여러 프로젝트의 코드를 보관하는 단일 저장소입니다. 현재 Google, Facebook 및 Twitter와 같은 대기업이 거대한 코드베이스의 복잡성을 관리하기 위해 선택된 방법들입니다.
아래는 그림은 제가 했던 프로젝트의 모노레포 예시입니다. eagle-web은 웹에 대한 로직 함수가 들어가 있고, web-ui는 ui 컴포넌트, eagle-backend는 nodejs가 들어 있습니다.
Lerna와 Yarn을 같이 사용하는 이유는 각 라이브러리가 잘하는 일이 다르기 때문문입니다.
Lerna는 Monorepo로 구성된 프로젝트 전체를 관리, Yarn은 각 패키지들간의 의존성을 관리합니다.
💡 Lerna로만 관리하고자 할 때 react 프로젝트에서 lerna bootstrap --hoist로 패키지를 설치했을때 리액트 모듈을 중복해서 불러와 에러가 발생하여 많은 블로거들이 yarn과 lerna를 같이 사용하도록 권장합니다새로운 프로젝트 생성
$ mkdir react-monorepo
$ cd react-monorepo
$ yarn init -y
packages
로 가정하였습니다){
"name": "react-monorepo",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"private": true,
"workspaces": ["packages/*"]
}
Lerna 설정
$ yarn add -DW lerna
$ yarn lerna init
{
"packages": ["packages/*"],
"version": "1.0.0",
"useWorkspaces": true,
"npmClient": "yarn"
}
React app 추가
$ yarn create react-app packages/app --typescript
{
name: '@foo/app',
version: '0.1.0',
private: true,
dependencies: {
'@types/jest': '24.0.23',
'@types/node': '12.12.7',
'@types/react': '16.9.11',
'@types/react-dom': '16.9.4',
// ...
},
}
yarn workspace
$ yarn workspace @foo/app start
lerna
$ yarn lerna run start --scope=@foo/app
💡 단일 명령을 사용하고 확인 할 때는 yarn workspace가 좋고, 필터를 사용해서 여러 패키지에 대한 작업을 수행 할 때는 lerna가 좋습니다.
라이브러리 패키지 추가
$ mkdir -p packages/shared
$ cd packages/shared
$ yarn init -y
$ yarn add -D typescript
yarn tsc --init
를 통해 타입스크립트 설정 파일을 생성하고, jsx 옵션과 declaration 옵션을 활성화 후, outDir를 설정하여 빌드 파일이 생성될 위치를 지정합니다.{
"compilerOptions": {
"jsx": "react",
"target": "es5",
"module": "commonjs",
"declaration": true,
"declarationMap": true,
"outDir": "./build",
"strict": true,
"esModuleInterop": true
}
}
{
"name": "@foo/shared",
"version": "1.0.0",
"main": "build/index.js",
"types": "build/index.d.ts",
"files": ["build"],
"license": "MIT",
"devDependencies": {
"typescript": "^3.7.2"
},
"scripts": {
"build": "tsc"
}
}
import React from 'react';
const Foo: React.FC = () => <div>Foo!</div>;
export default Foo;
export { default as Foo } from './Foo';
app 패키지에 shared 패키지 설치
lerna
를 사용합니다.yarn lerna add @foo/shared --scope=@foo/app
import './App.css';
import {Foo} from '@foo/shared'
function App() {
return (
<div className="App">
<Foo></Foo>
</div>
);
}
export default App;
$ yarn workspace @foo/app start
$ yarn workspace @foo/shared build
$ yarn workspace @foo/app start
{
"name": "@foo/shared",
"version": "1.0.0",
"main": "build/index.js",
"types": "build/index.d.ts",
"files": ["build"],
"license": "MIT",
"devDependencies": {
"typescript": "^3.7.2"
},
"scripts": {
"build": "tsc",
"start": "tsc -w"
}
}
$ yarn lerna run start --parallel
계속 위와 같은 에러가 뜰경우, tsconfig.json 파일에
"skipLibCheck": true
위 내용을 추가해주면 에러가 사라집니다.
https://doppelmutzi.github.io/monorepo-lerna-yarn-workspaces/
cy0c.github.io/2019/06/14/monorepo-tutorial/
https://medium.com/@maoberlehner/monorepos-in-the-wild-33c6eb246cb9
https://dev.to/stereobooster/typescript-monorepo-for-react-project-3cpa
https://imch.dev/posts/make-react-app-with-monorepo