Lighthouse of FE biginner

[React] Vite 라이브러리 모드 셋팅하기 본문

[WEB] 프론트엔드

[React] Vite 라이브러리 모드 셋팅하기

[FE] Lighthouse 2024. 8. 9. 09:49

Overview

Vite는 웹 애플리케이션을 빠르게 만들수 있도록 도와주는 프론트엔드 개발 툴 입니다. 내부적으로 ESM을 사용하며 ESBuild를 활용해 디펜던시를 빠르게 사전 번들링을 수행하고, rollUp을 사용해 빌드를 효율적으로 진행합니다.
 
오늘 포스팅에서는 Vite 템플릿을 활용해 라이브러리를 제작할 수 있도록 초기 셋팅 진행 과정을 소개해드리겠습니다.
아래 과정을 천천히 따라와주세요!

https://ko.vitejs.dev/guide/build.html#library-mode

 

환경 구축

먼저 Vite 환경을 구축해주세요. 환경 구축은 일반적인 Vite 템플릿 생성 과정과 동일합니다.

pnpm create vite my-react-lib --template react-ts

 
라이브러리를 구축하며 Storybook을 활용해 볼 예정입니다. 아래 공식문서대로 설정을 진행해주세요!

https://storybook.js.org/docs/get-started/frameworks/react-vite?renderer=react

 

디렉토리 구조 변경

먼저 디렉토리의 구조를 변경할 예정입니다. 우리는 라이브러리 모드로 진행할 예정이기 때문에 웹 어플리케이션을 위한 진입점을 필요하지 않습니다.
 
1. main.tsx, App.tsx 파일들을 제거해주세요.
2. 새로운 라이브러리 진입점 파일을 생성해주세요. (main.ts)
3. Storybook 탬플릿인 stories 디렉토리에서 components 폴더를 src 하위로 구조 변경해주세요.
 

vite.config.ts 파일 수정

플러그인

1. 의존성 설치

pnpm install -D vite-plugin-lib-inject-css vite-plugin-dts glob

 
@vitejs/plugin-react
기본적으로 React를 사용하기 때문에 위 플러그인은 설정되어 있습니다. 만약 babel 대신 swc를 사용하고 싶다면 아래 라이브러리로 대체한 후 import 해 넣어주시면 됩니다.

@vitejs/plugin-react-swc

 
vite-plugin-lib-inject-css
빌드 과정에서 CSS를 JavaScript 파일에 포함시킬 수 있도록 도와줍니다. 라이브러리를 배포할 때 CSS 파일을 별도로 관리하지 않고, JS 파일 안에 포함시키는 경우에 유용합니다.

vite-plugin-dts
타입스크립트 정의 파일(.d.ts)을 자동으로 생성해주는 플러그인입니다. exclude 옵션을 통해 특정 파일(예: .stories.tsx)을 제외할 수 있습니다. 이로 인해 라이브러리에 불필요한 파일이 포함되지 않도록 할 수 있습니다.
 
glob
glob 패키지는 파일 시스템에서 파일을 검색하기 위한 패턴 매칭 기능을 제공하는 Node.js 라이브러리입니다.
 
2. 플러그인 설정
 
stories 파일은 빌드에서 제외될 파일입니다. 그렇기 때문에 dts파일을 생성하지 않도록 제외시켜줍시다.

plugins: [
    react(),
    libInjectCss(),
    dts({ exclude: ["**/*.stories.tsx", "**/*.stories.ts"] }),
],

build

Vite의 빌드 옵션을 설정해봅시다. 먼저 라이브러리 모드로 빌드를 할 것 이기에 lib 옵션을 설정해줍시다.

build: {
  lib: {
    entry: resolve(__dirname, "src/main.ts"),
    formats: ["es"],
    name: "index",
    fileName: (format) => `index.${format}.js`,
  },

 

  • entry: 라이브러리의 진입점 파일을 지정합니다. 이 예제에서는 src/main.ts 파일이 엔트리로 사용됩니다.
  • formats: 라이브러리를 빌드할 출력 형식을 지정합니다. 여기서는 ES 모듈 형식(ESM)만 사용됩니다.
  • name: 라이브러리의 이름을 정의합니다.
  • fileName: 출력되는 파일 이름을 지정하는 함수입니다. 각 형식에 따라 파일 이름을 지정할 수 있습니다.

rollupOptions

rollUp 번들러가 수행합니다. 그렇기 때문에 롤업의 설정을 할 필요가 있습니다.

rollupOptions: {
  external: ["react", "react-dom", "react/jsx-runtime"],
  input: Object.fromEntries(
    globSync([
      "src/components/**/index.tsx",
      "src/hooks/**/index.ts",
      "src/main.ts",
    ]).map((file) => {
      const entryName = path.relative(
        "src",
        file.slice(0, file.length - path.extname(file).length)
      );
      const entryUrl = fileURLToPath(new URL(file, import.meta.url));
      return [entryName, entryUrl];
    })
  ),
  output: {
    entryFileNames: "[name].js",
    assetFileNames: "assets/[name][extname]",
    globals: {
      react: "React",
      "react-dom": "ReactDOM",
      "react/jsx-runtime": "react/jsx-runtime",
    },
  },
},

 

  • external: 이 설정은 빌드 결과물에서 외부 라이브러리를 제외합니다. 즉, React와 관련된 라이브러리는 번들에 포함되지 않고, 외부에서 가져오도록 처리됩니다.
  • input: 다중 엔트리 포인트를 지정합니다. globSync를 통해 지정된 패턴에 맞는 파일들을 찾아서 엔트리로 설정합니다.
  • output: 출력 파일의 이름 형식 및 글로벌 변수 설정을 정의합니다. entryFileNames와 assetFileNames를 통해 파일 이름 규칙을 정의하며, globals는 Vite 설정에서 외부 의존성(external dependencies)에 대한 전역 변수 매핑을 정의하는 옵션입니다.

copyPublicDir

빌드 과정에서 public 디렉토리의 파일을 복사하지 않도록 설정합니다. 이 설정은 라이브러리를 빌드할 때 불필요한 파일이 포함되지 않도록 합니다.
 

main.ts

라이브러리에서 작업한 컴포넌트를 외부로 내보내기 위해 라이브러리의 배럴 파일을 만들어줍시다. 해당 파일은 라이브러리의 진입점 이기도 합니다.

export { useTableSelection } from "./hooks/useTableSelection";
export type {
  UseTableSelectionResult,
  UseTableSelectionProps,
  RowSelection,
} from "./hooks/useTableSelection";

export { Dialog } from "./components/dialog";
export type { DialogProps } from "./components/dialog";

 

package.json 수정

{ 
  ...
  "files": [
    "dist"
  ],
  "main": "./dist/main.js",
  "module": "./dist/main.js",
  "types": "./dist/main.d.ts",
  ...
}

 

  • files: 패키지 배포 시 포함할 파일/디렉토리를 지정합니다.
  • main: CommonJS(CJS) 환경에서 패키지를 사용할 때 기본으로 불러올 파일을 지정합니다.
  • module: ES 모듈(ESM) 환경에서 패키지를 사용할 때 기본으로 불러올 파일을 지정합니다.
  • types: TypeScript 환경에서 패키지를 사용할 때 참조할 타입 정의 파일을 지정합니다.

 

build 수행

마지막으로 진행한 설정을 바탕으로 빌드를 수행해봅시다! 빌드 스크립트를 수행하면 타입스크립트 컴파일러가 타입스크립트 컴파일을 수행하고 Vite 빌드를 수행합니다.

// build: tsc && vite build
pnpm run build


 빌드 수행 결과 원하는 빌드 결과물을 확인할 수 있습니다!
 

마치며

라이브러리 모드로 설정을 하는데 있어서 아주 복잡한 과정을 거치지는 않았습니다.
환경에 따라서 다양한 변수가 존재할 수 있어서 위 과정을 그대로 거친다고 해도 생각한대로 셋팅이 진행되지 않을 수도 있습니다.
 
만약 타입스크립트 컴파일에서 문제가 발생한다면 아래 레포지토리의 tsconfig 파일을 참고해주세요!
읽어봐주셔서 감사합니다.

https://github.com/kangactor123/radix-storybook