pnpm workspace with React TS & TailwindCSS (1)

Jimin Lee·2023년 5월 7일
2

monorepo

목록 보기
2/3

pnpm workspaces를 사용하여 React TS & tailwindcss를 적용해보자.

monorepo 설정

구조 설계

프로젝트마다 다르지만 보통 두 타입의 구조가 존재한다고 한다.

  • package centric
    오픈소스 코드(Angular, React, Vue 등)에서 자주 사용하는 구조로 재사용가능한 패키지를 개발/배포하는데 중점이 둔다. 보통 package 폴더가 있고 npm과 같은 public registry에 게시되는 것이 특징이다.
  • app centric
    기업에서 일반적으로 사용하는 구조로, 어플리케이션이나 제품의 개발이 주 목적이다. apps, package, libs 폴더를 가지며 apps는 빌드/배포되는 어플리케이션이, package 혹은 libs는 모노레포안에서 개발되는 어플리케이션들의 라이브러리를 내포한다. 이 라이브러리들 역시 public registry에 게시 가능하다.

나는 서비스 개발이니까 후자를 선택한다. 하지만 폴더명은 변경가능하므로, apps 대신 projects를 사용할 것이다.
projects에는 실제 서비스가 담긴 프로젝트들: app, admin
packages에는 공통으로 사용되는 프로젝트들: component, tailwind-config을 위치시킬 계획이다.

tailwind-config는 공통 스타일 토큰이, component에는 tailwind-config를 사용한 공용 컴포넌트를, 그리고 projects 하단의 어플리케이션은 공용 컴포넌트를 가져다 쓸 계획이다.



pnpm 설치 및 시작

시작에 앞서 pnpm이 없다면 설치해주자. pnpm 설치
npm이 있다면 간단하게 설치할 수 있다.

npm install -g pnpm

그리고 프로젝트 디렉토리를 만들고, 디렉토리 안에서 다음 명령어를 통해 프로젝트를 초기화한다.

pnpm init

이제 package.json이 생성되었다.



workspace 설정파일

프로젝트 루트에 projects/ 폴더와 packages/ 폴더를 생성한다.

mkdir projects packages

프로젝트 루트에 pnpm-workspace.yaml을 생성한다. 공식 문서
packages 하단에 구조설계에서 정한 폴더명을 적어준다.

# pnpm-workspace.yaml
packages:
  - "projects/*"  # executable/launchable applications
  - "packages/*"

package.json에도 workspaces를 추가한다. 구조설계에서 정한 폴더명을 넣는다.

{
	// 추가
	"workspaces": [
		"projects/*",
		"packages/*"
	],
}

각 프로젝트 설정

이제 packages와 projects 하단에 프로젝트들을 셋팅해준다. 리액트, NextJS, Angular 무엇이든 상관없다.
나는 tailwindcss + React TS를 사용할 예정이다.

1. eslint, prettier 설정

공통으로 설정안해도 되긴 한데 모든 프로젝트에 동일하게 적용됐으면 해서 프로젝트 루트에 설정한다.

$ pnpm add -D eslint eslint-config-prettier eslint-plugin-prettier prettier

2. tailwind-config 생성

tailwind-config를 먼저 생성한다. packages > tailwind-config에 들어가서 pnpm init을 진행한다. (직접 package.json을 만들어도 된다.)
name에 구분을 위해 @packages를 붙여주었다.
// packages > tailwind-config >package.json

{
	"name": "@packages/tailwind-config",
	//...
}

이제 tailwindcss를 설치한다. 가이드대로 따라하면 된다.

pnpm add --filter @packages/tailwind-config tailwindcss postcss autoprefixer -D
pnpx tailwindcss init

postcss.config.js 생성

const config = require('./tailwind.config.js');
module.exports = {
	plugins: {
		tailwindcss: { config },
		autoprefixer: {},
	},
};

tailwind.config.js 설정

module.exports = {
  content: ['**/*.{js,ts,jsx,tsx}', '**/*/index.html'],
  theme: {
    extend: {},
  },
  plugins: [],
}



3. component 생성

이제 tailwind-config를 사용할 component 설정을 해준다.
packages 하단에 vite를 사용하여 ReactTS로 초기화를 진행해준다.

# packages > component
pnpm create vite . --template react-ts 

component에 tailwindcss 의존성을 추가한다.

// package.json

{
	"name": "@packages/component",
  	// ...
	"devDependencies": {
		"@packages/tailwind-config": "workspace:^0.1.0",
      // ...
    }
}

tailwind.config.cjs

module.exports = require('@packages/tailwind-config/tailwind.config.js');

postcss.config.cjs

module.exports = require('@packages/tailwind-config/postcss.config.js');


4. app 생성

루트 폴더에 projects > app을 생성하고 component와 마찬가지로 vite를 이용해서 react를 셋팅한다.

# projects/app/
pnpm create vite . --template react-ts

app > package.json 설정

{
	"name": "@projects/app",
	// ...
	"devDependencies": {
      	"@packages/tailwind-config": "workspace:^0.1.0",
		"@packages/component": "workspace:^0.0.0",
		// ...
	}
}

5. 루트 package.json에 명령어 추가

"scripts": {
		"build:comp": "pnpm --filter @packages/component build",
		"dev:comp": "pnpm --filter @packages/component dev",
		"dev:app": "pnpm --filter @projects/app dev"
	},



테스트

component에서 tailwind-config가 호출되는지 확인해보기 위해 tailwind-config에 공통 스타일을 추가해본다.

packages>tailwind-config>tailwind.config.js

module.exports = {
	content: ['**/*.{js,ts,jsx,tsx}', '**/*/index.html'],
	theme: {
		extend: {
			colors: {
				main: '#414066',
			},
		},
	},
	plugins: [],
};

버튼에 적용해본다.

// Button.tsx
export function Button(props: any) {
	return (
		<button onClick={() => props.onClick()} className="bg-main">
			{props.children}
		</button>
	);
}
export default Button;

잘된다.

참고

https://blog.nrwl.io/setup-a-monorepo-with-pnpm-workspaces-and-speed-it-up-with-nx-bc5d97258a7e
https://dev.to/soom/building-a-monorepo-with-pnpm-workspace-1544
https://github.com/ashleydavis/pnpm-workspace-examples
https://dev.to/ynwd/how-to-setup-react-shared-components-in-monorepo-with-tailwind-webpack-and-npm-workspace-570n
https://github.com/mihailtd/demo-monorepo (vue + tailwindcss)

0개의 댓글