이 글은 blog.jakoblind.no에서 작성한 What is babel-preset-env and why do I need it?을 번역/요약한 내용입니다.

모던 javascript 프로젝트를 시작할 때, babel을 설치하고 babel-preset-env plugin 설정을 .babelrc에서 하였을 것이다.

{
    presets: ['@babel/preset-env]
}

이렇게 하면 나름 동작을 잘 한다. 하지만 우리는 .babelrc 파일이 무엇을 하고 어떻게 동작하는지 알고 싶다.

babel from scratch

babel은 webpack과 같은 빌드시스템과 함께 사용한다. 그러면 bable이 어떻게 동작하는지 찾아보기 쉽다.

좋은 연습은 babel을 webpack과 같은 빌드 시스템없이 만들어 보는 것이다.

먼저 npm 프로젝트를 만들자

mkdir babel-test
cd babel-test
npm init -y

다음 빈프로젝트에 babel을 dependancy로 설치하자

npm install --save-dev @babel/core @babel/cli

다음과 같은 javascript 코드를 input.js에 입력하자

const hello = () => console.log("hello world")

이것은 es6 문법 중 arrow function이다. 대부분의 브라우저가 es6를 지원하지만 그렇지 않은 것도 있다. 그래서 es5로 컴파일해주는 것이 중요하다.(2019년 기준 es6문법이 적용되는 브라우저를 확인하고 싶다면 caniuse.com을 참조하자)

이제 babel을 통해 input.js를 실행해보자

npx babel input.js --out-file output.js

output.js파일을 열어본다면 변한게 없는것을 알 수 있다. 이건 우리가 예상한 것이 아니다. 사실 babel은 그 자체로는 아무것도 하지 않는다. 만약 preset과 plugin을 추가하지 않는다면 babel은 아무것도 하지 않는다.

babel은 그 자체로는 아무것도 하지 않는다.

진짜 동작하는 것은 babel plugin이다

babel이 무엇을 하게 하려면 plugin을 설치해야 한다. 사실 plugin이 다 한다고 보면된다.

각각의 plugin은 npm 라이브러리를 가지고 있다. 그래서 설치하고 싶은 각각의 plugin을 위해 새로운 npm 라이브러리를 설치하거나 또는 preset을 쓸 수 있다.

지금부터 es6의 arrow function을 컴파일 할 babel plugin을 설치해보자

npm install --save-dev @babel/plugin-transform-arrow-functions

그리고 babel한테 dependency를 쓴다고 말해야 한다..babelrc 파일을 프로젝트 root에 추가하자. 이것은 babel 설정파일이며, es6에서 es5로 컴파일 할 때 .babelrc이 babel에게 @babel/plugin-transform-arrow-functions를 사용하여 es6에서 es5로 컴파일하라고 명령한다. @babel/plugin-transform-arrow-functions는 오직 arrow function을 컴파일할 때만 쓰인다.

{
  plugins: ['@babel/plugin-transform-arrow-functions']
}

.babelrc : babel plugin들을 모아놓고 사용할 설정파일

이제 babel을 다시 실행하고 생성된 output.js 파일을 보자. 이제 컴파일된 코드를 볼 수 있을 것이다.

const hello = function () {
  return console.log("hello world!");
};

하지만 만약 es6의 기능을 더 쓰고싶다면 매번 npm 패키지를 설치하고 .babelrc에 플러그인을 매번 더해야 할 것이다. 이것은 매우 귀찮은 일이다.. 그래서 나온 솔루션이 바로 preset이다.

babel plugins에서는 번들로 babel preset이 함께 온다

babel foundation에서는 plugin들을 포함한 번들(plugin들을 모아놓은 파일이라고 생각하면 된다)파일을 포함 preset을 만들었다. 이 말인 즉슨, npm 설치와 babel 설정을 한번만 하면 plugin들이 자동적으로 설치된다는 뜻이다.

다양한 babel preset들이 있는데 babel foundadtion에서 제공하는 공식 preset과 Airbnb같은 곳에서 제공하는 비공식 preset이 있다. 심지어 우리가 만들 수도 있다.

babel이 7로 업데이트 되면서 scoped package로 전환했다. 간단히 이야기하면 기존의 비공식적인 package들과 네이밍 컨벤션에 문제가 있어서 바꾸게 되었다.

공식 preset은:

  • @babel/preset-env
  • @babel/preset-flow
  • @babel/preset-react
  • @babel/preset-typescript

각각의 preset은우리가 설치 설정해야할 npm dependency를 가지고 있다.
드디어 우리는 babel-preset-env를 실행할 준비가 되었다.

좋아, @babel/preset-env를 실행해보자

@babel/plugin-transform-arrow-functions 대신 babel-preset-env를 사용해보자

npm dependency를 먼저 설치하자

npm install --save-dev @babel/preset-env

.babelrc 파일에서 preset 섹션을 설정하자

{
  presets: ['@babel/preset-env']
}

지금까지 한 것은 기본적인 babel-preset-env 설정을 준비한 것이다. 그리고 모든 es6 기능을 컴파일할 모든 plugin 들을 얻은 것이다.

하지만 babel-preset-env은 이것보다는 조금 더 똑똑하다.

babel-preset-env로 설정하고자 하는 브라우저를 선택할 수 있다.

기본적으로 babel-preset-env는 단순히 모든 es6 plugin을 설치한다. 하지만 이것은 컴파일된 자바스크립트의 양이 많아져 번들의 코드를 길어지게 만든다.

스크린샷 2019-09-03 오후 2.47.04.png

왼쪽은 es6 코드이고 중간의 코드는 오래된 브라우저에 제공하기 위해 컴파일된 파일이다. 제일 오른쪽의 나름 최신의 브라우저에 제공되는 코드에 비해서도 매우 길다.

그래서 babel-preset-env만을 쓴다면 오래된 브라우저에 제공하는 코드의 길이는 엄청나게 많아져 번들 파일을 터뜨려 버릴 것이다. (그만큼 코드 길이가 늘어난다는 뜻)

최근의 브라우저는 대부분 es6를 지원한다. google analystics만 보더라도 99%는 최신의 브라우저이다. 그래서 모든 옛날 브라우저를 지원할 필요는 없다고 생각할 수도 있다.

그래서 babel-preset-env에게 원하는 브라우저만 지원가능하도록 plugin을 선택할 수 있다.

참조

npx

  • CLI tool from npm team
  • ships with npm from v5.2.0
  • Node.js package executor
    • run node package in a variety of ways
  • Execute local binaries
    • npx "binaries"
  • Run uninstalled binaries
    • install and run the binaries

we dont need to install the packages and go find the full path to execute the package that we installed like the code below

npm install serverless
./node_modules/.bin/serverless create --template aws-nodejs

we can simply run install the dependency and execute the package without tracking the path of it

npx serverless

also, you will be able to run the option at the end of the execution

npx webpac-cli init webpack-addons-react

정리

  • babel 자체로는 아무것도 안함
  • plugin이 컴파일
    • 매번 plugin 패키지 설치
    • .babelrc에 더하는 것이 귀찮
  • preset으로 plugin 그룹 한번에 설치
  • 공식 preset 사용 (@bable/core)