Babel은 JavaScript 컴파일러입니다.
Babel은 현재 및 이전 브라우저 또는 환경에서 ECMAScript 2015+ 코드를 이전 버전과 호환되는 JavaScript 버전으로 변환하는 데 주로 사용되는 도구 체인입니다.
위 설명은 공식 문서에서 가져온 문장이다.
가볍게 생각하면 javascript문법이 계속해서 생겨나면서 아직 브라우저에 적용이 안된 경우가 있을 수 있기 때문에 이 코드를 구버전 javascript 문법으로 변환시켜주는 컴파일러이다.
예를 들면 아래의 화살표 함수를 기본 함수 표현식으로 변환시켜 주는 것이다.
const add = (a, b) => a + b;
const add = function (a, b) {
return a + b;
};
📌 현재에는 JSX, 타입스크립트와 같은 정적 타입 언어, 코드압축 등에도 사용된다
바벨을 실행하는 방법은 네가지가 있지만 주로 세가지를 많이 사용한다.
@babel/cli
: command line에서 바벨을 사용babel-loader
: webpack에서 바벨을 사용@babel/core
: babel을 사용하기 위한 필수 패키지바벨을 사용해 보기 위해 패키지를 설치해야 한다
npm install @babel/core @babel/cli @babel/plugin-transform-template-literals @babel/plugin-transform-arrow-functions @babel/preset-react
📌 바벨은 파싱과 출력을 담당하고 플러그인이 변환 작업을 처리한다.
📌 preset은 plugins의 집합이다.
아래와 같은 코드를 작성해서 세가지 방식으로 변환 시켜 보자.
src/code.js
// jsx -> createElement
const element = <div>babel test</div>; // preset-react
// template-literals -> concat
const text = `element type is ${element.type}`; // plugin-transform-template-literals
// arrow-functions -> normal func
const add = (a, b) => a + b; // plugin-transform-arrow-functions
cli는 command line에서 사용하기 위한 것이기 때문에 터미널에 아래 명령어를 입력하면 작동한다.
npx babel src/code.js --presets=@babel/preset-react --plugins=@babel/plugin-transform-template-literals,@babel/plugin-transform-arrow-functions
그럼 아래처럼 결과가 콘솔에 출력된다.
const element = /*#__PURE__*/React.createElement("div", null, "babel test");
const text = "element type is ".concat(element.type);
const add = function (a, b) {
return a + b;
};
근데 이렇게 할때마다 입력하기 귀찮으니 config파일을 작성해서 사용한다.
babel.config.js
const presets = ["@babel/preset-react"];
const plugins = [
"@babel/plugin-transform-template-literals",
"@babel/plugin-transform-arrow-functions",
];
module.exports = { presets, plugins };
npx babel src/code.js
를 입력하면 위와 같은 결과가 나온다.
웹팩을 이용하기 때문에 웹팩도 같이 설치해준다
npm install webpack webpack-cli babel-loader
webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/code.js", // 번들링할 파일 지정
output: {
path: path.resolve(__dirname, "dist"), // 현재 폴더 경로에서 dist 폴더밑으로
filename: "code.bundle.js", // 이 이름으로 결과 생성
},
module: {
rules: [{ test: /\.js$/, use: "babel-loader" }],
},
optimization: { minimizer: [] },
};
npx webpack
을 입력하면 아래처럼 결과가 저장된다.
dist/code.bundle.js
/******/ (() => { // webpackBootstrap
var __webpack_exports__ = {};
// jsx -> createElement
const element = /*#__PURE__*/React.createElement("div", null, "babel test"); // preset-react
// template-literals -> concat
const text = "element type is ".concat(element.type); // plugin-transform-template-literals
// arrow-functions -> normal func
const add = function (a, b) {
return a + b;
}; // plugin-transform-arrow-functions
/******/ })()
;
@babel/cli
나 babel-loader
둘다 @babel/core
를 이용해서 바벨을 실행한다.
@babel/core
를 직접 사용하는 방법도 있다.
runBable.js
const babel = require("@babel/core");
const fs = require("fs");
const filename = "./src/code.js";
const source = fs.readFileSync(filename, "utf8");
const presets = ["@babel/preset-react"];
const plugins = [
"@babel/plugin-transform-template-literals",
"@babel/plugin-transform-arrow-functions",
];
const { code } = babel.transformSync(source, {
filename,
presets,
plugins,
configFile: false, // babel.config.js 사용 x
});
console.log(code);
node runBabel.js
을 입력하면 콘솔창에 결과가 나온다
👍 @babel/core
를 직접 사용하면 자유도가 높다
예를 들어 한 코드에 아래와 같은 설정을 입힌다고 해보자
const presets = ["@babel/preset-react"];
const plugins = ["@babel/plugin-transform-arrow-functions"];
const presets = ["@babel/preset-react"];
const plugins = ["@babel/plugin-transform-template-literals"];
이 설정값에 대해 @babel/cli
나 babel-loader
를 이용하면 똑같은 preset-react를 두번 실행한다.
@babel/core
로 이걸 해결할 수 있는데 AST를 이용하는것이다
💡 AST(abstract syntax tree)는 코드의 구문이 분석된 결과를 담고 있는 구조체이다
이걸로 어떻게 해결하냐면 바벨은 컴파일 시에 세단계를 거친다
❗️ 따라서 코드가 같으면 AST도 같기 때문에 재사용 할수 있다
runBabel2.js
const babel = require("@babel/core");
const fs = require("fs");
const filename = "./src/code.js";
const source = fs.readFileSync(filename, "utf8");
const presets = ["@babel/preset-react"];
const { ast } = babel.transformSync(source, {
// ast만 생성
filename,
ast: true,
code: false,
presets,
configFile: false,
});
const { code: code1 } = babel.transformFromAstSync(ast, source, {
filename,
plugins: ["@babel/plugin-transform-template-literals"],
configFile: false,
});
const { code: code2 } = babel.transformFromAstSync(ast, source, {
filename,
plugins: ["@babel/plugin-transform-arrow-functions"],
configFile: false,
});
console.log(code1);
console.log(code2);
위 코드처럼 preset-react
에 대해 AST를 만들어서 재사용해서 효율을 높일 수 있다.
참고: 실전 리액트 프로그래밍