2022. 2. 22. 15:25ㆍ프로젝트/Mr. Toolbox
그동안 미루고 미뤄왔던 프로젝트 세팅 공부를 본격적으로 하고 있다.
webpack에 이어 babel도 보자.
목표
React와 ES6를 ES5 문법으로 변환해보자.
로더(loader)란?
로더는 모듈을 변환후 반환하는 역할을 한다.
개념만 따지면 변환해주는 함수와 같아보인다.
그렇다면 중요한건, '어떤 녀석'을 '어떻게' 처리해서 결과를 낼거냐다.
바벨 (babel)
바벨은 이러한 로더의 한 종류다.
그냥 one of loader다.
다만 잘 만들고 쓰기 편하다는 점이 있다.
특히 webpack과의 연계가 좋다.
바벨로 변환을 해보자.
우선 새 프로젝트를 만들어보자.
1. 새 폴더 생성
2. npm init
3. @babel/cli 설치
mkdir babel-practice
cd babel-practice
npm init -y
npm i -D @babel/cli
이제 cmd창에서 'bable'명령어를 사용할 수 있다.
'babel-practice' 폴더에 index.js를 생성해보자.
const hello = () => console.log("hello world");
이제 'babel' 명령어로 출력해보자.
npx babel index.js --out-file output.js
결과파일인 output.js를 보면, 코드가 달라지지 않은걸 알 수 있다.
그 이유는, 아까 설명한 그림에서 '처리'에 해당하는 부분이 없는거다.
빈 껍데기를 지나서 나온 것이다.
(사실 잘 보면 파일 마지막에 줄바꿈이 들어가 있다. 기본적인 처리는 된 상태)
이제 그 '처리'에 해당하는 부분을 배치해보자.
플러그인(plugin)이란?
넥슨 플러그인
'처리'를 해주는 단위다.
우리가 함수단위로 개발을 하듯,
바벨은 플러그인 단위로 처리를 한다.
적용할 수 있는 플러그인에 대해서는 위의 링크를 참고하자.
설정파일 .babelrc
.babelrc 파일은 babel이 작동할 때 참고하는 설정파일이다.
우리가 이 파일에 설정값을 넣어주면,
아까와 같이 babel이 실행될 때 처리를 해줄 것이다.
설정파일에 대한 자세한 부분은 위의 링크를 참고하자.
우리가 작성한 코드는 ES2015의 arrow-function이다.
이 플러그인을 적용해보자.
우선 .babelrc 파일을 생성한 다음, 다음과 같이 코드를 작성한다.
{
"plugins": ["@babel/plugin-transform-arrow-functions"]
}
패키지를 설치해준다.
npm i -D @babel/plugin-transform-arrow-functions
그 다음 다시 빌드를 해보자.
npx babel index.js --out-file output.js
다음과 같이 처리가 되었다.
const hello = function () {
return console.log("hello world");
};
프리셋(preset)을 알아보자
프리셋이란 위와 같은 플러그인들의 집합이다.
예를 들어 @babel/preset-env는 모든 ES6+문법을 지원해준다.
이제 적용을 해보자.
.babelrc 파일에 다음과 같이 수정한다.
(plugins는 이제 없애줘도 된다.)
{
"presets": ["@babel/preset-env"]
}
이제 패키지를 설치하자
npm i -D @babel/preset-env
index.js도 다양한 문법으로 작성해보자.
const hello = () => console.log("hello world");
{
const foo = { a: 3, b: 5, c: 7};
const { a, b, ...etc } = foo;
const funcA = (num, ...etc) => {
console.log(num);
}
funcA(b, () => console.log({ ...etc }));
}
과연 그 결과는?
"use strict";
var _excluded = ["a", "b"];
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
var hello = function hello() {
return console.log("hello world");
};
{
var foo = {
a: 3,
b: 5,
c: 7
};
var a = foo.a,
b = foo.b,
etc = _objectWithoutProperties(foo, _excluded);
var funcA = function funcA(num) {
console.log(num);
};
funcA(b, function () {
return console.log(_objectSpread({}, etc));
});
}
이... 이게 뭐고.
아무튼 잘 된다.
react(jsx) 파일 변환하기
자, 이제 react에서 쓰는 문법에 대해 알아보자.
const ComponentA = () => {
return (
<div>Hello World!</div>
);
}
자... 근데 js파일에 html태그가 들어가도 되나?
놀랍게도 안 된다.
CRA(create-react-app)으로 생성하면 알아서 잘 되니까 몰랐는데,
원래는 안 된다.
그럼 이제 react문법에 맞는 플러그인들을 찾아야 하는데,
이미 프리셋으로 있다. (개꿀개꿀)
.babalrc 파일을 수정해보자.
{
"presets": ["@babel/preset-react"]
}
패키지를 설치해보자
npm i -D @babel/preset-react
index.js를 수정해보자.
const ComponentA = () => {
return (
<div>Hello World!</div>
);
}
export default ComponentA;
빌드 해보자.
npx babel index.js --out-file output.js
const ComponentA = () => {
return /*#__PURE__*/React.createElement("div", null, "Hello World!");
};
export default ComponentA;
오... 이런 결과가 나왔다.
총평
생각보다 바벨 플러그인의 종류도 적고 원리도 단순했다.
그동안 괜히 빨리 써먹으려고 제대로 보지도 않고서 겁먹은 것 같다.
참고
'프로젝트 > Mr. Toolbox' 카테고리의 다른 글
react 처음부터 세팅하기 헤딩하기 (0) | 2022.02.22 |
---|---|
npm - package.json 분석하기 (0) | 2022.02.22 |