turborepo에서 제공하는 with tailwind 옵션을 통해 초기 셋팅을 한다면 tailwind-config가 자동으로 추가되지만 학습 목적을 가지고 기본 셋팅을 통해 추가해 봄.
pnpm dlx create-turbo@latest --example with-tailwind
( 옵션을 통해 추가하는 방법은 위 cli를 입력해주면 됨. 링크)
목적 - 공통으로 쓰일 tailwind config 을 만들어서 각 패키지에 적용시키기
turborepo의 공식 문서에서는 패키지 매니저를 pnpm을 추천하여 pnpm으로 진행
1. turbo 전역 설치
pnpm install turbo --global
2. 초기 셋팅
pnpm dlx create-turbo@latest
위 명령어를 실행하면
packages 와 apps 폴더가 생성되는데
apps는 프로젝트들이 담겨져 있고, packages에는 typescript-config 와 eslint-config, ui 패키지가 기본적으로 셋팅되어져 있다.
tailwind config는 공통으로 쓰일 설정 파일이 될것이므로 packages에 셋팅할것이다.
3. 폴더 셋팅
cd packages
mkdir tailwind-config
cd tailwind-config
터보레포의 각 패키지들은 고유의 package.json을 가지는 것으로 구분되어진다.
4. package.json 셋팅
pnpm init
위 명령어를 실행하면 package.json이 기본 셋팅되어 있는데 패키지 json의 주요 속성에는 name과 exports가 있다.
1 )name에는 각 패키지가 구분되어져야 할 고유의 이름값이 들어간다. 따라서 prefix를 넣어주는 것을 turborepo는 추천함.
"
The name field is used to identify the package. It should be unique within your workspace.
It's best practice to use a namespace prefix for your Internal Packages to avoid conflicts with other packages on the npm registry. For example, if your organization is named acme, you might name your packages @acme/package-name.
We use @repo in our docs and examples because it is an unused, unclaimable namespace on the npm registry. You can choose to keep it or use your own prefix.
"
나는 package.json의 name을 @repo/tailwind-config로 설정함
2 )exports에는 외부 패키지에서 이 패키지의 모듈을 가져올려고 할 때 경로를 셋팅해주는 것이라고 봐도 될 것 같다.
나는 index.ts에 공통으로 쓰일 tailwind config 내용을 담을 것이므로
".": ".index.ts" 라고 셋팅해줬다.
만약 빌드 된 경로를 잡아줄 것이라면 아래처럼 잡아줘야 할 것이다.
{
"exports": {
".": "./dist/constants.ts",
"./add": "./dist/add.ts",
"./subtract": "./dist/subtract.ts"
}
}
3) tailwind config 셋팅을 위한 라이브러리 설치
pnpm add -D tailwindcss tailwindcss-animate typscript @types/node
아래는 내가 셋팅해 둔 package.json의 완성본이다.
{
"name": "@repo/tailwind-config",
"version": "1.0.0",
"private": true,
"exports": {
".": "./index.ts"
},
"devDependencies": {
"@types/node": "^22.10.1",
"tailwindcss": "^3.4.16",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.7.2"
}
}
5. index.ts 생성
content 를 생략하는 이유는 패키지별로 tailwind가 적용 될 범위가 다를 수도 있기 때문에 생략해줌.
content가 비워져 있어서 warn - No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration. 이러한 메시지가 뜰 수 있는데 이게 싫으면 content:[]라고 빈 값을 넣어줘도 될듯하다.
width에 나만의 고유 가로를 줘서 추후에 다른 패키지에서 w-zeroGym이 잘 먹히는지 확인할 것이다.
import type { Config } from 'tailwindcss';
import animate from 'tailwindcss-animate';
const config: Omit<Config, 'content'> = {
darkMode: ['class'],
theme: {
extend: {
width: {
zeroGym: '24rem',
},
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: 'calc(var(--radius) - 4px)',
},
},
},
plugins: [animate],
};
export default config;
6. web 패키지로 이동
( 루트에서 pnpm install 후 pnpm run dev 또는 pnpm run dev --filter web을 입력하여 실행시킬 수 있는데 turbopack을 읽을 수 없다는 에러가 뜸. web과 docs package.json에 dev 옵션으로 --turbopack을 --turbo로 수정해줬더니 실행 잘 됐음 )
기본 셋팅 되어 있는 web 패키지에는 next 15가 설치되어 있을 것이다. 여기에는 tailwind 셋팅도 없을 뿐더러 방금까지 내가 작성한 tailwind-config 가 없기 때문에 이것들을 설치해줘야함.
외부 패키지를 바로 pnpm add 해주면 에러가 떠서 devDependecies에 직접 @repo/tailwind-config:workspace:*를 작성해준뒤 pnpm install 실행함.
7. web에 tailwind 적용해주기
이건 tailwind 문서에 나온 설치법대로 진행하면 됨
pnpm add -D tailwindcss autoprefixer postcss
pnpm dlx tailwindcss init
init을 통해 tawilwind.config.js 가 생성 될텐데 이제 그 안에 @repo/tailwind-config의 config를 넣어주면 된다.
import config from '@repo/tailwind-config';
/** @type {import('tailwindcss').Config} */
export default {
...config,
content: [
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
...config.theme.extend,
},
},
plugins: [],
};
이때 extend안에 config를 풀어주지 않으면 씹혀져서 적용이 안된다.
따라서 꼭 ...config.theme.extend를 넣어주자..
postcss.config.mjs를 생성도 해주자
const config = {
plugins: {
tailwindcss: {},
},
};
export default config;
이제 global.css 최상단에 아래를 추가
@tailwind base;
@tailwind components;
@tailwind utilities;
8. 최종
<div className="bg-blue-400 w-zeroGym">sadasd</div>
width가 384px ( 24rem ) 인 w-zeroGym이 잘 먹힌 것을 확인할 수 있다.