개발
typescript react npm 라이브러리 개발을 위한 환경 설정
배우겠습니다
2024. 12. 28. 22:53
모노레포
어떤 라이브러리를 개발하고 그 결과를 테스팅하기 위해 모노레포를 사용한다.
필자는 pnpm을 사용한다. pnpm monorepo는 pnpm-workspace.yaml
로 설정할 수 있다.
packages:
- "packages/*"
- packages에 각각의 패키지(테스팅, 라이브러리)를 개발하기위해 위 내용을 작성한다.
- packages/example에 테스팅 용도 예제를 개발한다.
- packages/(library)에 라이브러리를 개발한다.
package.json
라이브러리 패키지의 package.json을 설정한다.
{
"name": "unique-lib-name",
"version": "1.0.0",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/types/index.d.ts",
"files": [
"dist",
],
"scripts": {
"build": "rollup -c"
},
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
...
- name엔 배포하고자 하는 라이브러리 이름이다. npm에 중복된 라이브러리가 존재해선 안된다.
- version은 라이브러리 버전이다. 처음이므로 1.0.0이다. 업데이트할때마다 올려야한다.
- main은 commonjs 시스템에서 라이브러리를 require할때 필요한 파일 경로를 설정한다. (esm으로만 사용하고자하면 당연히 필수는 아니다.)
- module은 esm에서 라이브러리를 import할때 필요한 파일 경로를 설정한다.
- types는 typescript에서 타입을 가져오기 위한 d.ts 파일 경로를 설정한다.
- peerDep은 라이브러리를 사용하는 프로젝트에서 설치해야할 라이브러리와 그 버전을 설정한다.
- 개발하기위해 depDep에도 peerDep에 기술한 라이브러리를 설치한다. 프로덕션 빌드에선 포함되지 않는다.
tsconfig
결국 typescript를 컴파일해 js로 변환해야 한다. 이 방식을 설정한다.
{
"compilerOptions": {
"target": "ES2019",
"module": "ESNext",
"jsx": "react",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationDir": "./dist/types",
"outDir": "./dist",
"moduleResolution": "node"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
- target으로 어떤 세대(버전)의 js문법으로 컴파일 할 것인지 결정한다.
- module에선 모듈 시스템을 지정한다.
- jsx로 tsx를 컴파일한다.
- esModuleInterop으로 cjs 모듈과 esm간의 호환성을 제공한다. 예를들어, cjs 시대에 게발된 매우 옛날 모듈을 import
~처럼 사용하게 해준다. - skipLibCheck로 라이브러리 의존성을 굳이 검사하지 않는다.
- declaration과 declarationDir로 d.ts 파일을 생성한다.
- outdir은 컴파일 결과 경로이다.
rollup config
라이브러리를 빌드하기 위한 설정
// import peerDepsExternal from "rollup-plugin-peer-deps-external";
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import dts from "rollup-plugin-dts";
// import copy from "rollup-plugin-copy";
import pkg from "./package.json" assert { type: "json" };
export default [
{
input: "src/index.ts",
output: [
{
file: pkg.main, // dist/cjs/index.js
format: "cjs",
sourcemap: true,
},
{
file: pkg.module, // dist/esm/index.js
format: "esm",
sourcemap: true,
},
],
external: [...Object.keys(pkg.peerDependencies || {})],
plugins: [
resolve(),
commonjs(),
typescript({
tsconfig: "./tsconfig.json",
}),
// copy({
// targets: [{ src: "src/ui/styles.css", dest: "dist" }],
// }),
],
},
{
input: "src/index.ts",
output: {
file: "dist/types/index.d.ts",
format: "es",
},
plugins: [dts()],
},
];
- input에는 빌드 진입점을 설정한다. 대부분 라이브러리 파일을 개발할땐, 한 파일(index.ts)에다 사용할 기능을 export한다.
- ouput에는 빌드 결과물을 설정한다. file엔 빌드 결과의 경로, format은 모듈 시스템 형식, sourcemap은 번들 코드와 원본 코드(es6, ts형식)의 매핑 파일(js.map)을 형성한다.
plugin
- resolve는 라이브러리에서 추가적인 의존성을 빌드결과에서 가져오고 ts와 jsx파일을 빌드하게 해준다.
- commonjs는 cjs 형식을 esm으로 변환해준다. 기본적으로 rollup은 esm을 지원한다.
- typescript는 tsc(타입스크립트 파일을 js로 변환)를 해준다.
- dts는 index.d.ts를 생성해준다.
테스팅용 패키지에서 라이브러리 사용
라이브러리를 빌드한 뒤 그 결과를 워크스페이스내에서 사용
테스팅용 package의 package.json에서
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1",
"my-lib": "workspace:*"
},
해당 내용 작성해준다.
my-lib이란 패키지를 워크스페이스 내에서 사용해준다는 의미이다.
my-lib을 빌드해준다면 그대로 테스팅용 패키지에서 사용 가능하다.