[Babel] Transfile과 Pollyfill 그리고 Babel에서 Pollyfill 적용 방식

이아영·2021년 2월 3일
1

Babel

목록 보기
1/1

Babel 설정을 하려고 보니 Transfile이니 Pollyfill이니 하는 용어들이 지속적으로 나왔고 Babel을 더 잘 이해하기 위해서 찾아보다가 정리를 해놔야겠다고 생각이 들었다.

Transfile

javascript에 있어서 trnafile은 최신 javascript 문법(const, arrow function, ...)을 이해할 수 없는 브라우저가 이해할 수 있도록 변환해주는 것이라고 말할 수 있다. Babel은 이렇게 변환을 해주는 Transfiler이고 이 Babel이 있으면 최신 문법을 사용해서 코딩을 하더라도 똥멍청이 IE도 알아듣게 만들 수 있다.

Pollyfill

하지만 Transfile만 한다고 해서 내 코드를 이전 버전의 브라우저가 모두 이해할 수는 없다. Transfile은 문법을 최신으로 변환해 주지만 Object와 Method(Map, Set, Promise, ...)는 변환하지 못하기 때문이다.
Pollyfill은 브라우저가 알아들을 수 없는 Object와 Method를 알아들을 수 있는 Object와 Method로 정의한 코드이다.

예를 들어 다음과 같이 Object 및 Method를 core-js라는 폴리필 라이브러리를 이용하면 이전 버전의 브라우저가 이해할 수 있는 코드로 바꿔준다.

var sym = Symbol();
var promise = Promise.resolve();
var check = arr.includes("yeah!");
console.log(arr[Symbol.iterator]());
import _getIterator from "@babel/runtime-corejs3/core-js/get-iterator";
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
import _Promise from "@babel/runtime-corejs3/core-js-stable/promise";
import _Symbol from "@babel/runtime-corejs3/core-js-stable/symbol";

var sym = _Symbol();
var promise = _Promise.resolve();
var check = _includesInstanceProperty(arr).call(arr, "yeah!");
console.log(_getIterator(arr));

Babel에서 Pollyfill 적용 방식

@babel/pollyfill

현재는 deprecated 방식으로, 커스텀 regenerator runtimecore-js가 포함되어 있다.

적용 방식은 매우 쉽다.
먼저, 다음 명령어로 다운로드 받고 webpack.config.js entry에 @babel/pollyfill을 추가해준다.

npm i -D @babel/pollyfill

// webpack.config.js
module.exports = {
  entry: ["@babel/polyfill", "./app/js"],
};

@babel/pollyfil은 전역 공간에 폴리필을 채워넣기 때문에 전역 공간이 오염 되어 폴리필 충돌이 일어날 수 있고 브라우저에서 필요하지 않은 폴리필까지 넣기 때문에 번들 크기가 커진다.

@babel/preset-env

대상 환경에 필요한 문법 변환 및 폴리필을 세부적으로 관리 할 필요없이 최신 JavaScript를 사용할 수있는 스마트 사전 설정

@babel/pollyfilldprecated 됨에 따라 core-js를 사용하는 것이 추천된다.
@babel/preset-env에서 corejs 옵션을 사용하여 버전을 지정할 수 있고 useBuiltIns 옵션으로 어떻게 폴리필을 다룰 것인지 설정한다.

사용 방법은 다음과 같다.

core-js는 버전 3을 쓰기 위해 함께 install 하고 webpack.config.js 파일에서 아래와 같이 설정해 준다.

npm i -D @babel/preset-env core-js @babel/runtime-corejs3

// webpack.config.js
module.exports = {
  presets: [['@babel/preset-env', {useBuiltIns: "usage", corejs: 3}]]
};  

useBuiltIns (stackoverflow: entry vs usage)

  • entry: 직접 임포트 한 core-js@babel/preset-env가 대상 환경이 필요로 하는 특정 모듈로 바꿔준다.
    // before
    import "core-js";
    // after
    import "core-js/modules/es.string.pad-start";
    import "core-js/modules/es.string.pad-end";
  • usage: 대상 환경에서 일부 기능 사용이 지원이 되지 않는 경우 자동으로 폴리필을 추가해 준다.
    // before
    var a = new Promise();
    // after
    import "core-js/modules/es.promise";
    var a = new Promise();

이렇게 @babel/preset-env를 통해서 폴리필을 설정할 수 있고 useBuiltIns: "entry" 옵션을 사용하면 전역 스코프가 오염되지만 useBuiltIns: "usage" 옵션을 사용하면 번들의 크기를 줄일 수 있고 전역 오염을 피할 수 있다.

@babel/plugin-transform-runtime

코드 사이즈를 줄이기 위해 이미 사용한 helper code를 재사용 할 수있는 플러그인

Babel은 기본적으로 매우 작은 helper code를 필요한 모든 파일에 추가한다. 애플리케이션이 여러 파일에 분산되어 있는 경우는 중복이 발생한다.
@babel/plugin-transform-runtime은 이러한 중복을 방지하기 위해 helper code들이 @babel/runtime을 참조하여 재사용할 수 있게 해준다.

위에서 install한 것에 추가로 다음을 install 해주고 webpack.config.js를 설정해준다.

npm i -D @babel/plugin-transform-runtime babel/runtime

// webpack.config.js
module.exports = {
  presets: [['@babel/preset-env']],
  plugins : [["@babel/plugin-transform-runtime",{corejs: 3}]]
};  

core-js@3@babel/transform-runtime를 함께 사용하면 core-js-pure 버전으로부터 폴리필을 주입하는데 core-js-pure버전은 전역 스코프를 오염시키지 않는다.

단, 외부 모듈이 전역공간에 선언된 최신 객체를 필요로 할 경우 매번 webpack의 include 옵션에 포함시켜줘야 한다는 단점이 있다.(자세한 설명)

참고 문헌:

0개의 댓글