리액트와 타입스크립트를 이용해 UI 컴포넌트 라이브러리를 사내에서 사용할 일이 생겼다. 이를 위해 간단한 UI 컴포넌트를 npm publish 말고 로컬 파일로 사용할 수 있도록 코드를 정리해보겠다.
// MyComponent.jsx
import React from 'react';
export default function MyComponent() {
return (
<div>hello</div>;
)
}
// index.js
import MyComponent from './MyComponent.jsx';
export { MyComponent };
javascript 모듈 번들러로 ES6 모듈 형식으로 결과물을 생성한다.
트리 쉐이킹으로 최소한의 필수 요소만 포함하기 때문에 더 가볍고 빠르고 복잡한 라이브러리 애플리케이션을 만들 수 있다.
import {babel} from "@rollup/plugin-babel";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import nodeResolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from "@rollup/plugin-typescript";
export default {
input: "./src/index.ts", // 진입점
output: {
file: './dist/bundle.js',
format: 'esm', // esmodule로 output
sourcemap: true,
},
plugins: [
peerDepsExternal(),
nodeResolve(),
commonjs(),
babel({
babelHelpers: 'bundled',
extensions: ['.js', '.jsx', '.ts', '.tsx'],
presets: ["@babel/env", "@babel/react", "@babel/preset-typescript"]
}),
typescript() // typescript compile
]
};
babelHelpers
해당 바벨 헬퍼가 코드에 삽입되는 방법을 결정하는지 명시적으로 구성해야 한다.
runtime: 헬퍼 함수를 @babel/runtime 라이브러리에서 가져온다.
bundled: 헬퍼 함수가 각 번들 파일에 포함된다. 기본설정
inline: 각 헬퍼 함수가 각 파일에 인라인으로 삽입된다.
external: 헬퍼 함수를 외부 모듈로 설정한다.
extensions : babel이 변환해야하는 파일 확장자들
{
"name": "MyComponent",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c",
"doc": "typedoc --out ./docs",
"prepack": "rimraf ./package && npm run build && npm run doc && mkdirp ./package ./package/docs ./package/dist && xcopy README.md .\\package\\ /k /Y && xcopy package.json .\\package\\ /k /Y && xcopy docs\\*.* .\\package\\docs\\*.* /e /h /k /Y && xcopy dist\\*.* .\\package\\dist\\*.* /e /h /k /Y && json -I -f ./package/package.json -e \"this.main='dist/bundle.js';this.types='dist/types/index.d.ts'\"",
"pack": "tar cvzf my_component.tar.gz package/*"
},
"author": "",
"license": "ISC",
"main": "./dist/bundle.js",
"devDependencies": {
"@babel/core": "^7.19.1",
"@babel/preset-env": "^7.19.1",
"@babel/preset-react": "^7.18.6",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-commonjs": "^22.0.0",
"@rollup/plugin-node-resolve": "^13.3.0",
"babel-loader": "^9.1.3",
"rollup": "^2.79.0",
"rollup-plugin-peer-deps-external": "^2.2.4"
},
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
저는 이전 글에서 작성했던 패키지화 하는 방식으로 라이브러리화를 하였습니다. npm run pack을 하면 간편하게 패키지를 뽑을 수 있습니다.
MyComponent 에서 npm package 설치 후 npm run build를 수행한다.
사용하려는 프로젝트에서 MyComponent를 로컬적으로 사용하려면 npm i path로 설치하면 된다.
// other project
import React from 'react';
import { MyComponent } from 'my-component';
export default function App() {
return (
<>
<MyComponent />
</>
)
}