크로스 브라우징
: 브라우져마다 지원하는 환경이 다르기에 해석할 수 있는 언어 또한 다르다. (예를들어 Safari는 최근 몇년전만 해도 Promise.prototype.finally 메소드를 사용 할 수 없었다.)
이러한 크로스 브라우징
을 해결할 수 있는게 바로 트랜스파일러 Babel
이다.
Babel
은 ECMAScript2015 이후 최신 문법으로 작성한 코드를 모든 브라우저에서 동작하도록 호환성을 지켜준다. (ts, jsx, tsx 등도 포함)
아래의 명령어를 통해 Babel
을 설치해준다.
$ npm install @babel/core @babel/cli
$ yarn add @babel/core @babel/cli
@babel/core
: 핵심적인 동작이 담겨있는 바벨 코어
@bable/cli
: 커맨드라인 명령어를 지원하기 위한 바벨 CLI
이제 간단한 테스트를 위해 ES6 문법인 const
와 arrow function
을 사용해 테스트 파일 babel-test.js
를 만들었다.
// babel-test.js
const alert = (msg) => window.alert(msg);
아래의 명령어를 통해 트랜스파일 을 실행해보았더니
$ npx babel babel-test.js
똑같은 결과가 나왔다.
Babel
의 동작은 아래의 3단계로 구분된다.
파싱 (Parsing)
: 코드를 읽고 추상 구문 트리 (AST)로 변환하는 단계변환 (Transforming)
: 추상 구문 트리를 변경하는 단계출력 (Printing)
: 변경된 결과물을 출력하는 단계이 과정에서 사실 Babel
은 Parsing
과 Printing
만 담당하게 되고 Transforming
은 Plugin
이 처리하게된다.
아래는 const
를 var
로 바꿔주는 간단한 Plugin
을 구현한 예시코드이다.
// my-babel-plugin.js
module.exports = function myBabelplugin() {
return {
visitor: {
VariableDeclaration(path) {
console.log("VariableDeclaration() kind:", path.node.kind);
if (path.node.kind === "const") {
path.node.kind = "var";
}
},
},
};
};
이제 아래의 명령어를 통해 Plugin
을 적용시켜 다시 트랜스파일 을 실행해보았더니
$ npx babel babel-test.js --plugins './my-babel-plugin.js'
const
키워드가 var
로 잘 바뀐것을 확인 할 수 있다.
이해를 위해서 이처럼 Plugin
을 작성해보았지만, 사실 Babel
사용시 Plugins
를 작성하는 일은 거의 드물고, 제공하는 Plugin
들을 사용한다.
아래는 대표적인 Babel
의 Plugin
들이다.
@babel/plugin-transform-block-scoping
@babel/plugin-transform-arrow-functions
@babel/plugin-transform-strict-mode
위의 Plugin
들을 설치해주고 babel
의 설정파일인 babel.config.js
를 만들어준다.
// babel.config.js
module.exports = {
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-strict-mode",
],
};
이제 npx babel babel-test.js
의 기본 명령어로 실행해도 위의 Plugin
들이 적용되어 use strict
, var 로 변환
, arrow function 변환
이 적용된 것을 확인할 수 있다.
preset
:Babel
에서 목적에 맞게 여러개의 플러그인을 모아놓은 것 (n개의 plugin이 1개의 preset)
위에서 사용한 3개의 plugin
들로 custom preset
을 만들어보았다.
// my-babel-preset.js
module.exports = function myBabelPreset() {
return {
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-strict-mode",
],
};
};
위에서 만든 preset
은 plugin
과 마찬가지로 babel.config.js
에서 설정해주면 된다.
// babel.config.js
module.exports = {
presets: ["./my-babel-preset.js"],
}
아래는 Babel
의 대표적인 preset
들이다.
preset-env
: ECMAScript2015+ 를 변환할 때 사용preset-flow
: flow를 변환preset-react
: react를 변환preset-typescript
: ts를 변환아래처럼 타겟 브라우저를 설정해줄수도있다. (해당 버전에서 호환되는 코드로 트랜스파일)
module.exports = {
presets: [
[
"@babel/preset-env",
{
targets: {
chrome: "79",
ie: "11",
},
},
],
],
};
만들었던 babel-test.js
의 코드를 아래와 같이 수정한 뒤, babel
을 적용시켜 실행해보면
// babel-test.js
new Promise();
아래와 같이 변화가 없는 결과를 볼 수 있다.
Promise
는 ES6
객체이고, Babel
은 ECMAScript2015+ 에서 SCMAScript5 버전으로 변환할 수 있는 것들만 변환하고, 그렇지 못한 것들은 polyfill
이라는 코드 조각들을 추가해서 해결해야 한다.
// babel.config.js
module.exports = {
presets: [
[
"@babel/preset-env",
{
targets: {
chrome: "79",
ie: "11",
},
useBuiltIns: "usage", // "usage", "entry", "false
corejs: {
version: 3,
},
},
],
],
};
useBuiltIns
: 어떤 방식으로 polyfill
을 사용할지 설정하는 옵션 (기본 false)core-js
를 모듈로 가져오며 yarn add core-js@3
명령어를 통해 core-js
를 설치해줘야한다.)polyfill
설정 후 실행해보면, 아래와 같이 코드조각들을 가져온것을 확인할 수 있다.