라이브러리&프레임워크/Next.js

[Nextjs] Tree Shaking 트리쉐이킹 번들 사이즈 최적화

youngble 2022. 12. 22. 16:07

SEO 최적화는 어느정도 마무리가되어 서비스의 성능 최적화를 위하여 번들사이즈를 줄이기로 하였다. 

 

먼저 찾아본결과 Nextjs build후에 번들의 사이즈를 알기위해서 bundle analyzer를 사용하여 사이즈를 체크하고 사용하지않는 코드와 import들을 Tree Shaking을 진행하면 된다고 하였다.

 

현재 Nextjs로 진행하고 있기 때문에 @next/bundle-analyzer 라이브러리를 사용하여 번들사이즈를 이미지화하여 볼수 있다.

 

bundle-analyzer를 사용하여 보는 사이즈는 Stat size, Parsed size, Gzipped size 총 3개가 있다.

 

Stat: 빌드된 그대로의 상태 사이즈

Parsed: 번들된 사이즈

Gzipped: 압축된 사이즈

 

Parsed를 줄이면 Gzipped비례하여 줄어들기 때문에 Parsed size를 기본으로 줄이기를 시도하는 것이 좋다.

 

트리쉐이킹 전

위의 사진은 @next/bundle-analyzer를 사용하여 본 화면이다. 내가 줄여야할 것은 lodash 이다. Stat은 531KB, Parsed는 67.85KB 였고 사진처럼 서비스에서 많은 비율을 차지하고 있다. 실제로 lodash 를 통해 사용하고 있는 기능은 debouncethrottle 이였기 때문에 이 두가지를 제외한 나머지 기능들을 쓸때없이 build시에 다 가져올 필요가없었다. 

 

트리쉐이킹을 하는 방법은

1. SideEffects을 없애고

//package.json
{
...
"sideEffects": false,
...
}

2. babel 설정에서 es6commonjs 로 바꾸는 것을 막아주어야하고

// .babelrc
{
...
"presets": 
[
  [
  "@babel/preset-env",{"modules": false}
  ]
],
...
}

3. importcherry-picking을 통해 사용하는 기능들만 불러와야한다.

// page js
...
import throttle from "lodash/throttle"
....

cherry-pickingimport할때 예를들어 A 라는 기능을 불러와 사용할때 

import A from "Library" 라는 형식으로 쓰게 되면 Library라는 가장 큰곳에서 불러오기때문에 build시에 모두 가져오게 되므로 A가 있는 위치까지 가서 import 해주는 것이다. import A from "Library/SpecificLocation" 와 같은 형식으로 접근하여 필요한부분만 가져오는것을 cherry-picking이라고한다. 말뜻 자체가 좋은 체리들만 고르는것이기 때문에 불필요한것은 제외하고 가져온다고 생각하면된다.

 

그런데 lodash의 경우 sideEffectsbabel설정을 하고 cherry-picking을 해도 되지만 es6구문으로 쓰여진 lodash-es라는 라이브러리가 있어서 이것을 사용한다면 위의 설정을 할필요가 없다. 그렇게 되면 아주적은 사이즈로 같은 기능을 사용할 수 있다. 아래는 lodash-es를 사용하여 줄어든 사이즈를 보여준다.

위의 사진처럼 lodash-es의 사이즈는 Stat은 13.85KB, Parsed는 2.1KB 로 기존 lodash 사용때보다 Stat은 500KB줄였고 Parsed경우는 65KB줄이게 되었다. 다음 표를 통해 쉽게 이해할 수 있다.

전체 사이즈로보면 Stat: 2.43MB -> 1.91MB, Parsed : 923.89KB -> 848.25KB 로 줄어든것을 볼수 있다.

 

결론적으로 전체기준으로 Stat Size는 22.4% 감소, Parsed Size는 8.2% 감소하였고 

해당 lodash 라이브러리 기준으로는 Stat Size는 97.4% 감소, Parsed Size는 96.9% 감소하였기 때문에 번들사이즈를 대폭 줄인 최적화가 이루어졌다.