Babel preset-env 이해하기
Babel은 최신 JavaScript 문법을 구버전 브라우저에서도 동작하도록 변환해주는 트랜스파일러다. @babel/preset-env는 그중에서도 가장 많이 쓰는 프리셋이다.
preset이 뭔가
Babel은 플러그인 기반으로 동작한다. 화살표 함수를 변환하려면 @babel/plugin-transform-arrow-functions, 클래스를 변환하려면 @babel/plugin-transform-classes... 이런 식으로 기능마다 플러그인이 따로 있다.
근데 이걸 하나하나 설치하고 설정하기 귀찮으니까, 자주 쓰는 플러그인들을 묶어놓은 게 preset이다.
preset-env가 하는 일
@babel/preset-env는 타겟 브라우저에 맞춰서 필요한 변환만 해준다.
예를 들어 Chrome 최신 버전만 지원하면 화살표 함수는 그대로 두고, IE11까지 지원해야 하면 일반 함수로 변환한다. 불필요한 변환을 안 하니까 번들 크기도 줄고 성능도 좋아진다.
설치
npm install @babel/core @babel/preset-env -D
기본 설정
babel.config.js 또는 .babelrc에 설정한다.
// babel.config.js
module.exports = {
presets: ['@babel/preset-env']
};
이대로 쓰면 기본값으로 동작하는데, 타겟을 지정하지 않으면 모든 ES6+ 문법을 ES5로 변환한다. 보통은 타겟을 지정해서 쓴다.
targets 옵션
지원할 브라우저를 지정한다.
module.exports = {
presets: [
['@babel/preset-env', {
targets: {
chrome: '80',
firefox: '78',
safari: '14',
edge: '80'
}
}]
]
};
browserslist 쿼리를 쓸 수도 있다.
targets: '> 1%, last 2 versions, not dead'
또는 package.json에 browserslist 필드를 추가하면 preset-env가 자동으로 읽는다.
{
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
useBuiltIns 옵션
Promise, Array.includes 같은 새로운 API는 문법 변환만으로 안 된다. 폴리필이 필요하다.
useBuiltIns 옵션으로 폴리필을 어떻게 처리할지 정한다.
false (기본값)
폴리필을 자동으로 추가하지 않는다. 직접 import해야 한다.
entry
엔트리 파일에서 core-js를 import하면, 타겟 브라우저에 필요한 폴리필만 import문으로 바꿔준다.
// 변환 전
import 'core-js/stable';
// 변환 후 (타겟에 따라 필요한 것만)
import 'core-js/modules/es.promise';
import 'core-js/modules/es.array.includes';
// ...
설정:
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'entry',
corejs: 3
}]
]
};
usage
코드에서 실제로 사용하는 기능만 폴리필을 추가한다. import문 없이도 자동으로 넣어준다.
// 소스 코드
const arr = [1, 2, 3];
arr.includes(2);
// 변환 후
import 'core-js/modules/es.array.includes';
const arr = [1, 2, 3];
arr.includes(2);
설정:
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3
}]
]
};
usage가 번들 크기 최적화에 유리하다. 대신 서드파티 라이브러리가 폴리필을 필요로 하는데 감지를 못하는 경우가 있어서, 상황에 따라 entry를 쓰기도 한다.
modules 옵션
모듈 시스템을 어떻게 변환할지 정한다.
module.exports = {
presets: [
['@babel/preset-env', {
modules: false
}]
]
};
'auto'(기본값): 자동 감지false: ES 모듈 유지'commonjs': CommonJS로 변환
Webpack이나 Rollup 같은 번들러를 쓴다면 false로 설정하는 게 좋다. ES 모듈을 유지해야 트리 쉐이킹이 제대로 동작한다.
실제 설정 예시
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: '> 1%, last 2 versions, not dead',
useBuiltIns: 'usage',
corejs: 3,
modules: false
}]
]
};
Webpack과 함께 쓸 때:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}
]
}
};
정리
targets: 지원할 브라우저 범위 지정useBuiltIns: 폴리필 처리 방식 (entry또는usage)modules: false: 번들러와 함께 쓸 때 트리 쉐이킹을 위해 설정
타겟 브라우저에 맞춰서 최소한의 변환만 하기 때문에, 무조건 ES5로 내리는 것보다 번들 크기가 작아진다.