ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 더 나은 개발 환경을 위한 Build tool 선택 Vite
    Build/Build 2023. 10. 22. 18:22

    이전에 작업했던 프로젝트의 유지보수를 위해 오랜만에 해당 프로젝트의 개발 서버를 올렸는데 꽤나 많은 시간이 걸렸습니다. 소스 코드를 수정했을 때도 리빌드 시간이 매우 많이 걸렸습니다. 현재 작업 중인 프로젝트에선 Vite를 도입하여 사용 중이다 보니 체감상 더 크게 느끼게 되었습니다. 이전의 프로젝트들에서 사용했던 Webpack, Rollup과 달리 개발 서버 구동 시 많은 시간을 줄이게 해 준 Vite가 무엇인지 살펴보겠습니다.

     

    Unbundled Development

    브라우저에서 ESM(ES Modules)을 사용하지 못하던 시절 JavaScript의 native 방식의 모듈 관리를 할 수 없었습니다. 그래서 번들링을 하여 모듈화 된 소스 코드를 합쳐 브라우저에서 동작할 수 있게 했습니다. 하지만 애플리케이션의 규모가 커질수록 번들링의 사이즈도 커지게 되고 이에 따른 처리 시간도 길어지게 되었습니다. 이에 따라 개발 서버를 구동하거나 소스 코드 갱신 시에 많은 시간을 뺏기게 됩니다. 그래서 등장하게 된 Unbundled Development 콘셉트의 Vite가 등장했습니다.

     

    Vite?

    기존의 번들러 기반의 환경에서 개발 서버는 cold start시 모든 소스코드에 대한 빌드 작업으로 인해 많은 시간을 소비합니다. 하지만 vite는 dependencies와 source code의 두 카테고리로 나누어 개발 서버를 구동합니다. 

    Dependencies

    개발 시 변화가 없는 Plain 한 Javascript code로 컴포넌트 라이브러리 같은 의존성 모듈들입니다. Vite의 개발 서버는 모든 소스 코드를 ESM으로 가져오기 때문에 CommonJS와 UMD 모듈을 ESM으로 변환하고 번들링을 합니다. Vite에서 dependencies는 Pre-bundling 하며 Esbuild를 사용하고 있습니다. Esbuild는 Webpack, Rollup과 달리 Go로 만들어져 기존 번들러보다 10~100배 빠른 속도를 보입니다. 

     

    Source code

    개발 시 작성하는 코드로 수정이 잦은 Non Plain 한 Javascript code입니다. Vite는 Native ESM을 이용하여 소스 코드를 제공합니다. 이는 브라우저가 ESM을 지원하기 때문에 가능하며 브라우저가 번들러 역할을 합니다. 그래서 모든 코드가 초기에 불러올 필요가 없기 때문에 브라우저에서 특정 모듈에 대한 소스 코드를 요청하면 Vite는 이를 전달합니다. 코드는 실제 브라우저에서 사용이 되어야만 처리가 됩니다. 모듈에 대한 소스 코드 수정 시에 해당 모듈과 관련된 부분만 교체하여 브라우저에서 해당 모듈을 요청하면 교체된 모듈을 전달합니다.

     

    But Production?

    하지만 브라우저에서 최근에서야 ESM을 지원하기 때문에 아직 사용하지 못하는 브라우저 환경이 있을 수 있고 필요시에 모듈을 요청하기 때문에 오버헤드가 발생할 수 있습니다. 그래서 번들링 과정이 필요하며 그리고 번들링은 Esbuild가 아닌 Rollup으로 하는데 이는 Code-splitting와 CSS와 관련된 처리가 아직 완벽하지 않기 때문입니다. Rollup에 대한 옵션은 vite config 파일을 통해 설정할 수 있습니다.

     

    Vite로 프로젝트 시작하기

    # npm
    npm create vite@latest
    
    # or
    
    # yarn
    yarn create vite

    해당 command를 통해 프로젝트를 생성하거나 아래에서 처럼 Vite supported template을 이용하여 프로젝트를 생성할 수 있습니다.

    # npm 7+, '--'를 반드시 붙여주세요
    npm create vite@latest my-vue-app -- --template vue
    
    # yarn
    yarn create vite my-vue-app --template vue

    template의 종류는 vanillavanilla-tsvuevue-tsreactreact-tspreactpreact-tslitlit-tssveltesvelte-ts가 있습니다.

     

    Vite Config

    Vite 설정을 위한 주요 config 옵션을 살펴보겠습니다.

    base

    Public Base Path로 default로 '/'의 기본값을 가집니다.

    plugins

    사용할 플러그인을 담을 배열로 프로젝트의 개발 환경에 맞게 필요한 플러그인을 추가해줍니다.

    // example
    import react from '@vitejs/plugin-react';
    import eslintPlugin from 'vite-plugin-eslint';
    
    ...
    
      plugins: [
        react(),
        eslintPlugin(),
      ],
      
    ...

     

    resolve.alias

    파일 시스템 alias를 지정합니다.

    // example
    ...
    
      resolve: {
        alias: {
          '@': path.resolve(__dirname, 'src'),
        },
      },
    
    ...


    server

    서버 관련된 옵션들로 구성할 수 있으며 주요 옵션을 살펴보겠습니다.

    • server.host
      서버가 수신할 IP주소로 default로 'localhost'의 기본값을 가집니다. 해당 옵션이 true일 경우 LAN와 공용 주소를 포함한 모든 주소를 수신할 수 있습니다.(모바일 디바이스에서 테스트 시 용이)
    • server.port
      서버 포트 번호를 지정하는 옵션으로 server.strictPort 옵션이 true가 아닐 경우 자동으로 사용 가능한 다음 포트 번호로 시도합니다.
    • server.https
      해당 옵션이 true일 경우 https를 사용합니다.
    // example
    ...
    
      server: {
        port: 5501,
        host: '0.0.0.0',
        https: true,
      },
    
    ...

     

    build

    빌드와 관련된 옵션들로 번들 시 관련된 옵션들로 구성할 수 있으며 Rollup에 대한 옵션도 지정할 수 있습니다. Rollup에 대한 옵션만 살펴보겠습니다.

    // example
    ...
    
      build: {
        rollupOptions: {
          // Rollup 설정 옵션
          // example
          plugins: [
            ...
          ],
          manualChunks: {
            ...
          },
        },
      },
    
    ...

     

    optimizeDeps

    Dependency 최적화 옵션으로 Esbuild에 대한 옵션도 지정할 수 있습니다. Esbuild에 대한 옵션만 살펴보겠습니다.

    • optimizeDeps.esbuildOptions
      Esbuild에 전달할 옵션으로 기존의 Esbuild 설정 옵션(https://esbuild.github.io/api/#simple-options)과 같으며 external, plugins 두 옵션은 Dependency 최적화와 호환되지 않기때문에 생략되었습니다.
    // example
    ...
    
      optimizeDeps: {
        esbuildOptions: {
          // Esbuild 설정 옵션
          // example
          define: {
            ...
          },
          plugins: [
            ...
          ],
        },
      },
    
    ...

     

    Env Variables and Modes

    env 변수를 client code에서 사용하기 위해 Vite는 import.meta.env 이용하여 환경 변수에 접근할 수 있도록 합니다. env 변수 유출을 막고자 VITE_가 prefix로 붙은 변수를 사용합니다.

    VITE_NODE_ENV=development
    VITE_BASE_URL=https://base.com
    // env 변수 사용
    const mode = import.meta.env.VITE_NODE_ENV
    const baseURL = import.meta.env.VITE_BASE_URL

     

    .env 파일은 각 모드에 따라 파일을 만들어 사용합니다. .env 파일의 경우 수정이 있을 경우 Vite 서버를 재 실행시켜야 합니다.

    .env                # loaded in all cases
    .env.local          # loaded in all cases, ignored by git
    .env.[mode]         # only loaded in specified mode
    .env.[mode].local   # only loaded in specified mode, ignored by git
    
    # example
    # .env.dev => package.json scripts vite --mode=dev
    # .env.real => vite --mode=real

     

    TypeScript 사용 시 vite-env.d.ts를 만들어 import.meta.env에 대한 타입 정의를 제공해주어야 합니다.

    /// <reference types="vite/client" />
    
    interface ImportMetaEnv {
      readonly VITE_APP_TITLE: string
      ...
    }

     

    마무리

    이전 프로젝트에서 Webpack과 Rollup을 Build tool로 사용했을 때와 달리 Vite를 도입하여 사용함으로써 개발 생산성이 많이 좋아졌고 설정하는 부분에 대해 많은 리소스가 줄었습니다. 기존에 Webpack과 Rollup을 사용했다면 체감이 많이 될 것입니다.

    State of JS 2022 Build Tools (https://2022.stateofjs.com/en-US/libraries/build-tools/)

     

    State of JS 2022의 Build Tools을 보면 Vite가 개발자들로부터 많은 관심과 사용하고 있음을 알 수 있습니다. 많은 개발자들로부터 검증되고 사용량도 증가하고 있습니다. 이처럼 점점 발전하고 있는 Build tool들을 적재적소에서 잘 활용하면 좋겠습니다.

     


    참고 자료

    https://vitejs.dev/guide/

    https://vitejs.dev/guide/why.html

    https://vitejs.dev/config/

    'Build > Build' 카테고리의 다른 글

    Webpack 다시 보기  (0) 2024.03.24
    What is Babel?  (0) 2024.02.16
    Migration Lerna into Nx  (0) 2023.11.18
Designed by Tistory.