부족한 점이 많은 글 봐주셔서 감사합니다. 틀린 내용이 있으면 댓글 첨부 부탁드리겠습니다. 후기는 편의상 반말로 작성하였습니다.
개인 프로젝트를 진행하면서 프로젝트 간 사용하는 공통기능을 묶어 하나의 라이브러리로 분리하고 싶었다. 처음에는 Webpack으로 분리하려 했지만 라이브러리 내부에서 오류(Cannot read properties)가 해결 이 안되어 Rollup 번들러를 사용하게 되었다.
프로젝트 폴더를 생성하고 yarn 초기화를 한다. 초기화 명령어는 init이다. 필요한 의존성 패키지는 아래와 같다.
yarn init
## devDependencies에 의존성 추가시
yarn add -D rollup
## peerDependencies에 의존성 추가시
yarn add -P react
## 프로젝트의 진입점
"main": "./dist/bundle.js",
"type": "module",
"devDependencies": {
"@babel/core": "^7.20.12",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@rollup/plugin-babel": "^6.0.3",
"rollup": "^3.14.0"
},
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
여기서 "peerDependencies" 속성이 중요하다. peerDependencies 속성을 사용하면 react, react-dom 라이브러리를 사용하고 있는 루트 프로젝트의 node_modules 하위 react, react-dom을 참조한다는 뜻이다. 만약에 루트 프로젝트에 없다면 일반적인 의존성으로 대체된다.
만약 peerDependencies를 사용하지 않으면 react의 경우 Hooks 에러가 발생한다. 정확히는 아래와 같은 오류가 발생했다.
리액트 공식 홈페이지(https://ko.reactjs.org/warnings/invalid-hook-call-warning.html)에 해당 이슈에 대해 잘 나와 있는데 요약하면 프로젝트 React 패키지의 두 복사본이 있는 경우 오류가 발생한다고 한다. 두 복사본을 사용하는지 아닌지 확인할 수 있는 예제 소스도 알려주는데 직접 적용을 해봤다.
devDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@babel/core": "^7.20.12",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@rollup/plugin-babel": "^6.0.3",
"rollup": "^3.14.0"
}
window.React1 = require('react');
console.log(window.React1);
import ReactDom from 'react-dom';
import React from 'react';
window.React2 = React;
console.log(window.React1 === window.React2);
만약 peerDependencies에 react, react-dom을 옮기고 적용하면 true 값이 뜨면서 오류가 발생하지 않는다.
import babel from "@rollup/plugin-babel";
export default {
input: "./index.js",
external: ['uuid', 'react', 'react-dom'],
output: {
file: "./dist/bundle.js",
format: "es",
sourcemap: true,
},
plugins: [
babel({
babelHelpers: "bundled",
presets: ["@babel/preset-env", "@babel/preset-react"],
})
],
};
재그지그님의 블로그에서 "Rollup 기반 라이브러리 개발 환경 구성하기"글을 참고하였다. 설정에 사용된 속성을 살펴보자.
input: "./index.js"
라이브러리의 시작파일 경로 및 파일명을 지정하면된다.
external: ['uuid', 'react', 'react-dom']
라이브러리에서 의존하는 외부 패키지를 추가한다. 추가하지 않을 경우 "Unresolved dependencies" 경고가 발생한다.
rollup으로 빌드 시 외부 패키지가 라이브러리의 node_module에 없더라도 오류가 발생하지 않는다. 다만 경고만 노출하며 개발자가 node_module에 없는 것을 의도한다면 external 옵션을 주면 경고가 사라진다.
나의 경우엔 루트 프로젝트에 react, react-dom, uuid가 기본적으로 있기에 external 옵션을 줬다.
만약 라이브러리 번들에 외부 패키지를 포함시키고 싶으면 "@rollup/plugin-node-resolve" 플러그인 을 찾아보자
output: {
file: "./dist/bundle.js",
format: "es",
sourcemap: true,
},
output 옵션은 빌드 결과로 나온 변들 파일에 대한 옵션이다.
file : 경로 및 번들 파일명으로 지정한다.
format : 번들 된 파일의 포맷을 정의한다. 아래 링크 접속 시 이해할 수 있다.
https://rollupjs.org/repl/
sourcemap : 디버깅을 하기 위해 추가하였다. true로 주면 map 파일을 생성하고 브라우저에서 디버깅할 수 있게 된다.
plugins: [
babel({
presets: ["@babel/preset-env", "@babel/preset-react"]
})
]
rollup에서 사용할 외부 플러그인을 추가하는 옵션이다. 예를 들어 rollup은 jsx 구문을 처리하지 못한다. 그래서 바벨 플러그인을 설치해서 처리하도록 한다. 이렇듯 rollup에서 처리하지 못하는 부분들을 플러그인을 사용해서 해결한다.
"scripts": {
"build": "rollup -c",
"watch": "rollup -cw"
}
package.json 파일에 scripts를 추가 후 yarn build를 실행해보자.
yarn link를 사용하면 라이브러리를 npm에 배포하지 않고 테스트할 수 있는 방법이다. 사용법은 간단하다.
라이브러리 폴더로 이동
yarn link 명령어 실행
라이브러리의 심볼릭 링크가 "~/.config/yarn/link" 경로에 생긴다.
루트 프로젝트 이동
yarn link <라이브러리 프로젝트 이름>
link 경로에 있는 라이브러리를 참조하여 사용할 수 있다.
이번 경험 글을 작성하면서 개발 시 모르고 지났던 세세한 부분들도 공부할 수 있어 좋았다. 나만 보는 글이 아닌 다른 분들도 볼 수 있기에 잘못된 정보가 있는지 꼼꼼히 체크하고 모르는 부분들은 찾아보았다.
react - Invalid Hook Call Warning
yarn - yarn link
재그지그 - Rollup 기반 라이브러리 개발 환경 구성하기
심심재 - npm link 이해하기