이전에 사이드 프로젝트를 진행하면서, 특정 UI 옆에 tooltip 말풍선 을 출력하는 형태의 React 컴포넌트를 개발해본적이 있습니다.
언젠가는 이걸 라이브러리화 해서 npm 에 배포해보자는 생각이 있었는데, 이번에 기회가 되서 한번 진행해보려고 합니다.
그 과정에서 프로젝트 세팅 부터, 배포된 패키지의 개발 과정과 경험 등도 같이 블로그에 작성 해볼까 합니다.
먼저 npm 에 내가 만든 패키지를 배포하기위해 프로젝트를 세팅하고, 개발환경을 설정 해야겠죠? 저는 React 와 Next 환경에서 import 해온 custom hook 과 component 를 사용할수 있도록 패키지화 하고 싶습니다. 아마도 배포후에도 계속 업데이트를 할것이므로, 개발또한 계속 가능해야합니다. 그래서 아래와 같이 세팅을 하도록 준비했습니다.
- package maneger : pnpm
- bundler : vite
- transfiler : swc
- target : react, next
- test : jest, react-testing-library, cypress
- typescript, eslint, husky
제가 프로젝트를 세팅한 과정을 까먹지않고, 경험을 공유하기위해 모든 과정을 기록 해보았습니다.
프로젝트 세팅 가이드를 따라 해보실분들은 제 입맛대로, 제가 원하는 프로젝트를 만들기위해 설정 한것이므로 굳이 똑같이 하지 않으셔도 괜찮습니다.
1. 프로젝트 초기화
먼저 자신이 사용하는 패키지 매니저에 맞게 init 을 해주어야 합니다. 저는 pnpm 을 좋아하므로, pnpm 을 기준으로 해보겠습니다
npm 을 사용하게되면 이것저것 물어보는데, 각 프롬프트에 맞게 입력하거나 모두 enter 을 입력해서 지나가도 괜찮습니다.
pnpm init
깃헙에서 레포를 먼저 생성하고 왔다면, 아래와 같이 package.json 이 생겨납니다. init 명령어를 사용하지 않고 package.json 을 직접 생성하셔도 괜찮습니다.
2. React 와 Vite 설치
vite 는 webpack 과 같은 모듈 번들러로, webpack 을 사용해도 되지만 저는 vite 를 사용해서 해볼까 합니다.
사용해보면 꽤 가볍고 빠르다는 느낌이 와닿는 번들러 같습니다. vite 에 대한 자세한 내용은 다음에 다뤄보겠습니다.
pnpm add react react-dom
pnpm add -D @types/react @types/react-dom
pnpm add -D vite @vitejs/plugin-react
이렇게 되면 아래와 같이 파일이 몇가지 생겨나고, package.json 에 dependency 가 추가됩니다.
3. Vite 설정
이제 vite 설정을 다루는 config 파일을 만들어야합니다. 저는 타입스크립트를 주로 사용하기 때문에 타입스크립트로 설정하도록 하겠습니다.
프로젝트의 루트에 vite.config.ts 를 만들고, 다음과 같이 코드를 입력해줍니다.
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import type { UserConfig } from "vite";
export default defineConfig(({ command }): UserConfig => {
if (command === "build") {
return {
plugins: [react()],
build: {
outDir: "lib",
lib: {
entry: "src/index.ts",
name: "...", // 자신의 패키지명 입력
formats: ["cjs"],
fileName: "index",
},
minify: false,
rollupOptions: {
external: ["react", "react-dom"],
output: {
globals: {
react: "React",
"react-dom": "ReactDOM",
},
},
},
},
};
} else {
// 개발 환경 설정 등이 필요한 경우 추가
return {
plugins: [react()],
};
}
});
4. 타입스크립트 설정
타입스크립트도 사용할 것 이니 타입스크립트 설정도 해보도록 하겠습니다. 먼저 타입스크립트를 dev dependency 로 추가하고 설정 파일을 만들어, vite 와 react 환경에 맞게 설정해보도록 하겠습니다. 아래는 제가 주로 사용하는 설정이니 참고만 하시고 프로젝트에 맞게 설정 해주시면 됩니다.
보통 따로 지정 하지 않으면 tsc 범위에 대부분 잡히게 되니, 컴파일 하지 않을 파일들을 exclude 배열안에 추가하였습니다.
추가로 여기서는 소개하지 않지만, jest 와 react-testing-library 를 타입스크립트 환경에서 사용시 compilerOptions 안의 types 배열에 추가로 등록 해야합니다.
pnpm add -D typescript
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"useDefineForClassFields": true,
"isolatedModules": true,
"noImplicitAny": true,
"strictNullChecks": true,
"downlevelIteration": true,
"incremental": true,
"useUnknownInCatchVariables": false,
"jsx": "react-jsx",
"types": ["vite/client", "jest", "@testing-library/jest-dom"],
"declaration": true,
"composite": true,
"outDir": "lib"
},
"include": [
"src",
"**/*",
"**/*.ts",
"**/*.tsx",
"src/app.tsx",
"src/index.tsx"
],
"exclude": [
"node_modules",
"lib",
"src/__tests__",
"**/*.spec.ts",
"**/*.spec.tsx",
"**/*.config.ts",
"**/*.build.js",
"jest.config.js",
"jest.setup.ts",
"src/temp.tsx"
],
"references": [{ "path": "./tsconfig.node.json" }]
}
아래는 tsconfig.node.json 파일 설정입니다. TypeScript 컴파일러에게 Node.js 환경에서 실행되는 프로젝트의 구성을 알려주는 파일입니다. 이 파일은 기본 tsconfig.json 파일을 확장하고 Node.js에 특화된 설정을 적용합니다.
// tsconfig.node.json
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
5. ESLint 설정
eslint 도 같이 설정해보도록 하겠습니다. 앞으로 계속 개발해 나갈 예정이고, 개발환경에서 에러를 줄이고 몇가지 필요한 코드스타일을 위해 추가했습니다.
pnpm add -D eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin
다음은 .eslintrc.json 파일을 만들어 설정을 추가해보겠습니다. 이것도 제가 주로 사용하는 설정이니, 참고만 하시고 프로젝트에 맞게 설정 해주시면 됩니다.
// .eslintrc.json
{
"root": true,
"env": {
"browser": true,
"es6": true,
"node": true,
"jest": true
},
"globals": {
"JSX": true,
"React": true
},
"plugins": ["react", "@typescript-eslint", "prettier", "import"],
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"next",
"next/core-web-vitals"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": "latest",
"sourceType": "module"
},
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"@typescript-eslint/no-unsafe-call": "warn",
"@typescript-eslint/no-unsafe-return": "warn",
"@typescript-eslint/no-unsafe-argument": "warn",
"@typescript-eslint/no-unsafe-member-access": "warn",
"@typescript-eslint/no-empty-function": "warn",
"@typescript-eslint/no-unsafe-assignment": "warn",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/no-misused-promises": "off"
}
}
추가로, 저는 빌드된 js 파일이나 필요없는 파일에 eslint 를 사용하고싶지 않으니, .eslintignore 파일을 추가해서 무시하도록 하겟습니다.
// .eslintignore
/dist
*.js
/unused
6. SWC 설정
SWC 는 Babel 과 대응되는 컴파일러로, 트랜스파일링을 수행해줍니다. 속도가 빨라 주목받는 트랜스파일러로, 저같은 경우 패키지 배포시에는 컴포넌트와 훅만 배포하고, 프로젝트 내에서 따로 테스팅을 하기 위해서 추가햇습니다. 보통은 이과정이 필요하지 않을듯 합니다.
pnpm add -D @swc/core
다음은 .swcrc 를 추가해 설정을 합니다.
{
"$schema": "https://json.schemastore.org/swcrc",
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": true,
"dynamicImport": true
},
"transform": {
"react": {
"runtime": "automatic"
}
}
},
"module": {
"type": "commonjs",
"strict": false,
"strictMode": true,
"lazy": false,
"noInterop": false
},
"env": {
"targets": {
"chrome": "79"
},
"mode": "entry",
"coreJs": "3.22"
},
"sourceMaps": true,
"minify": true
}
그다음, vite 에서 번들링 할때 swc 를 사용해서 빌드될수 있도록, vite 설정을 수정 하겠습니다. 먼저 아래 명령어를 입력해서 추가 패키지를 설치합니다.
pnpm add -D @vitejs/plugin-react-swc
pnpm remove @vitejs/plugin-react
vite.config.ts 파일을 수정합니다.
// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc"; // 이곳을 수정합니다.
import type { UserConfig } from "vite";
...
7. Husky 설정
다음은 커밋시에 lint 체크를 도와주는 husky 를 설정해보겠습니다. husky 는 git hook 을 이용하여 특정 git command 이벤트에 실행할 동작을 추가할수 있게 해줍니다.
먼저 husky 를 설치합니다.
pnpm add -D husky lint-staged
다음은 husky 를 실행시켜 git hook 폴더를 생성해줍니다.
npx husky install
.husky 폴더가 생성되면, packages.json 에 다음 내용을 추가합니다.
// package.json
...
"scripts": {
...
"lint-staged": "lint-staged",
...
},
"husky": {
"hooks": {
"pre-commit": "eslint --fix && prettier --write"
}
},
"lint-staged": {
"./**/*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write"
]
},
...
다음은 pre-commit 이 실행될때 동작할 커맨드를 등록해야합니다. 아래와 같이 명령어를 입력해줍니다.
npx husky add .husky/pre-commit "pnpm lint-staged"
이렇게 개발환경 세팅을 모두 마쳤습니다 !
테스트 코드 환경설정이나 프로젝트 내에서 리액트 어플리케이션 개발서버를 띄우는 과정은 생략이 되었는데요, 다음에 추가로 작성해보도록 하겠습니다.
다음 포스트에서는 어떻게 리액트 컴포넌트와 커스텀 훅 등을 넣고, 빌드해서 npm 에 배포하는지 과정을 적은 내용을 작성하도록 하겠습니다.
만약 이 가이드를 따라 패키지 배포과정을 해보고 계시다면, 아래 포스트도 같이 참고해주세요 !
npm 에 내가만든 패키지 배포하기 - (1) : React 컴포넌트와 Custom Hook 을 패키지로 만들기
지난 포스팅에 이어서 이번에는 어떻게 리액트 컴포넌트와 커스텀 훅 코드를 패키지 형태로 배포하는지 그 과정을 공유 해볼까합니다. 만약 패키지를 배포 하기위해 개발환경 세팅부터 해야한
yoonocean.tistory.com
'npm' 카테고리의 다른 글
npm 에 내가만든 패키지 배포하기 - (2) : github action 을 이용한 ci/cd 워크플로우 자동화 (0) | 2023.04.19 |
---|---|
npm 에 내가만든 패키지 배포하기 - (1) : React 컴포넌트와 Custom Hook 을 패키지로 만들기 (0) | 2023.04.17 |