✅ Webpack

  • 여러 개의 entry point로 의존성 그래프를 빌드하여, 각 모듈을 하나 이상의 모듈로 합침.
  • JS 이외 파일(CSS, 애셋 파일 등) 처리 시 loader 필요
  • parcel, rollup보다 code splitting 안전성 높음
  • webpack-dev-server 지원 (live-reload 지원)
  • 가장 역사가 깊으며, 레퍼런스가 많고 안정적이다
  • tree-shaking을 ES6 모듈에서만 지원하기 때문에 SideEffects 항목 별도 기재 필요

    • { sideEffects: false } 를 표시하여 사용하지 않는 export는 제거해도 괜찮음을 webpack에게 알려줌
    • 즉 side effect가 발생해도, 해당 구문을 사용하지 않는다면 제거함
  • 많은 서드파티를 필요로 하는 복잡한 애플리케이션 임

✅ Parcel

  • zero-configuration
  • 빠른 빌드 속도

    • parcel의 JS 컴파일러, CSS transformer, sourcemap은 성능을 위해 Rust로 작성되었음.
    • parcel의 JS 컴파일러는 SWC를 기반으로 트리셰이킹, 핫-리로딩 등을 지원
    • SWC는 Rust 기반
    • ES6 및 CommonJS 모듈 모두에 대해 tree-shaking을 지원
    • 워커 쓰레드를 사용한 병렬 빌드
    • 캐싱을 사용한 빠른 빌드 속도
    • 모든 것은 캐시됨(transformation, dependency resolution, bundling, optimizing 등)
    • 코드가 바뀌면 부분적으로 캐시를 무효화. → webpack보다 최대 20배 빠름 (캐시 사용 시)
  • 플러그인 없이 JS, CSS, HTML, 파일 애셋, 그 외 많은 것들에 대한 지원을 기본으로 제공

    • JS 이외 파일 처리 시에도 별도의 loader 불필요
    • 앱 진입을 위한 HTML을 직접 읽을 수 있음 -0 JS 엔트리포인트를 지정할 필요가 없음
  • 필요하다면 Babel, PostCSS, PostHTML같은 트랜스파일러들을 기본으로 지원

    • .babelrc, .postcssrc 등의 파일을 발견하면 자동으로 변환(node_modules까지도)
  • 동적 import 문을 사용해서 output 번들을 분할 할 수 있음

    • 이를 통해 초기 로드시 필요한 것들만 로드할 수 있음
    • dev에서는, 브라우저에서 요청이 있을 때까지 번들링을 지연할 수 있음
    • 실제 필요한 페이지만 로드하며, 적절하게 code split 시 dev server 실행 시간을 줄여줌
  • HMR 기본 지원

    • React, Vue 사용 시에도 fast refresh 가능
  • dev server 기본 제공
  • 프로덕션 자동 최적화

    • tree shaking: 동적 모듈 import, 공용 모듈, CSS 모듈에 대해서도 적용됨
    • 최소화 및 난독화: JS, CSS, HTML, SVG minifier를 제공
    • 이미지 최적화 지원
  • 코드 스플리팅

    • 앱의 여러 파트에서 동일한 모듈에 의존하고 있다면, 해당 모듈을 자동으로 별도의 번들로 분리해줌
    • CSS도 마찬가지로 지원
  • 모든 output 파일에 대해 content hash를 제공함
  • 브라우저 캐시에 유리

✅ Rollup

  • ES6 모듈(ESM) 형식으로 빌드 결과물을 생성함. (webpack은 only CommonJS 형태만 가능)
  • 여러 개의 모듈을 하나의 단일 모듈로 합쳐서 코드를 최적화함

    • 진입점을 다르게 설정하여 번들링 가능
    • 코드들을 동일한 수준으로 호이스팅 한 후 한 번에 번들링을 진행
    • code splitting에 강점 (중복 제거에 특화)이 있음
    • cf) webpack의 ModuleConcatenationPlugin이 비슷한 역할
  • 트리셰이킹 기본 지원

    • JS 이외 파일 처리 시 플러그인 사용코드를 정적으로 분석하여 미사용 코드는 제외함
  • 데브서버 지원, 하지만 live-reload를 위해서는 추가 플러그인 설치가 필요함
  • HMR: 플러그인으로 지원
  • 파일의 해시 캐스캐이딩(hash cascading; 하나의 파일의 해시가 바뀌면 그것을 참조한 파일의 해시도 알아서 바뀜) 이 약함
  • CommonJS 종속성이 많음
  • 서드파티 라이브러리 통합이 어려움

✅ Esbuild

  • Go로 작성되어 있어 빠른 번들링 속도
  • 코드 파싱, 출력과 소스맵 생성을 모두 병렬로 처리함
  • CommonJS, ES6, JSX, Typescript, Tree shaking을 지원함

    • ES5 이하의 문법을 아직 100% 지원하지 않기 때문에, IE 대응이 어려움
  • 빌드 도구이지 통합 툴이 아니라서, 기존의 툴(webpack, parcel, rollup 등)을 사용해야 함 → snowpack 또는 vite와 결합하여 사용함
  • 버전 1.0도 안됨
  • 대규모 프로덕션 사이트에는 사용 지양
  • live/hot reload(HMR) 지원하지 않음
  • PostCSS와 기타 전처리기 자동 변환 X
  • AST 변환 작업을 지원하지 않음 (플러그인 필요)

✅ Vite

  • react, vue, preact를 지원(CRA, vue-cli의 대체재)
  • 사전 번들링(Pre-bundling)

    • esbuild를 사용하여 기존 번들링 대비 10-100배 빠른 속도
  • Native ESM 제공 (dev)

    • 번들링 없이 온디맨드(on-demand)로 파일을 제공할 수 있음
    • JSX, CSS 또는 Vue/Svelte 컴포넌트와 같이 컴파일링이 필요하고, 수정이 잦은 Non-plian JS 소스코드 → Native ESM을 이용해 소스코드를 제공하여, 브라우저를 번들러처럼 사용함
  • production에서는 rollup을 사용

    • production에서는 esbuild가 아닌 번들링 방식을 사용하는 이유는 프로덕션에서 번들 되지 않은 ESM을 가져오는 것은 중첩된 import로 인한 추가 네트워크 통신으로 인해 여전히 비효율적임
    • 프로덕션 환경에서 최적의 로딩 성능을 얻으려면 트리 셰이킹, 지연 로딩 및 청크 파일 분할(더 나은 캐싱을 위해)을 이용하여 번들링 하는 것이 더 좋음
    • Esbuild는 번들링에 필수적으로 요구되는 기능인 코드 분할(Code-splitting) 및 CSS와 관련된 처리가 아직 미비함
  • esbuild(dev)와 rollup(prod)으로 구성되어 있음
  • dependencies(패키지)와 소스코드를 분리하여 빌드함

    • 패키지: 설치 후에 내용이 바뀌지 않음
    • 소스코드: 빈번하게 바뀜
  • 빠른 HMR 지원

    • 번들러가 아닌 native ESM을 사용하기 때문(브라우저가 곧 번들러)
    • 모듈 수정 시 해당 부분만 교체하고, 브라우저에서 해당 모듈을 요청할 때까진 사용되지 않음
  • 기본적으로 TypeScript, JSX, CSS 등을 지원

    • 내부적으로 esbuild를 사용
  • 빌드 최적화

    • CSS를 자동으로 추출해 파일로 분리
    • 빌드 시 Direct import 구문에 대해 <link ref="modulepreload"> 디렉티브를 이용해 미리 모듈을 캐싱하도록 자동으로 변환
    • 모든 Direct import 구문을 preload하여 불필요한 네트워크 요청을 줄임
  • tree-shaking, 코드 스플리팅을 지원하지 않음
  • rollup 번들러를 사용한 pre-configured 빌드 환경에서 rollup config를 뜯어내기가 아주 어려움

참고