- 나무 흔들기는 불필요한 코드를 제거해 주는 기능이다.
- 웹팩은 기본적으로 나무 흔들기 기능을 제공한다.
- 웹팩이 알아서 모든 경우를 제대로 처리 못할 수 있다.
- 번들 파일 크기를 최소로 유지 하기 위해서는 사용자가 작업이 필요할 때가 있다.
export function func1() {
console.log("func1");
}
export function func2() {
console.log("func2");
}
import { func1 } from "./util_esm";
func1();
- ESM 문법으로 작성된 모듈을 ESM 문법으로 가져오고 있다.
- func1 함수만 사용하고 func2 함수는 사용하지 않는다.
- 웹팩 실행 후 번들 파일을 열어 보면 func2 함수가 보이지 않는것을 확인 할 수 있다. (Tree Shaking)
- 하지만, func2를 모듈 내부에서 호출하는 경우에 문제가 발생될 수 있다.
const arr = [];
export function func1() {
console.log("func1", arr.length);
}
export function func2() {
arr.push(10);
console.log("func2");
}
func2();
- 모듈이 평가(evaluation)될 때 func2함수가 실행된다.
- 모듈은 최초로 사용될 때 한 번 평가되는데, 이때 전역 변수 arr이 변경된다.
- func2 함수가 제거되면 func1함수는 의도한 대로 동직하지 않기 때문에 웹팩은 모듈이 평가되는 시점에서 호출되는 함수를 제거하지 않는다.
function func1() {
console.log("func1");
}
function func2() {
console.log("func2");
}
module.exports = { func1, func2 };
import { func1 } from "./util_commonjs";
func1();
- 웹팩 실행 후 번들 파일을 열어 보면 func2 함수가 보인다.
- 나무 흔들기는 다음과 같은 경우에 동작하지 않는다.
- 사용되는 모듈이 ESM이 아닌 경우
- 사용하는 쪽에서 ESM이 아닌 다른 모듈 시스템을 사용하는 경우
- 동적 임포트(dynamic import)를 사용하는 경우
import("./util_esm").then((util) => util.func1());
- 동적 임포트를 사용하면 나무 흔들기가 동작하지 않는다.
- 외부 패키지는 저마다 다양한 방식의 모듈 시스템을 사용하기 때문에 나무 흔들기가 제대로 동작하지 않을 수 있다.
- 로다시 패키지는 ESM으로 되어 있지 않기 때문에 나무 흔들기로 코드가 제거되지 않는다.
import { fill } from "lodash";
const arr = [1, 2, 3];
fill(arr, "a");
- 로다시의 fill 함수만 사용하지만, 웹팩으로 만들어진 번들 파일에는 모든 로다시의 코드가 포함된다.
- 이처럼, ESM이 아니라면 각 기능을 별도의 파일로 제공하는지 여부를 파악하여 번들 크기를 줄일 수 있다.
- 로다시는 각 함수를 별도의 파일로 만들어서 제공해 준다.
import fill from "lodash/fill";
- 코드를 바벨로 컴파일한 이후에도 ESM 문법으로 남아 있어야 한다.
- 만약 @babel/preset-env 플러그인을 사용한다면 babel.config.js 파일에서 설정을 해 줘야 한다.
const presets = [
[
"@babel/preset-env",
{
modules: false,
},
],
];
- 모듈 시스템을 변경하지 않도록 설정한다.
- ESM 문법으로 컴파일된 코드는 웹팩에서 자체적으로 사용 후 제거되기 때문에 Browser Issue는 없다.