React로 프로젝트를 세팅하고 개발에 임하면서 React가 제공하는 Hook API나, 리액트에서 사용되는 라이브러리등을 공부해 프로젝트에 적용했었다.
그러나, 이러한 React 프로젝트를 사용할 수 있도록 도와주는 라이브러리들(Bable,WebPack,vite 등등..)은 항상 React 패키지 설치 시 자동으로 설치되다보니 이러한 모듈러나 트랜스파일러등이 어떻게 동작하는지 확인하지 않고 개발에 임했었다.
이번 글을 계기로 다양한 모듈러나 트랜스파일러등을 분석하고 작성할 생각이다.
이 글은 바벨 공식문서를 참고해 작성한 문서입니다!
Bable은 JavaScript 컴파일러입니다.
Babel이 제공하는 주요 기능들
1. 최신 JavaScript로 문법 변환 : 위에서 써있듯이 최신 JavaScript문법을 구형 브라우제어도 동작 가능케 하는 ES5 코드로 변환하는 역할을 합니다.
2. 폴리필 기능 : Bable은 폴리필 기능을 통해 구형 브라우저에 지원하지 않는 최신 JavaScript API(ex:Promise, Fetch API, Spread Syntax)를 사용할 수 있게합니다.
React 개발 시 JSX 문법은 필수적으로 사용된다고 해도 과언이 아닙니다.
const element = <h1>Hello, world!</h1>;
/* 바벨 트랜스파일러에 의해 다음과 같이 컴파일 됩니다.*/
const element = React.createElement('h1', null, 'Hello, world!');
pnpm i -D @babel/core @bable/cli @babel/preset-env
@bable/core
- Bable의 핵심기능들을 제공하는 역할을 합니다.
- JavaScript 코드 파싱 -> AST(추상 구문트리)로 변환 -> 플러그인 혹은 프리셋을 적용 -> 다시 과거문법으로 트랜스파일링 된 JavaScript 코드로 변환
@bable/cli
- Bable을 커맨드라인에서 사용할 수 있게 하는 패키지이며, 해당 패키지를 통해 소스 코드를 트랜스파일하고 결과를 출력 디렉토리에 저장할 수 있습니다.
@bable/preset-env
- 개발자가 지정한 환경에 맞게 최신 JavaScript를 변환해주는 Babel 프리셋입니다.
- 예를 들어, 특정 버전의 브라우저를 지원하도록 설정할 수 있으며, 이에 따라 필요한 플러그인들을 자동으로 결정하여 적용합니다.
const bable = "Hellow World";
const bableObject = {
name: "babel",
version: 7,
};
const copyBable = {...bableObject};
{
"name": "babel",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"compile": "babel src -d dist"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.23.9",
"@babel/core": "^7.24.0",
"@babel/preset-env": "^7.24.0"
}
}
babel.config.json 파일 생성 및 사전 설정 추가하기
bable.config.json
파일을 생성합니다.modules : false
로 설정한 이유는, ES6 모듈을 다른 모듈타입(=Cjs)로 변환하는것을 방지하기 위함입니다.{
"presets": [["@babel/preset-env", {"modules": false}]]
}
pnpm run compile
function _typeof(o) {
"@babel/helpers - typeof";
return (
(_typeof =
"function" == typeof Symbol && "symbol" == typeof Symbol.iterator
? function (o) {
return typeof o;
}
: function (o) {
return o &&
"function" == typeof Symbol &&
o.constructor === Symbol &&
o !== Symbol.prototype
? "symbol"
: typeof o;
}),
_typeof(o)
);
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r &&
(o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})),
t.push.apply(t, o);
}
return t;
}
function _objectSpread(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2
? ownKeys(Object(t), !0).forEach(function (r) {
_defineProperty(e, r, t[r]);
})
: Object.getOwnPropertyDescriptors
? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t))
: ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true,
});
} else {
obj[key] = value;
}
return obj;
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : String(i);
}
function _toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
var bable = "Hellow World";
var bableObject = {
name: "babel",
version: 7,
};
var copyBable = _objectSpread({}, bableObject);