# Babel CLI 구성

## 프로젝트 초기화 <a href="#project-initialization" id="project-initialization"></a>

Babel CLI 실습에 앞서 프로젝트를 초기화 합니다.

{% tabs %}
{% tab title="프로젝트 초기화 설정" %}

```bash
mkdir <프로젝트> && cd $_
npm init -y
git init
```

{% endtab %}
{% endtabs %}

## Babel CLI 설치 <a href="#install-babel-cli" id="install-babel-cli"></a>

[@babel/core](https://www.npmjs.com/package/@babel/core) [@babel/cli](https://www.npmjs.com/package/@babel/cli) 패키지를 프로젝트에 설치하면 명령어 환경(CLI)에서 Babel 컴파일러를 사용할 수 있습니다.

```bash
npm i -D @babel/core @babel/cli
```

{% hint style="info" %}

#### 로컬 설치가 권장되는 이유

Babel CLI 글로벌 설치 보다, 프로젝트 단위로 로컬 설치하는 것이 좋습니다. 이유는 다음과 같습니다.

1. 프로젝트 마다 다른 버전의 Babel CLI를 사용할 수 있습니다.
2. 작업 중인 환경의 암시적 종속성이 없어 프로젝트를 이식 가능하고 설정하기 쉽게 만듭니다.
   {% endhint %}

## 컴파일 명령 등록 <a href="#add-compile-command" id="add-compile-command"></a>

`package.json` 스크립트 항목에 `compile` 명령을 추가합니다. `src` 디렉토리의 JavaScript 파일을 컴파일 한 후 `dist` 디렉토리에 결과를 저장하도록 설정하고, `start` 명령을 추가해 `compile` 을 실행하도록 설정합니다.

{% tabs %}
{% tab title="package.json" %}

```javascript
{
  "scripts": {
    "start": "npm run compile",
    "compile": "babel src -d dist"
  }
}
```

{% endtab %}
{% endtabs %}

등록한 `start` 명령을 실행하면 Babel에 의해 JavaScript 코드가 컴파일 됩니다.

{% tabs %}
{% tab title="NPM 명령 실행" %}

```bash
npm start # npm run compile 명령 실행
```

{% endtab %}
{% endtabs %}

컴파일 된 결과는 `dist` 디렉토리 안에 출력됩니다.

```bash
.
├── dist/ # 컴파일 출력 코드
│   ├── ellipseText.js
│   └── index.js
│
└── src/ # 원본 소스 코드
    ├── ellipseText.js
    └── index.js
```

## 컴파일 출력 코드 <a href="#compile-result" id="compile-result"></a>

Babel 컴파일을 통해 하위 브라우저 호환용 코드로 변경되었을 거라 기대하지만, 실제 결과는 그렇지 않습니다.

{% tabs %}
{% tab title="dist/index.js" %}

```javascript
import { ellipseText } from './ellipseText.js';
console.log(ellipseText(`Node.js 환경에서 ES 모듈을 사용하려면 mjs 확장자 또는 
     package.json에 type을 module로 설정해야 합니다.`));
```

{% endtab %}

{% tab title="dist/ellipseText.js" %}

```javascript
export const ellipseText = (text, limit = 100) => `${text.slice(0, limit)}...`;
```

{% endtab %}
{% endtabs %}

## Babel 구성 (Env 사전 설정) <a href="#babel-config" id="babel-config"></a>

사전 설정(presets) 없이는 Babel은 아무 것도 컴파일 하지 않습니다. 기대대로 Babel이 하위 브라우저에서 호환 가능한 코드로 컴파일 하도록 설정하려면 [@babel/preset-env](https://babeljs.io/docs/en/babel-preset-env) 설정이 필요합니다.

먼저 사용 할 @babel/preset-env 사전 설정 패키지를 설치합니다.

{% tabs %}
{% tab title="Babel Env 사전 설정 패키지 설치" %}

```bash
npm i -D @babel/preset-env
```

{% endtab %}
{% endtabs %}

`babel.config.json` 파일을 프로젝트 루트에 만든 후, 사전 설정을 추가합니다.

{% tabs %}
{% tab title="babel.config.json" %}

```javascript
{
  "presets": ["@babel/preset-env"]
}
```

{% endtab %}
{% endtabs %}

다시 Babel 컴파일을 실행합니다.

{% tabs %}
{% tab title="NPM 명령 실행" %}

```bash
npm start
```

{% endtab %}
{% endtabs %}

컴파일 결과를 살펴보면 ~~하위 브라우저에서도 호환 가능한 코드가 출력된 것을 볼 수 있습니다.~~  ECMAScript 5 코드로 출력된 듯 보이지만, 뭔가 이상합니다. 웹 브라우저 환경에서 지원할 코드에 `require()` 라니...

{% tabs %}
{% tab title="dist/index.js" %}

```javascript
"use strict";

var _ellipseText = require("./ellipseText.js");

console.log((0, _ellipseText.ellipseText)("Node.js ...생략..."));
```

{% endtab %}

{% tab title="dist/ellipseText.js" %}

```javascript
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ellipseText = void 0;

var ellipseText = function ellipseText(text) {
  var limit = arguments.length > 1 && arguments[1] !== undefined ? 
                arguments[1] : 100;
  return "".concat(text.slice(0, limit), "...");
};

exports.ellipseText = ellipseText;
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}

#### require() 함수?

[require()](https://nodejs.org/api/modules.html#modules_require_id)는 웹 브라우저가 아닌, Node.js에서 사용하는 CommonJS의 모듈 불러오기 함수입니다. Babel 출력 코드에서 require() 함수가 출력된 이유는 ES 모듈을 사용했기 때문입니다.

ES 모듈을 사용하지 않고 ES6 코드를 사용했다면? 아래와 같이 호환 가능한 코드가 출력됩니다.

```javascript
"use strict";

var ellipseText = function ellipseText(text, limit) {
  if (limit === void 0) {
    limit = 100;
  }

  return text.slice(0, limit) + "...";
};

console.log(ellipseText("Node.js ...생략..."));
```

{% endhint %}

만약 ES 모듈 코드를 CommonJS 모듈 방식으로 변경하지 않을 경우, 다음과 같이[ 옵션](https://babeljs.io/docs/en/babel-preset-env#modules)을 설정합니다.

{% tabs %}
{% tab title="babel.config.json" %}

```javascript
{
  "presets": [
    [
      "@babel/preset-env",
      { "modules": false }
    ]
  ]
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}

#### 유니버셜 모듈 디피니션 ([UMD](https://github.com/umdjs/umd))

CommonJS, AMD, Browser 환경에서 모두 사용 가능한 모듈 코드를 출력하려면 "[umd](https://blog.rhostem.com/posts/2019-06-23-universal-module-definition-pattern)" 값을 설정합니다.

```javascript
"modules": "umd"
```

{% endhint %}

## Babel은 모듈 번들러가 아닙니다. <a href="#babel-is-not-module-bundler" id="babel-is-not-module-bundler"></a>

Babel은 Javascript 컴파일러입니다. 새로운 ES 문법을 지원하지 않는 브라우저에서도 사용할 수 있게 언어 차원에서의 변환 기능을 제공하는 도구일 뿐입니다. Webpack과 같은 모듈 번들러가 하는 일을 처리하지는 못합니다.

즉, ES 모듈을 사용해 모듈 불러오기, 내보내기 기능을 사용한다면 Babel 컴파일 코드 출력 결과물만으로는 웹 브라우저 환경에서 사용할 수 없습니다. Webpack과 같은 모듈 번들러를 사용해 빌드 시스템을 구축한 후, Babel 컴파일러를 로더로 추가해 사용해야 합니다.

![](https://1127883942-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MTbexhuB2p5ev8QaGgg%2F-MV968R8xccy3HZuuQBq%2F-MV96yUYv6TlHiWuhCnh%2Fimage.png?alt=media\&token=3e9b4324-9177-414c-824e-b3830da91373)

{% content-ref url="../webpack/config-webpack-dev-environment" %}
[config-webpack-dev-environment](https://yamoo9.gitbook.io/webpack/webpack/config-webpack-dev-environment)
{% endcontent-ref %}

## Browserslist 통합 <a href="#browserslist-integration" id="browserslist-integration"></a>

브라우저 또는 Electron 기반 프로젝트의 경우, `.browserslistrc` 파일을 사용하여 대상을 지정하는 것이 좋습니다.

{% tabs %}
{% tab title=".browserslistrc" %}

```javascript
> 0.25% in KR
not ie < 11
not dead
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}

#### 브라우저 지원 목록 출력

프로젝트 루트 위치에서 다음 명령어를 실행하면 프로젝트가 지원하는 브라우저 목록이 출력됩니다.

```bash
npx browserslist
```

{% endhint %}

## 참고 <a href="#reference" id="reference"></a>

{% embed url="<https://babeljs.io/setup#installation>" %}

{% embed url="<https://babeljs.io/docs/en/babel-preset-env#browserslist-integration>" %}
