ES6 에서 ES5로 컴파일 해주는 트랜스 파일러입니다.
컴파일러 : 한 언어로 작성된 소스 코드를 다른 언어로 바꾸는 것입니다.
트랜스 파일 :
a라는 소스코드 파일을 읽어서 b라는 소스코드 파일로 변환시키는 행위, 컴파일 했을 때 , 추상화 수준이 같은 코드로 변환합니다.
구버전의 소스코드를 신버전에 호환하는 형식으로 바꾸기도 하며, 신버전의 소스를 구버전에 호환되게 하기도 하는것이 목적입니다.
설치하기
npm install @babel/core @babel/cli
js 파일을 하나 만들고 babel로 실행시켜 보겠습니다.
const alertMessage = (msg)=>{window.alert(msg)}
실행하기
npx babel myJS.js
바벨 명령어를 통해 트랜스 파일을 하게 되면 똑같은 결과가 나오게 됩니다. 일단 바벨의 빌드 단계부터 알아봅시다.
파싱 : 코드를 읽고 추상 구문 트리로 변환하는 단계를 파싱이라고 합니다. 빌드 작업을 처리하기 적합한 구조인데, 컴파일러 이론에 사용되는 개념입니다.
변환 : 추상 구문 트리를 변경하는 것이 변환 단계 입니다. 실제 코드를 변경합니다.
출력 : 변경된 결과물을 출력합니다.
앞선 작업에서 바벨이 변환을 못한 것 같은데 바벨은 파싱과 출력만 담당하고 , 변환작업은 '플러그인'이 처리하게 됩니다.
= 바벨의 코드 변환은 플러그인 혹은 preset 설정 파일에 적용함으로써 활성화 됩니다.
custom-babel-plugin.js 를 만들면서 알아보겠습니다.
module.exports = function customBabelPlugin() {
return {
// 보통 visitor라는 객체를 만들게 됨
visitor: {
Identifier(path) {
const name = path.node.name;
// 바벨이 만든 AST 노드 출력
console.log("change name:", name);
// 변환 작업: 코드 문자열을 역순으로 변환
path.node.name = name.split("").reverse().join("");
},
},
};
};
바벨의 플러그인은 오브젝트 내부에 visitor : 프로퍼티를 반환하는 함수로 시작됩니다.
visitor 프로퍼티 내부에 Identifier 매소드를 구현합니다.
Identifier 가 받을 path 에서는 node.name 등 정보를 가져올 수 있습니다.
이제 실행을 해보겠습니다. 바벨의 여러 명령어 중 plugins 명령어를 이용하겠습니다.
npx babel myJS.js --plugins './custom-babel-plugin.js'
=> 결과창
change name:alertMessage
change name:msg
change name:window
change name:alert
change name:msg
const egasseMtrela = gsm => wodniw.trela(gsm);
AST 노드의 토큰 하나하나를 path.node.name 으로 가지고 있습니다 . 그리고 이것을 뒤집어 출력해줍니다.
이런식으로 js 파일의 코드를 하나씩 확인하면서 바꿔줄 수 있습니다.
이번에는 const를 var로 바꾸는 플러그인을 만들어 보겠습니다.
module.exports = function customBabelPlugin() {
return {
visitor: {
VariableDeclaration(path) {
if (path.node.kind === "const") {
path.node.kind = "var";
}
},
},
};
};
위와 동일하게 실행시키면 아래와 같이 바뀌게 됩니다.
구형 브라우저에서 호환되지 않는 const를 var로 변환하기 때문에 그 브라우저에서도 사용할 수 있게 됩니다.
var alertMessage = (msg)=>{window.alert(msg)}
우리가 만들었던 customBabelPlugin은 이미 플러그인 형태로 제공되고 있습니다.
babel-plugin-transform-block-scoping 에서 let을 var로 바꿔주는 것을 확인할 수 있습니다.
npm install @babel/plugin-transform-block-scoping
npx babel myJS.js --plugins @babel/plugin-transform-block-scoping
결과
var alertMessage = (msg)=>{window.alert(msg)}
const 가 var 로 바껴있는 것을 확인할 수 있습니다.
마찬가지로 ()=> 함수 또한 트랜스컴파일해줄 수 있는 플러그인을 설치하고 같이 실행해 보겠습니다.
plugin-transform-arrow-functions
콤마(,) 를 이용해 여러개를 같이 사용할 수 있습니다
npx babel myJS.js --plugins @babel/plugin-transform-block-scoping,@babel/plugin-transform-arrow-functions
결과
var alertMessage = function(msg){
return window.alert(msg);
}
자바 스크립트 문법에 엄격 모드를 적용시키는 플러그인입니다.
babel.config.js 파일을 메인에 생성합니다.
module.exports = {
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-strict-mode",
],
};
실행해보겠습니다.
npx babel myJS.js
를 바로 실행해도 플러그인을 적용한 결과로 나옵니다.
많은 양의 바벨 플러그인을 사용해야 하는데, 바벨의 플러그인 설치는 시간과 관리가 힘듭니다. 그래서 목적에 맞게 여러개의 플러그인을 모아놓은 것을 프리셋이라고 부릅니다.
custom-babel-preset.js 파일을 만들고,
module.exports = function customBabelPreset() {
return {
plugins: [
"@babel/plugin-transform-block-scoping",
"@babel/plugin-transform-arrow-functions",
"@babel/plugin-transform-strict-mode",
],
};
};
babel.config.js 내용도 바꿔줍니다.
module.exports = {
preset: ["./custom-babel-preset.js"],
};
실행시켜주면, 뭉쳐진 preset이 잘 적용이 됩니다.
자주 사용되는 프리셋 몇개가 있습니다.
preset-env : ES6 를 변환할 때 사용됩니다.
preset-flow : flow 를 변환합니다.
preset-react : react를 변환합니다.
preset-typescript : typescript를 변환합니다.
babel.config.js 작성
module.exports = {
presets: [
[
"@babel/preset-env",
{
targets: {
chrome: "79",
},
},
],
],
};
targets 가 추가 되었습니다. 결과는 어떨 까요 ? 화살표 함수와 const 가 둘다 그대로 적혀있습니다.
왤까요? chrome 이 최신 문법들을 사용이 가능하기 때문에 그대로 사용되는 것입니다.
하지만 이 targets에 ie가 적힌다면 어떻게 될까요?
targets: {
chrome: "79",
ie: "11"
}
ie 에서 호환이 되기 위해 function과 var으로 변환된 결과가 나타나게 됩니다.
리액트에서 자동으로 preset을 만들어 줘서 잘 몰랐었으나
Babel을 이해하고, 적용시키기 위해 크로스 브라우징을 해결해볼 수 있는 기회가 생겼으면 좋겠습니다.