💡 Bundler는 의존성이 있는 모듈 코드를 하나 혹은 여러개의 파일로 만들어주는 도구 입니다.
Chrome 등 최신 브라우저에서는 ES6 Module을 지원하기도 하지만, 모듈화 하여 작성한 코드를 브라우저에서 바로 실행할 수 없으므로 가공을 해주는 역할을 바로 이 번들러가 해주게 됩니다.
대표적인 번들러로는 Webpack, Parcel, Rollup등이 있으며, Parcel, Rollup 의 간단한 소개 및 Webpack 까지 세개의 번들러에 대한 비교를 간단하게 보여드리도록 하겠습니다.
Parcel 은 2017년에 나온 웹 애플리케이션의 번들러 입니다.
Webpack에 비해 매우 늦게 나왔지만 Webpack 보다 빠르고 설정이 필요 없는 부분에서 큰 특징이 보입니다. Webpack의 설정은 까다롭고 시간적으로 비용이 많이 들기도 하는데요.
Parcel은 설정이 필요없는 zero-configuration
이기 때문에, 빌드를 위해 번들러를 학습하는 시간을 많이 줄일 수 있는 매력적인 번들러라고도 말 할 수 있습니다.
zero-configuration
의 특징을 가지고 있는 Parcel 은 Webpack 과 달리 JavaScript 엔트리포인트를 지정해주는 것이 아니라, 애플리케이션 진입을 위한 HTML파일 자체를 읽습니다.
즉, HTML 파일을 순서대로 읽어나가면서 JavaScript, CSS, 이미지 에셋 등을 직접 참조합니다.
이는 Webpack이 에셋을 읽기 위해 JavaScript로 변환하기 위한 플러그인과 로더를 깔아야 된다는 것과 비교하자면 굉장히 자연스러운 플로우를 타고 있다는 것을 알 수 있습니다.
또한, Parcel은 캐싱을 사용하여 빌드 속도가 더 빠릅니다.
Webpack4 도 일부 캐싱을 수행하지만, 전체 캐싱 과 병렬 처리는 구현하지 않았습니다. ( 해당 내용은 여기 에서 참고해주세요! )
Parcel은 ES6 및 CommonJS 모듈 모두에 대해 Tree-shaking 역시 지원합니다. NPM 라이브러리에 있는 대부분의 코드가 여전히 CommonJS를 사용한다는 것을 감안하면 유용한 기능이라고 볼 수 있습니다. 그리고, Webpack 과 동일하게 HMR (Hot Module Replacement) 를 지원합니다.
즉, 코드가 변경되면 이를 감지하고 브라우저에 최신 코드를 반영하여 자동으로 모듈을 교체합니다.
Parcel은 많은 트랜스파일러를 내장 지원하고 있기 때문에 모듈 안의 설정 파일(.babelrc
, .postcssrc
, .posthtml
)을 발견하면 이를 자동으로 변환하여 실행하기도 합니다.
Rollup은 Webpack과 유사한 모듈 번들러이지만, 가장 큰 차이점은 ES6 모듈 형식으로 빌드 결과물을 출력할 수 있으므로 이를 라이브러리나 패키지에 활용할 수 있다는 것 입니다.
Webpack 과 Parcel은 자체 로더가 있지만 Rollup은 ES6를 기본적으로 따르기 때문 입니다.
이로 인해 Code splitting 측면에서 다른 번들러와 비교해 강점을 보입니다. 중복 제거에 특화되어 있는데, 특히 진입점(entry point)이 여러 개 있을 때 이 부분이 두드러집니다.
⚠️ 참고
진입점이 너무 많아지면 설정 이 더 복잡해 진다는 단점도 가지고 있긴 합니다.
더 자세히 보기
롤업은 진입점이 다르기 때문에 중복해서 번들될 수 있는 부분을 공통되는 알아내고 독립된 모듈로 분리해 낼 수 있습니다.
다만 파일의 해시 캐스캐이딩(hash cascading, 하나의 파일의 해시가 바뀌면 그것을 참조한 파일의 해시도 알아서 바뀜)이 약하다는 점이 약점으로 꼽히고 있습니다.
Bundler는 앞서 이야기한 것과 같이 모듈화된 코드를 브라우저에서 실행할 수 있도록 Bundle을 생성하는 것 이외에도 코드축소, Hot reloading, 코드 분할 등 여러 기능을 제공합니다.
Bundler를 선택할 수 있는 기준이 될 기능들을 나열해보면 다음과 같습니다.
Configuration 하면 바로 Zero-configuration 특징을 가지고 있는 parcel 이 생각이 날 것 입니다. Parcel을 설치하고 Parcel build를 실행하기만 하면 즉시 모든 작업들을 수행 할 수 있습니다.
반면에 Webpack이나 Rollup은 entry, output, loaders, plugins, transformations 등을 설정하는 구성 파일을 필요로 합니다.
이 중 Rollup은 상대경로를 지원하며, import/export 를 위한 node polyfills 가 있지만
Webpack은 polyfill이 없으며, 상대경로 또한 지원하지 않기 때문에 path.resolve
, path.join
을 사용합니다.
Javascript 이외의 파일을 처리하기 위해서는 Javascript 형식으로 파일을 변환한 후, Bundler로 전달을 해주어야 하는데요.
Webpack에서는 babel-loader, css-loader 등 과 같이 loader를 사용합니다.
Rollup은 플러그인을 사용합니다. ( axios 같은 경우에는 많은 플러그인을 요구하였다고 합니다. )
Parcel은 zero-configuration 특징으로 별도의 설정파일 없이 다양한 변환을 지원합니다.
Parcel은 ES6및 CommonJS 모듈 모두에 대해 Tree shaking을 지원합니다. 또한 대부분의 작업을 캐싱하여 다시 빌드할 경우 빠른 속도를 지니고 있습니다.
Rollup은 코드를 정적으로 분석하고 실제로 사용되지 않는 코드는 제외합니다. 즉 기존 도구와 모듈을 기반으로 빌드가 가능합니다.
Webpack은 Tree shaking을 ES6 모듈에서만 지원하기 때문에 package.json 에서 SideEffects
항목을 필요로 합니다. 그리고 UglifyJS와 같은 minimize tool도 필요로 합니다.
⚠️ 참고 [ 원본 ]
—————————————————
롤업과 웹팩은 정적으로 분석하기가 쉽기 때문에 ES6의 Tree-shaking 에 좀 더 초점을 맞췄지만, 플러그인을 가져오는 CoomonJS 종속성도 분석해야 합니다.
그러나 자바스크립트는 Dynamic 하다는 점을 감안할 때, 정적으로 분석할 수 없음을 의미하기도 합니다. 따라서 번들러에 지나치게 의존하는것 보다 코드 작성을 하기 전에 component 들을 시각화 하고 분석하는 것이 최상의 결과를 얻을 수 있을것 입니다.
Webpack은 최소한의 작업과 로드 시간이 더 빠르다는 점을 가지고 있습니다.
entry 설정을 사용하거나 CommonChunk 플러그인을 사용하여 청크를 중복 제거 하고 분할하거나, 모듈 내 인라인 함수를 불러와 동적으로 import 하는 Code Splitting을 활성화 하는 세가지 접근 방식이 있습니다.
Rollup의 Code splitting은 동적 로딩이나 다중 진입점과 같이 Rollup이 코드를 자동으로 청크로 분할하는 경우가 있으며 output.manualChunks 옵션을 통해 별도의 청크로 분할할 모듈을 Rollup에 명시적으로 알려주는 방법이 있습니다.
Parcel의 Code splitting은 zero-configuration 이라는 특징으로 확인 할 수 있습니다. import() 함수 구문 을 사용하여 제어되며, 이는 일반 import 문이나 require 함수처럼 작동하지만 Promise를 반환합니다. 이는 모듈이 비동기적으로 로드됨을 의미합니다.
Rollup과 Parcel은 Code-splitting 하는데에 있어서 유용하지만, 아직까지 이슈들이 보이기 때문에 안정된 상태의 웹팩을 계속 사용하는것이 좋다고도 합니다.
코드 분할이 활성화 된 동일한 코드의 마지막 경우 빌드시간이 Webpack 에서 가장 짧고 그 후는 Rollup, Parcel이 있다는 점이 있습니다.
개발 하는 동안 변경사항을 확인하기 위해 수동으로 새로 고치는 대신 작성한 새로운 코드로 앱을 업데이트 하는것이 좋습니다.
Webpack 은 wepback-dev-server
를 제공합니다. 이는 live-reload를 지원합니다.
Rollup은 Dev Server를 위해 rollup-plugin-serve
를 제공합니다. live-reload 를 위해서는 추가로 rollup-plugin-livereload
를 설치해야 합니다.
Parcel은 Dev server가 내장되어 있고, 파일이 변경할 경우 다시 빌드 합니다. 그러나 HTTP logging, Hooks, middleware를 사용할 때 이와 관련된 이슈가 발생 했었습니다.
이 기능은 코드가 실행되는 동안 전체 리로드를 할 필요없이 모듈을 추가, 제거 할 수 있는 기능을 이야기 합니다.
Webpack은 webpack-dev-server
를 통해 지원합니다.
Rollup은 rollup-plugin-hotreload
를 통해 지원합니다.
Parcel은 기본적으로 HMR을 지원합니다.
해당 사항은 Rollup 및 Parcel과 같은 번들러에서는 새로운 기능으로 느껴지므로 개발 중에 이슈가 생기는 것을 피하고 싶기 때문에 안전한 Webpack을 사용합니다.
Building a basic app and want to get it up and running quickly? Use Parcel.
Building a library with minimal third-party imports? Use Rollup
Building a complex app with lots of third-party integrations? Need good code splitting, use of static assets, and CommonJs dependencies? Use webpack.
[출처] : https://betterprogramming.pub/the-battle-of-bundlers-6333a4e3eda9
간단히 말해서, 복잡한 설정을 피하고 간단한 애플리케이션을 빠르게 만들고 싶다면 Parcel,
최소한의 서드파티로 라이브러리를 만들고 싶다면 Rollup,
많은 서드파티를 필요로 하는 복잡한 애플리케이션 에는 Webpack 을 추천한다고 합니다.
각 번들러 별 상세한 장단점이 궁금하신 분들은 이곳 을 확인하시면 좋을것 같습니다.
[ 참고 ]
도움이 되었습니다! 감사합니다 :)