기타

react + typescript로 github package화 하기(feat. rollup)

MoZZANG 2023. 2. 9. 17:00

package화 하게 된 계기

 

회사에는 그 회사만의 컬러나 디자인 시스템이 있을 것이다. 때문에 클라이언트에게 서비스하는 다양한 도메인에서 고작 버튼이라도 동일하거나 비슷한 버튼을 사용할 것이다. 그럴 때마다 동일한 코드를 계속해서 작성해서 동일한 컴포넌트를 만드는 것은 재사용성이나 유지보수 측면에서 절대 좋지 않을 것이다.

 

때문에 디자인 시스템이 정해진 곳이라면 모든 도메인에서 공통적으로 사용하는 컴포넌트들은 라이브러리화하여 가져다 쓸 수 있다면 정말 좋지 않을까?

 

그러기 위해서 아주아주 유명한 npm에 publish하여 npm install로 사용할 수도 있겠지만...

 

 

 

보통 회사에서는 private repo로 서비스를 관리하는데 이런 private repo를 npm에 registry하려면 돈을 내야한다. 심지어 그 private레포를 공유하는 사람 머릿수 곱하기 $7였던거 같은데 이렇게 되면 금액적으로도 큰 지출이 될 수 있기 때문에 다른 방법을 찾아야 했다.

 

그래서 찾은 방법이 바로 github package이다.


 

 

 

github package란?

 

npm에 publish하듯이 github에서 제공해주는 publish 기능이다. 보통 회사에서 github 유료계정을 사용하기 때문에 유료계정을 하용하게 되면 같이 제공해준다.


 

 

 

 

시작하기

1. Access Token 생성

 

먼저 해당 repo에 접근권한을 위해 token을 생성합니다.

 

 

 

 

 

 

 

순으로 진입해줍니다.

 

 

기본적으로 위와 같이 3개의 옵션을 선택해주고 나머지는 옵션으로 필요에따라 선택해주면 됩니다.

 

⚠️ 다들 아시겠지만 현재 화면을 벗어나면 해당 토큰값은 두 번 다시 볼 수 없으니 복사를 꼭 해줍시다!!


 

 

 

 

2. package.json 설정

 

프로젝트를 배포하기 위해서는 조건에 맞춰 수정해주어야 합니다.

// package.json
// 추가 설정해야할 내용들

{
  "name": @github 개인아이디 또는 github 회사 계정명/프로젝트 명
  "version": "1.0.0",
  "main": 모듈 실행하는 시작할 파일(ex. index.js)
  "scripts": {
    ...
  },
  "author" : 사용자
  "license": "MIT",(알아서)
  "repository": {
  	"type" : "git",
    "url" : 패키지화 할 repo의 github 주소
  },
  "publishConfig": {
    "registry":"https://npm.pkg.github.com"
  }
}

 

✅ 중요

  • name : @를 꼭 붙여주세요!
  • publishConfig : 어디에 publish 할 것인지에 대한 registry 주소 정보
    => github package repo경로를 넣으면 npm publish 할 때 npm 저장소가 아닌 github의 패키지 저장소에 저장이 됩니다.
  • repository: repo가  어떤 타입이고 어디인지

 

 

 

3.tsconfig 설정하기

 

 

//tsconfig.json
{
  "compilerOptions": {
    // Default
    "target": "es5", 
    "esModuleInterop": true, 
    "forceConsistentCasingInFileNames": true,
    "strict": true, 
    "skipLibCheck": true,

    // Added
    "jsx": "react-jsx",
    "jsxImportSource" : "@emotion/react",
    "noEmit" : false,
    "module": "ESNext",  
    "declaration": true,
    "declarationDir": "types",
    "sourceMap": true,
    "outDir": "dist",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "emitDeclarationOnly": true,
    ...
  }
}

 


 

 

 

4. rollup 설치하기

 

 

rollup이 뭐지?

rollup 라이브러리를 설치하여 사용할 것인데, rollup은 webpack과 같은 번들링 툴인데, 각각의 JS module들을 브라우저가 이해하기 더 쉽게 하나의 source로 해준다.

 

또한, commonJs 모듈 형태뿐만 아니라 esModule형태로도 번들링이 가능하기에 cjs나 esm을 사용하는 곳 모두에서 사용할 수 있으므로 library처럼 범용성이 필요한 곳에서 사용하기 좋다

 

webpack은 esModule로 번들 불가하다.

 

webpack과 rollup 모두 궁극적으로는 번들링을 위한 도구이지만 

일반적으로 webpack은 응용프로그램 번들에 사용되는 툴이라면 rollup은 특히 라이브러리 번들에 적합하다.

 

유지관리도 잘 되고 있고 해외에서는 많이 쓰이는 라이브러리화 번들링 도구이다.

https://npmtrends.com/rollu

 

npm trends: Compare NPM package downloads

Which NPM package should you use? Compare packages download stats, bundle sizes, github stars and more. Spot trends, pick the winner.

npmtrends.com

 

 

 

또한 rollup은 commonJS와 ESModule 모두에서 사용가능하도록 각각의 폴더로 번들링을 해서 생성해주기도 하는 것도 장점이다.

 

자, 이제 기본적으로 필요한 것들을 설치해보자

 

✔️ 설치하기

 

--기본적인 설치

  • @rollup/plugin-node-resolve : node_modules에서 third party module들 사용하는 용도로 사용. js외의 확장자(ts, tsx)를 불러오기 위해서도 필요함.
  • @rollup/plugin-typescript : typescript 지원 플러그인
  • @rollup/plugin-commonjs : commonJS 를 ES6로 변환해준다.
  • rollup-plugin-dts : d.ts파일들을 번들링 해준다.
  • rollup-plugin-terser: 생성된 es번들을 최소화하기 위한 플러그인

 

-- 필요시 추가 플러그인

  • + 필요시 rollup-plugin-peer-deps-external : peerDependency로 설치된 라이브러리의 코드가 번들링 결과에 포함되지 않고 import를 통해 불러와서 사용할 수 있게 해주는 플러그인
  • @rollup/plugin-url: 파일을 데이터 URI 혹은 es모듈로 가져오는 플러그인
  • @rollup/plugin-commonjs: CommonJS 모듈을 es 모듈로 변환하는 플러그인
  • 등등

 

만약 peerDependency설치를 했다면 package.json에 아래와 같이 필요한 라이브러리들을 추가해주면 된다.

//package.json
"peerDependencies": {
  "@emotion/react": "^11.5.0",
  "react": "^17.0.2",
  "react-dom": "^17.0.2"
}

 

 

 

npm i -D rollup @rollup/plugin-node-resolve @rollup/plugin-typescript @rollup/plugin-commonjs rollup-plugin-dts

 

 

 

 

✔️ rollup.config.mjs 세팅하기

 

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";

const packageJson = require("./package.json");

export default [
  {
    input: "src/index.ts",(경로는 사용자 환경세팅에 맞춰서)
    output: [
      {
        file: packageJson.main,
        format: "cjs",
        sourcemap: true,
      },
      {
        file: packageJson.module,
        format: "esm",
        sourcemap: true,
      },
    ],
    plugins: [
      resolve(),
      commonjs(),
      typescript({ tsconfig: "./tsconfig.json" }),
    ],
  },
  {
    input: "dist/esm/types/index.d.ts",
    output: [{ file: "dist/index.d.ts", format: "esm" }],
    plugins: [dts()],
  },
];

 

기본적으로 rollup 은 우리의 모듈을 번들링할 때 단 하나의 객체를 내보내는 export default 인지, 아니면 default 없이 일일이 이름을 지어서 내보내는지 추측해서 번들링 하도록 되어있다.

 

output.exports 의 옵션으로 default, named 아니면 none 3가지 옵션을 주고 있다.

 

rollup 의 권장사항은 named 이다. 애초에 코드를 작성할 때도 마지막에 export default 를 하지 않기를 권장한다.

 

 

 

 

 

rollup 사용을 위해 아래 코드를 package.json에 추가해주자.

//package.json

"scripts" : {
	"rollup" : "rollup -c"
}
"main" : "dist/cjs/index.js",
"module" : "dist/esm/index.js",
"types" : "dist/index.d.ts"

 

 

 

 

이후 rollup을 하게 되면

 

아래와 같이 output폴더로 지정해두었던 곳에 commonjs에서 사용할 수 있는 버전(?)과 esModule에서 사용할 수 있는 버전 두 가지로 다 빌드가 잘 된 모습을 볼 수 있습니다.

 

 

 

위의 빌드된 폴더로 npm publish를 하게되면 package.json에서 설정해두었던 publishConfig에 의해 github package로 배포가 되게 된다. github repo에 가면 우측어딘가에 아래와 같이 패키지가 생성 되어있을 것이다.

 

 

 

 

들어가보면

 

 

 

와 같이 마치 Npm처럼 설치 코드와 최신 버전등을 알려주고 있다.

 

그리고 가져다 사용하면 된다.

 

 

 

 

 

❗️주의 사항으로는 code상에서 수정이 이루어지고 다시 push를 할때는 package.json에 있는 version을 0.0.1 단위로 꼭 올려서 push해야 패키지가 업데이트 된다!!

 

 

가져다 사용할 때는

가져다 사용하는 곳에서는 .npmrc 를 만들고 아래와 같은 코드를 작성 후 npm install받아야 token값을 이용해 잘 설치된다.

package.json의 name에서 @뭐시기 : registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=아까 발급한 토큰값

 

 

 

 

불편함 해결

뭔가 작은 코드 수정을 하였을 때마다 version을 올려서 Push하고 잘 적용되는지 확인하고 하는 것이 많이 번거롭다...

 

이럴때는 local에서 확인 후 잘 적용된다면 version 올리고 push하는 방향으로 한다면 좀 더 효율적일 것이다.

 

나는 파일을 압축해서 local에서 npm install하는 방식으로 문제를 해결하였다.

 

//package.json
"scripts": {
		"publish:npm": "rm -rf ./dist && rollup -c && npm pack"
	},

 

 

이렇게 하면 라이브러리화 한 프로젝트의 root에 .tgz확장자로 된 압축파일이 하나 생성되고 이걸 Local에서 아래와 같이 가져다 사용하면 된다.

 

가져다 쓰고 싶은곳에서 압축파일과의 상대경로로 설치해주면 되는데,

 

 

설치하면

 

 

 

아까 압축한 그 파일을 마치 npm install한 것 마냥 설치해서 사용할 수 있다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'기타' 카테고리의 다른 글

MongoDB)가입부터 초기 세팅까지 해보자  (2) 2023.12.02
팀플영상  (0) 2023.01.11
포트폴리오용 영상  (0) 2022.08.04