Webpack - 바벨(Babel)

12493 단어 webpackbabelbabel

[ Babel 이란 ? ]

  • ES6+(ECMAScript 2015+) 코드를 하위 버전으로 변환해주는 JS 컴파일러
  • 하위 JS 문법으로 변환할 수 없는 코드는 core-js같은 third-party 폴리필을 통해 변환
  • Typescript 코드를 컴파일 시점에 Javascript 코드로 변환
  • Webpack / Rollup 등의 정적 모듈 번들러들을 통해 함께 사용 가능

[ Babel이 필요한 이유 ]

  • 크로스 브라우징 이슈를 해결하기 위해 Babel을 통해 모던 JS의 변환이 필요
  • 특히 웹표준을 따르지 않는 IE 지원을 위해 많이 사용되었다
    • MS에서 IE(Internet Explorer)는 2022.06.15에 공식적인 지원 종료를 선언
      (Edge에서 2029년 까지 IE모드로 선택적 사용은 지원)
  • 크로스 브라우징 (Cross Browsing) ?
    • HTML, CSS, Javascript 작성 시 W3C의 웹 규격에 맞는 코딩을 함으로써 어느 브라우저, 기기에서 사이트가 의도된 대로 보여지고 작동되는 기법
    • 각 브라우저 / 플랫폼 처럼 상이한 환경에서도 의도한 대로 작동되도록 웹 페이지를 개발하는 하나의 방법론으로 이해 가능
    • 각 브라우저의 렌더링 엔진의 차이로 발생

[ 구성 파일 ]

[ 개요 ]

  • babel을 구성하는 다양한 방법이 존재
    • 프로젝트 전체 구성 : babel.config.[js | json | mjs | cjs]
    • 파일 상대 구성
      • .babelrc.[js | json | mjs | cjs]
      • package.json

[ babel.config.json ]

  • 프로젝트 root에 위치하여 프로젝트 전체적으로 광범위하게 적용해야하는 구성 파일
  • 여러 패키지 디렉토리를 가진 프로젝트에서 하나의 바벨 설정을 가져갈 때 유용
  • js vs json 확장자

[ .babelrc.json ]

  • 하위 디렉토리나 파일에서 특정 플러그인 / 변환(규칙)을 실행할 때 사용하는 구성 파일
  • 컴파일되는 filename 에서 시작하는 디렉터리 구조를 검색하여 .babelrc.* 파일을 로드
  • 패키지 하위 섹션에 대한 독립적인 구성을 만들 수 있다는 것이 핵심

[ package.json ]

  • .babelrc.json 파일 구성과 동일한 구성을 가지며, 동일한 역할을 수행
  • package.jsonbabel key를 이용해 등록 가능

[ 동작 원리 ]

바벨의 빌드 단계

  • 파싱(Parsing)
    • 코드를 읽고 추상 구문 트리(AST)로 변환하는 단계
    • AST 자료구조는 빌드 작어븡ㄹ 처리하기에 적합한 하나의 자료구조
    • 바벨 코어(core)가 수행
  • 변환(Transforming)
    • AST를 실제 코드로 변환하는 단계
    • 플러그인(Plugin)이 수행
  • 출력(Printing)
    • 최종적으로 변환된 코드를 출력하는 단계
    • 바벨 코어(core)가 수행

[ Plugin ]

[ 개념 ]

  • 예시
    • @babel/plugin-transform-block-scoping : const / let => var
    • @babel/plugin-transform-arrow-functions : 화살표 함수(arrow function)를 일반함수로 변경
    • @babel/plugin-transform-strict-mode : script를 strict mode로 변환

[ custom plugin ]

  • const, let은 ES6에서 사용 가능한 문법이라서 var로 트랜스 파일링 되어야 한다
    • 같은 기능을 하는 플러그인 : @babel/plugin-transform-block-scoping
/* my-babel-plugin.js
   => 실행 : npx babel ./src/app.js --plugins './my-babel-plugin.js'*/

module.exports = function myBabelPlugin(){
    return {
        visitor: {
            // 토큰 하나씩 구분하는 vitisor
            Identifier(path){
                const name = path.node.name;
                // babel이 만든 AST 노드 -> 토큰이라는 하나의 단위로 실행 된다
                console.log('Identifier() name : ', name)

                // 변환 작업
                path.node.name = name
                    .split("")
                    .reverse()
                    .join("");
            },
            // 변수 선언과 관련된 visitor
            VariableDeclaration(path){
                // const 를 찾아서 let으로 변환
                if(path.node.kind === 'const') path.node.kind = 'var'
            }
        },
    }
}

[ Preset ]

[ 개념 ]

  • 공식 Presets
    • @babel/preset-env
    • @babel/preset-typescript
    • @babel/preset-react
    • @babel/preset-flow

[ 적용 예시 : @babel/preset-env ]

  • @preset-env
    • 설명
      • ECMAScript 2015+ 를 변환할 때 사용되는 플러그인들의 집합
      • babel 7 이전에는 연도별로 제공했었지만, 현재는 -env 하나로 통합됨
      • babel docs : https://babeljs.io/docs/en/babel-preset-env
    • 주요 기능
      • target browser 지정
        : 사용될 브라우저를 직접 지정하거나 범위로 설정 가능
      • Polyfill 추가
        • 하위 버전의 JS로 호환되지 않는 Promise같은 기능은 폴리필이 필요
        • core-js 같은 thrid-party 패키지를 통해 적용 가능
/* babel.config.js */
    presets: [
        ['@babel/preset-env', {
            targets: {
                chrome: '79',
                ie: "11"
            },
            // 폴리필 기능을 해주는 corejs 의 사용 여부와 버전을 명시
            useBuiltIns: 'usage', // false(미사용), entry
            corejs: {
                version: 3
            }
        }]
    ]

[ Babel & Webpack ]

[ 설명 ]

  • 바벨은 일반적으로 웹팩과 함께 통합해서 사용
  • 로더 형태로 바벨이 제공되어 babel-loader로 적용
  • core-js를 사용하는 경우 함께 설치가 되어 있어야 한다
  • webpackbabel-loader 가이드 : https://webpack.js.org/loaders/babel-loader/

[ 적용 예시 : babel-loader ]

/* webpack.config.js */
{
    module: {
        rules: [
          ...
            // babel-loader
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            }
        ]
    },
}
  • @babel/preset-env 에서 async / awaitPromise로 바꾸고 PolyfillJS 변환을 수행
    => 해당 기능이 비교적 최근에 추가되었음
    => 그 전까지는 regenerator-runtime/runtime 패키지를 사용해서 변환했었다

좋은 웹페이지 즐겨찾기