트리 셰이킹(Tree Shaking)은 번들러가 import/export를 정적으로 분석해, 어디서도 쓰지 않는 export를 최종 번들에서 빼는 최적화다. 빌드 단계의 죽은 코드 제거라고 보면 된다.
- 전제는 ESM(ECMAScript Modules)이다. ES 모듈의 import/export는 최상위에 고정돼 있어서 실행 전에 의존 그래프를 만들 수 있다. CommonJS의
require는 런타임에 조건부로도 호출할 수 있어서 무엇이 쓰이는지 확정하기 어렵다 - 부수 효과가 있으면 지우지 못한다. 모듈을 불러오기만 해도 무언가 실행된다면 지우면 안 된다. 그래서
package.json의"sideEffects": false(또는 폴리필 같은 예외 파일 목록)로 번들러에게 안전하다고 알려 준다 - 깨지기 쉬운 경우
import * as utils처럼 namespace 전체를 가져오면 번들러가 보수적으로 판단할 수 있다utils[key]처럼 동적으로 접근하면 정적 분석이 안 된다- Babel 같은 변환 단계가 ESM을 CommonJS로 바꿔 버리면 효과가 사라진다(
@babel/preset-env의modules옵션) - TS의 enum은 IIFE(Immediately Invoked Function Expression)로 컴파일돼 지우기 어렵다
- named import와 ESM 배포판(lodash-es, date-fns)을 쓰면 효과가 좋다
| 구분 | 트리 셰이킹 | 코드 스플리팅 |
|---|---|---|
| 목적 | 안 쓰는 코드 제거 | 번들을 여러 조각으로 분리 |
| 시점 | 빌드 | 로딩 전략 |
코드 스플리팅과 동적 임포트과 같이 쓰고, 배럴 파일과 re-export은 잘못 구성하면 트리 셰이킹을 방해할 수 있다. 번들러별 차이는 번들러 참고.