티스토리 뷰

과거에 배포했던 npm package를 번들링 한뒤 배포해 보기로 했다.

 

https://ljy1011.tistory.com/182

 

React 컴포넌트 Npm에 배포하기 (with TS)

react 로 만든 컴포넌트를 npm 사이트에 배포해 보자! (typescript 적용) https://www.npmjs.com/package/react-divided-progress-bar react-divided-progress-bar A progress-bar which has divided section based on React.js. Latest version: 0.1.7, l

ljy1011.tistory.com

https://ljy1011.tistory.com/203

 

[NPM에 배포한 React Package 개선]

React.js로 컴포넌트를 만들어 배포한적이 있었다https://ljy1011.tistory.com/182 React 컴포넌트 Npm에 배포하기 (with TS)react 로 만든 컴포넌트를 npm 사이트에 배포해 보자! (typescript 적용) https://www.npmjs.com/pa

ljy1011.tistory.com

 


 

번들링의 목적은 기존의 여러개의 파일(.js .css)로 분리 되어있던 기존 패키지를 하나로 합치기 위함. 이를 통해 파일 사이즈 감소, 트리쉐이킹을 통한 최적화 등을 기대해 볼 수 있다.

 

번들러로 webpack을 사용할까 하다가 Rollup을 사용 하기로 했다.

rollup은 라이브러리 및 모듈을 번들링 하는데 webpack 보다 최적화 되어 있기 때문이다. 

 

1. ES 모듈에 대한 우수한 지원

2. webpack 보다 효율적인 트리 쉐이킹(Tree Shaking)

3. webpack 보다 가벼운 번들 사이즈 

 

가 있다. 

peerDependancy 설정


peerDependency란?

peer dependency는 패키지 간 호환성을 명시하고, 중복 설치 문제를 방지하며, 개발자가 프로젝트의 의존성을 더 잘 관리할 수 있게 해 준다. 따라서 프로젝트를 패키지로 배포 시 특정 하위 패키지에 대해 의존성이 높은 경우 에 사용하는 것이다. 

 

 

우선 기존 프로젝트 package.json 설정부터 변경 하기로 했다.

내가 제작한 라이브러리는 react에 대한 의존성을 지니기 때문에, peerDependancy에 react 버전을 정확히 명시해 두는편이 더 나았다. 

 

기존에는 dependency의 react와 react-dom 버전을 dependency에 명시 하였다.

이는 문제점을 낳았는데, 만약 라이브러리가 dependencies에 React 18을 명시하고 있다면, NPM 또는 Yarn은 라이브러리를 설치할 때 프로젝트에 React 18을 함께 설치하게 되나.. 이 경우, 최종 프로젝트는 React 17과 React 18 두 버전이 중복 설치될 수 있다! React는 서로 다른 버전이 동시에 사용되는 것을 허용하지 않기 때문에, 이로 인해 애플리케이션이 예기치 않게 동작하거나 오류가 발생할 수 있었다.

 

수정전)

  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },

 

수정 후)

  // 제거
  "dependencies": {
  },
  "peerDependencies": {
    "react": ">=17.0.0 <19.0.0",
    "react-dom": ">=17.0.0 <19.0.0"
  },

 

 

Rollup Plugin 설정


필요한 플러그인을 일일이 다운받고 설치해 주어야 하기 때문에 rollup의 단점이라고 할수 있는 plugin 설정

 

추가한 plugin은 다음과 같다.

npm i -D rollup @rollup/plugin-babel @rollup-plugin-peer-deps-external @rollup-plugin-postcss @rollup/plugin-typescript @rollup/plugin-node-resolve @rollup/plugin-commonjs postcss-import autoprefixer

 

@rollup/plugin-babel

Babel을 Rollup에서 사용할 수 있도록 해주는 플러그인

@rollup-plugin-peer-deps-external

peerDependencies로 정의된 패키지들을 Rollup 번들에 포함하지 않고 외부 패키지로 처리해주는 플러그인

@rollup-plugin-postcss

CSS 파일을 처리할 수 있게 해주는 플러그인. PostCSS를 사용하여 CSS를 변환하거나 미니파이(minify)하는 등의 작업을 할 수 있다. 또한, 스타일 파일을 번들에 포함시킬 수 있다.

  • 기존에는 .style 파일을 빌드 결과물에 그대로 복사해 붙여 넣었기에, 이를 js 번들로 변환해주는 작업을 위해 추가 했다.
  • 이를 위해서는 rollup-plugin-postcss 뿐만 아니라,  postcss-importautoprefixer 패키지를 추가로 install 했다.

@rollup/plugin-typescript

TypeScript 파일을 Rollup을 통해 트랜스파일할 수 있도록 해주는 플러그인

@rollup/plugin-node-resolve

Node.js 모듈을 처리할 수 있게 해주는 플러그인으로, Rollup이 node_modules에 있는 패키지를 찾을 수 있도록 도와준다. 이를 통해 Node.js의 모듈 시스템을 사용한 패키지를 번들에 포함시킬 수 있다.

@rollup/plugin-commonjs

CommonJS 모듈을 ES 모듈로 변환해주는 플러그인 Rollup은 기본적으로 ES 모듈만 처리할 수 있기 때문에, CommonJS로 작성된 패키지를 사용할 경우 이 플러그인이 필요 하다. 이를 통해 CommonJS로 작성된 코드를 Rollup 번들에 포함할 수 있다.

 

rollup.config.ts

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";
import autoprefixer from "autoprefixer";
import postcss from "rollup-plugin-postcss";
import cssimport from "postcss-import";
import pkg from "./package.json";

// eslint-disable-next-line import/no-anonymous-default-export
export default {
  external: [],
  input: "./src/index.tsx", // 진입점
  output: [
    {
      file: pkg.main,
      format: "cjs", // cjs로 output
      sourcemap: true,
      // 라이브러리 변환 이슈
      banner: "/* eslint-disable no-unused-expressions, no-undef */",
    },
  ],
  plugins: [
    peerDepsExternal(),
    nodeResolve(),
    babel({
      babelHelpers: "bundled",
      extensions: [".js", ".jsx", ".ts", ".tsx"],
      presets: ["@babel/env", "@babel/react", "@babel/preset-typescript"],
    }),
    commonjs(),
    typescript(), // typescript compile
    postcss({
      plugins: [cssimport(), autoprefixer()],
    }),
  ],
};

 

package.json

tsc로 컴파일후 .sytle 파일을 복사해 넣던 기존 명령어 보다 훨씬 간결해 졌다.

 "scripts": {
    "start": "rollup -c -w",
    "build": "rm -rf dist && rollup -c",
    "prepare": "npm run build"
 },

 

 

 

결과


여러개로 분할되어 있던 .js 및 .css 파일이 깔끔하게 index.js 로 번들링 되었다.

 

before)

 

after) 

 

 

 

 


아직 완벽히 해결하지 못한 ESLint - no-unused-expressions 에러

 

번들링된 결과물에서 eslint 오류가 발생 하였다.

문제의 해당 라인. clsx 이슈 였다.

해당 라인을 살펴본 결과 Class merge를 위해 추가했던

clsx 라이브러리가 plugin-node-resolve plugin의 node_modules 패키지 변환 과정중 생긴 이슈 였다.

해당 문제를 완벽하게 해결하기 위해 노력해봤지만 plugin의 package 변환 과정시 생긴 eslint 오류를 해결하기는 너무 버거웠다..

 

https://stackoverflow.com/questions/52274829/eslint-no-unused-expressions-in-reactjs

 

ESLint - no-unused-expressions in ReactJS

Getting a ESLint error when copiling with babel: Line 28: Expected an assignment or function call and instead saw an expression no-unused-expressions Line 29: Expected an assignment or function...

stackoverflow.com

 

결국 stackoverflow 검색 결과 해당 라인을 eslint disable 시키는 방법을 차선책으로 선택하였다. 

eslint 설정을 disable시키기 위해 rollup.config에서 banner 프로퍼티에 eslint-disable 라인을 추가 했다. 

output: [
    {
      // 라이브러리 변환 이슈
      banner: "/* eslint-disable no-unused-expressions, no-undef */",
    },
...
]

 

 

'프로젝트' 카테고리의 다른 글

[NPM에 배포한 React Package 개선]  (0) 2024.07.03