이 영상를 보고 연습삼아 한번 만들어보고 있습니다. 각 항목에 대한 상세한 설명은 추후 추가 할 예정입니다.
라이브러리 배포를 위해 먼저 npm 아이디가 필요합니다.
롤업은 웹팩과 마찬가지로 자바스크립트 모듈 번들러이다.
- 공식문서 발췌
롤업은 코드들의 작은 조각들을 컴파일해서 라이브러리나 어플리케이션 같이 크고 복잡한 것으로 바꾸어주는 자바스크립트 모듈 번들러입니다.
롤업은 CommonJs나 AMD같은 이전의 특이한 해결책들 대신에, ES6가 포함된 새롭게 기준화된 포맷을 사용합니다.
ES 모듈들을 사용해서 당신은 좋아하는 라이브러리들로부터 각각 개별의 기능들을 자유롭고 원활하게 결합할수 있습니다.
이는 결국엔 어디서든지 가능하게 되겠지만, 롤업을 사용해서 지금 당장 가능하게 합니다.
{
"name": "testlibrarycomponent",
"version": "1.0.0",
"description": "test",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "brgndy",
"license": "MIT"
}
npm install react typescript @types/react --save-dev
npx tsc --init
{
"compilerOptions": {
"jsx": "react", // jsx 코드를 리액트로 변환
"target": "ESNext", // 가장 최신 ECMAScript 버전 사용
"module": "ESNext", // 가장 최신 ECMAScript 버전 사용
"esModuleInterop": true, // CommonJS와 AMD 모듈을 ES6 모듈로 잘 통합하게 해줌
"forceConsistentCasingInFileNames": true, // 파일의 대, 소문자 일관성 강조
"strict": true, // 엄격한 타입 체킹
"skipLibCheck": true, // 선언 파일(d.ts)파일은 타입체크 건너 뜀
"rootDir": ".", // 소스 파일 최상위 디렉토리 지정
"declaration": true, // 타입 선언 파일(d.ts) 사용
"declarationDir": "types", // 선언 파일 저장할 디렉토리
"sourceMap": true, // 컴파일된 파일을 원본 소스와 맵핑
"outDir": "dist", // 컴파일 된 파일들을 저장할 출력 디렉토리 지정
"moduleResolution": "Node", // 모듈 해석 방식
"allowSyntheticDefaultImports": true, // 기본적으로 export 되지 않은 파일들을 default import로 가져오기
"emitDeclarationOnly": true // 자바스크립트 파일 생성하지 않고 오직 선언 파일만 생성
}
}
import React from "react";
import { PropsWithChildren } from "react";
export default function Button(props: PropsWithChildren<object>) {
const { children } = props;
return <button>{children}</button>;
}
// 이 파일은 Button 컴포넌트를 외부에 노출시키는 역할을 한다.
// export { default } from "./Button"; 구문을 사용함으로써, Button.tsx에서 export된 기본 컴포넌트를 바로 재export 한다.
// 이렇게 하면 다른 파일에서 Button 컴포넌트를 가져올 때
// import Button from './components/Button'와 같은 방식으로 직접적인 경로를 사용하지 않고
// import { Button } from './components'의 방식으로 더 간결하게 가져올 수 있다.
export { default } from "./Button";
// 이 파일은 components 폴더 내의 모든 컴포넌트를 한 곳에서 관리한다.
// export { default as Button } from "./Button"; 구문을 통해
// Button 컴포넌트를 다시 한번 재export하고, 필요한 경우 여기에 다른 컴포넌트들도 추가할 수 있다.
// 이 구조를 사용함으로써, components 폴더에 새로운 컴포넌트를 추가할 때 마다
// 이 index.ts 파일만 업데이트하면 되므로, 관리가 편리해진다.
export { default as Button } from "./Button";
// export { default as Input } from './Input';
// 이 파일은 전체 라이브러리의 진입점(entry point) 역할을 한다.
// export * from "./components"; 구문은 components 폴더의 모든 export들을 재export한다.
// 이렇게 함으로써, 라이브러리 사용자는 이 라이브러리에서 제공하는 모든 컴포넌트를
// import { Button, AnotherComponent } from 'your-library-name'와 같은 방식으로 한 번에 가져올 수 있도록 한다.
export * from "./ components";
src
┣ components
┃ ┣ Button
┃ ┃ ┣ Button.tsx
┃ ┃ ┗ index.ts
┃ ┗ index.ts
┗ index.ts
npm install --global rollup
npm install rollup --save-dev
롤업은 기본적으로 전역 설치도 가능하지만, 만약 협업을 하거나 환경에 제약이 있다면 로컬 설치도 가능하다.
일단 로컬 설치로 진행해보려한다.
npm install --save-dev @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-terser @rollup/plugin-typescript rollup-plugin-dts rollup-plugin-peer-deps-external tslib
import nodeResolve from "@rollup/plugin-node-resolve"; // Node.js 모듈 충돌 해결
import commonjs from "@rollup/plugin-commonjs"; // commonjs 를 es6로 변환하여 롤업 번들에 포함시킬수 있도록 함
import typescript from "@rollup/plugin-typescript"; // 타입스크립트를 롤업 번들과 통합시켜줍니다.
import dts from "rollup-plugin-dts"; // .d.ts 정의 파일을 롤업할 수 있는 플러그인.
//NEW
import terser from "@rollup/plugin-terser"; // 생성된 es 번들을 최소하 해줍니다
import peerDepsExternal from "rollup-plugin-peer-deps-external"; // 롤업 번들에서 PeerDependency를 자동으로 외부화
// rollup 설정 파일은 대부분 Node.js의 기본설정(commonjs)이 적용된 환경에서 실행 되기때문에 require 문을 사용한다.
const packageJson = require("./package.json");
export default [
// 소스 코드에 대한 번들링 설정
{
// 엔트리 포인트로 src/index.ts 파일을 지정
input: "src/index.ts",
// 번들의 결과물의 출력 설정
output: [
{
file: packageJson.main,
format: "esm",
//소스맵은 컴파일된 코드(여기서는 번들링된 JavaScript 파일)를 원본 소스 파일(예: TypeScript 파일)에 매핑하는 파일
// 소스맵을 설정해주면 디버깅에 용이하기때문에 오류 추적이 훨씬 쉬워진다.
sourcemap: true,
},
],
// 플러그인들 설정
plugins: [
// NEW
typescript(),
peerDepsExternal(),
nodeResolve(),
commonjs(),
// NEW
terser(),
],
},
// 타입 선언 파일의 번들링 설정
{
// 선언 파일의 엔트리 포인트
input: "dist/cjs/types/src/index.d.ts",
// 선언파일의 출력 형식, dist/index.d.ts 파일을 esm 형식으로 출력
output: [{ file: "dist/index.d.ts", format: "esm" }],
//dts 플러그인을 사용하여 d.ts 파일을 만듬
plugins: [dts.default()],
// css 파일을 외부모듈로 처리
external: [/\.css$/],
},
];
{
"name": "testlibrarycomponent",
"version": "1.0.0",
"description": "test",
"main": "dist/cjs/index.js",
"files": [
"dist"
],
"types": "dist/index.d.ts",
"scripts": {
"rollup": "rollup -c --bundleConfigAsCjs"
// rollup.config.js 경로와 같다.
// c는 config의 단축형이다.
// -c 뒤에 파일 경로를 지정하지 않으면, Rollup은 기본적으로 현재 디렉토리에서 rollup.config.js 파일을 찾아 사용한다.
// 프로젝트가 CommonJS 모듈 형식을 사용하는 경우, 이 플래그를 통해 Rollup에게 설정 파일을 CommonJS 형식으로 해석하도록 지시
},
"author": "brgndy",
"license": "MIT",
"type": "module",
"keywords": [
"tutorial",
"button",
"test"
],
"devDependencies": {
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.5",
"@types/react": "^18.2.43",
"react": "^18.2.0",
"rollup": "^4.9.0",
"rollup-plugin-dts": "^6.1.0",
"rollup-plugin-peer-deps-external": "^2.2.4",
"tslib": "^2.6.2",
"typescript": "^5.3.3"
},
"peerDependencies": {
"react": "^18.0.0"
}
}
npm run rollup
dist
┣ cjs
┃ ┣ types
┃ ┃ ┗ src
┃ ┃ ┃ ┣ components
┃ ┃ ┃ ┃ ┣ Button
┃ ┃ ┃ ┃ ┃ ┣ Button.d.ts
┃ ┃ ┃ ┃ ┃ ┗ index.d.ts
┃ ┃ ┃ ┃ ┗ index.d.ts
┃ ┃ ┃ ┗ index.d.ts
┃ ┣ index.js
┃ ┗ index.js.map
┗ index.d.ts
node_modules
dist
.rollup.cache
npm adduser
npm publish
npm 사이트에도 정상적으로 배포가 된 것을 확인해 볼수 있다.