DEV Community

Cover image for Building a Monorepo with pnpm Workspace
soom
soom

Posted on • Updated on

Building a Monorepo with pnpm Workspace

Abstract

Introducing the Monorepo Approach through pnpm Workspace.

Multi Repo, Mono Repo, Micro Frontend Architecture 등 최근에는 효율성을 높이기 위한 다양한 접근 방법이 소개되고 있다.

본 포스팅에서는 pnpm workspace 릁 통해 간단한 Monorepo 구조를 구현해 보겠다.

p.s 지난번 dev.to 쪽 이슈로 글이 날아가버려서 다시 쓰는 내용이기 때문에 기억이 잘 나지 않아 아쉽다.
역시 백업은 중요한 것


Getting Started

Prerequisite

  • pnpm global 설치가 필요
Terminal
# Node Version <16.14
npm install -g pnpm

# Node Version >16.17
corepack enable

corepack prepare pnpm@latest --activate
Enter fullscreen mode Exit fullscreen mode

Set Project Structure

프로젝트 구조를 구성해보자

├── packages/
│   ├── app/
│   └── common/
├── package.json
└── pnpm-workspace.yaml
Enter fullscreen mode Exit fullscreen mode

파일 생성 뒤 다음과 같이 작성

/package.json
{
    "name": "@soom/root",
    "private": true,
    "scripts": {
        "preinstall": "pnpm dlx only-allow pnpm"
    },
    "workspaces": ["packages/*"],
    "engines": {
        "node": ">=16.14.2",
        "pnpm": ">=7.9.0"
    },
    "packageManager": "pnpm@7.9.0",
    "devDependencies": {
        "pnpm": "^7.9.0"
    }
}
Enter fullscreen mode Exit fullscreen mode
/pnpm-workspace.yaml
packages:
  - 'packages/*'
Enter fullscreen mode Exit fullscreen mode

packages/app/ packages/common/ 폴더 안에 리액트 프로젝트를 생성

여기서는 vite 를 통해 생성

pnpm create vite .
Enter fullscreen mode Exit fullscreen mode

Setting Common Component

먼저 packages/common/ 폴더 쪽에 다음과 같이 Button Component를 생성

packages/common/src/components/Button.tsx
import type { FC, PropsWithChildren } from 'react';

interface Props extends PropsWithChildren {
    textColor: string;
}

const Button: FC<Props> = (props) => {
    return <button style={{ color: props.textColor }}>{props.children}</button>;
};

export default Button;
Enter fullscreen mode Exit fullscreen mode

main.tsx 에서 방금전 생성한 Button Component 를 export

packages/common/src/main.tsx
import Button from './components/Button';

export { Button };
Enter fullscreen mode Exit fullscreen mode

package.json을 다음과 같이 수정

packages/common/package.json
{
    "name": "@soom/common",
    "type": "module",
    "main": "./src/main.tsx",
    ...
}
Enter fullscreen mode Exit fullscreen mode

Run App with Imported Shared Component

이제 app 폴더로 가서 package.json 을 다음과 같이 수정 후 패키지 설치 재실행

packages/app/package.json
{
    "name": "@soom/app",
    "private": true,
    "type": "module",
    ...
    "dependencies": {
        "@soom/common": "^0.0.0",

    },
    ...
}
Enter fullscreen mode Exit fullscreen mode

패키지 설치

pnpm install
Enter fullscreen mode Exit fullscreen mode

App.tsx 에서 좀전에 설치한 @soom/common 패키지를 이용해 버튼을 import

packages/app/src/App.tsx
import './App.css';
import { Button } from '@soom/common';

function App() {
    return (
        <div className='App'>
            <h1>Monorepo Button?</h1>

            <Button textColor='red'>Hello Common Package Button</Button>
        </div>
    );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

app 폴더에서 프로젝트 실행

이제 common 프로젝트의 버튼이 무사히 app 프로젝트에 적용이 된것을 확인할 수 있다.

pnpm dev
Enter fullscreen mode Exit fullscreen mode

Result

👉 CodeSandBox Sample Link

Result


➕ P.S

마지막으로 monorepo 루트 폴더에서 직접 app폴더에 접근하지 않고 구동시키기 위해서 root 폴더의 package.json에 다음과 같이 스크립트를 사용할 수 있다.

package.json
{
    "name": "@soom/root",
...

    "scripts": {
        "preinstall": "pnpm dlx only-allow pnpm",
        "dev:app": "pnpm --filter @soom/app dev"
    },

...
}

Enter fullscreen mode Exit fullscreen mode
Terminal
pnpm dev:app
Enter fullscreen mode Exit fullscreen mode

Conclusion

pnpm workspace 를 이용해서 monorepo 를 구성해보았다.
이 프로젝트에 turborepo, lerna 등을 이용해 다양한 관리를 할 수 있다.
monorepo를 구성하는 방법은 여러가지가 있지만 개인적으로 pnpm workspace를 이용하는 방법이 가장 가볍고 직관적이었다.

pnpm 의 자세한 내용은 하기 링크를 참고.
https://pnpm.io/ko/

Monorepo Tool에 대한 자세한 내용은 하기 링크를 참조.
참고 링크: https://monorepo.tools/

Top comments (3)

Collapse
 
devnyang profile image
Dok6n

정말 감사합니다~~

Collapse
 
daehyunthevc profile image
daehyun • Edited

기존의 pnpm을 이용한 monorepo 구성 포스트가 다른 포스트로 덮어졌네요. 기존 글은 어디서 볼 수 있을까요?

Collapse
 
soom profile image
soom

글 자체는 dev.to 문제로 날아갔다고 하네요 ㅠㅠ
복구가 어렵다고해서 해당하는 내용 다시 포스팅 했어요