최근 clippler의 bootstrap-vue module 번들링 최적화를 위해 tree shaking 작업을 진행하면서 webpack-bundle-analyzer 의 번들링 size가 최적화 이전보다 증가하는? 희한한 경험을 했다. 그래서 webpack-bundle-analyzer의 size가 정확히 무슨 의미인지 정의해보는 글을 써볼려고 한다. (왜 더 증가했는지 알게되는건 덤으로)
Webpack Bundle Analyzer
인터랙티브하게 줌(zoom)이 가능한 트리맵을 통해 번들링된 파일 사이즈를 시각화해주는 Webpack Plugin 이다.
사용법
사용법은 다음 포스트에서 다뤄볼 생각이므로 여기선 간단히…
1 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; |
그럼 아래 gif처럼 webpack의 번들링 작업 후 분석된 내용을 treemap으로 보여준다.
본론; 그래서 size의 정의는…
몇개의 국내외 블로그들을 봤는데 약간… 겉핥기식의 글도 많았고, 서로 다른 주장을 하는 글들도 많아서 돌고 돌아서 공식 깃허브 페이지와 Issue에서 관련 글이 있는걸 보기로 했다.
https://github.com/webpack-contrib/webpack-bundle-analyzer#size-definitions
크기 정의 (Size definitions)
stat
This is the “input” size of your files, before any transformations like minification. It is called “stat size” because it’s obtained from Webpack’s stats object.
최소화와 같은 어떠한 변형이 일어나기 전의 파일들의 “input” 크기입니다. Webpack’s stats 객체 로부터 얻었기 때문에 “stat size”라고 부릅니다.
Webpack’s stats 이란
The
stats
option lets you precisely control what bundle information gets displayed. This can be a nice middle ground if you don’t want to use quiet or noInfo because you want some bundle information, but not all of it.
stats
(통계)을 사용하면 표시되는 번들 정보를 정확하게 제어할 수 있고, quiet
또는 noInfo
를 사용하지 않을 경우, 모든 번들 정보가 아닌 일부 정보를 원한다면 좋은 중간 지점일수 있습니다.
parsed
This is the “output” size of your files. If you’re using a Webpack plugin such as Uglify, then this value will reflect the minified size of your code.
파일의 “output(출력)” 크기 입니다. 만약 Uglify와 같은 웹팩 플러그인을 사용한다면, 이 값은 우리 코드의 최소화된 사이즈를 반영합니다.
gzip
This is the size of running the parsed bundles/modules through gzip compression.
gzip 압축(compression)을 통해 분석된 번들/모듈을 실행하는 크기입니다.
다음으로 webpackBundleAnalyzer 깃허브 이슈 중 각 Size에 대한 정의를 물어본 이슈를 보자.
Stat size, parsed size…? #61
비록 2017년 issue이지만 Vote 수가 74개다. 그만큼 비슷한 고민을 한 개발자들이 많았을테고 답변 comment 또한 유의미했을거라 생각한다..
질문
“stat size”, “parsed size,” 등에 대한 정확한 의미를 어디에서 찾아볼 수 있을까요? 만약 다른 곳에 있다면 README에 정의를 추가하면 행복할거 같습니다 (생략)…
Thanks for the great plugin.
best 답변
Stat sizes are fetched from the webpack stats object directly, and use the actual source code of your modules as-is and report the size before minification or gzip
Stat sizes는 웹팩 stats(통계) 객체에서 직접 가져오고, 모듈의 실제 소스코드를 있는 그대로 사용하고 minification 또는 gzip 이전의 크기를 제공합니다.
Parsed size is calculated by reading the actual compiled bundle files and making a link back to the modules from webpack stats file. So if you use a minifier, such as UglifyJS, the parsed size shows you the size after minification.
Parsed size는 실제 컴파일된 번들 파일들을 읽고 Webpack stats(통계) 파일로부터 모듈로 돌아가는 링크를 만듦으로써 계산됩니다. 그래서 우리가 UglifyJS와 같은 압축기를 사용한다면, Parsed size는 최소화 이후의 사이즈를 보여줄 것입니다.
Likewise, the gzip size is calculated by reading the actual compiled bundle files and running gzip for each one of the module sources separately. Thus the gzip size shows you the size after minification and gzip, but it isn’t a 1-to-1 mapping with the actual file sizes as gzipping each module separately yields less “wins” in terms of compression as the separate sources have less opportunities for gzip to compress together.
마찬가지로, gzip size는 실제 컴파일된 번들 파일을 읽고 모듈 소스 각각에 대해 gzip을 실행한 것에 대해 계산한 크기입니다. 따라서, gzip 크기는 minification and gzip 이후의 사이즈를 보여줍니다. 그러나 실제 이것이 1 대 1 맵핑은 아닙니다. 각 모듈을 개별적으로 gzip으로 압축하면 개별 소스들을 gzip으로 함께 압축할 기회가 적기 때문에 압축 측면에서 “승리”가 적기 때문에 실제 파일 크기와 1:1 매핑이 아닙니다.
정리
위의 정의를 통해 추측하는건 Tree Shaking을 통한 모듈 최적화 이전보다 Parsed, gzip 사이즈가 늘어는건
- “output”으로 나온 코드 중 최소화 등의 transformations 과정이 적용된 소스량이 Global Import 방식보다 증가했다.
- 그리고 이전보다 1:1 맵핑할 수 있기 때문에 gzip Size가 더 크게 계산된 것이다.
위 글들을 바탕으로 이해한 것은 즉, 이전의 Global Import 방식의 bootstrap-vue 소스들이 1:1 맵핑이 아니어서 오히려 Tree Shaking 방식의 Individual Import 방식의 소스들보다 크기가 적게 계산됐을 것으로 생각된다.
이다. 아직 정확하게 맞는지는 모르겠지만 아무튼 이정도로 추측성? 이해?를 해보았고, 다른 실험들을 통해 Bundle Size가 줄어드는 경우가 있는지 혹은 bootstrap-vue의 Tree Shaking Import한 파일을 변경해보는 방법도 고려해봐야겠다.