꾸준한 개발일기

Javascript:: Babel과 Webpack을 이용한 ES6+/ES.NEXT 개발 환경 구축 본문

JS/JavaScript

Javascript:: Babel과 Webpack을 이용한 ES6+/ES.NEXT 개발 환경 구축

꾸개일 2022. 12. 4. 00:45
반응형

1. Babel

  • 대표적인 트랜스파일러임
트랜스파일링이란 특정 언어로 작성된 코드를 비슷한 다른 언어로 변환시키는 것이이다. 이를 해주는 것이 트랜스 파일러이다.

트랜스파일링이 필요한 이유는?

모든 브라우저가 ES6의 기능(최신기능)을 제공하지 않기 때문에 ES5코드(구기능)으로 변환시키는 과정이 필요하기 때문이다.

1.1 Babel 설치

# 프로젝트 폴더 생성
$ mkdir esnext-project && cd esnext-project

# package.json 생성
$ npm init -y

# babel-core, babel-cli 설치
$ npm install --save-dev @babel/core @babel/cli

생성된 package.json

{
  "name": "esnext-project",
  "version": "1.0.0",
  "devDependencies": {
    "@babel/cli": "^7.19.3",
    "@babel/core": "^7.20.5"
  }
}

1.2 Babel 프리셋 설치와 babel.config.json 설정 파일 작성

  • @babel/preset-env는 함께 사용되어야 하는 Babel 플러그인을 모아 둔 것으로 Babel 프리셋이라 부름
  • @babel/preset-env는 필요한 플러그인들을 프로젝트 지원 환경에 맞춰 동적으로 결정해줌

Babel이 제공하는 공식 Babel 프리셋

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

@babel/preset-env 설치

# @babel/preset-env 설치
$ npm install --save-dev @babel/preset-env

설치가 완료된 이후 package.json

{
  "name": "esnext-project",
  "version": "1.0.0",
  "devDependencies": {
    "@babel/cli": "^7.19.3",
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.20.2"
  }
}

루트 폴더에 babel.config.json 설정 파일 생성

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

1.3 트랜스파일링

npm scripts에 Babel CLI 명령어를 등록(package.json 파일에 scripts 추가)

{
  "name": "esnext-project",
  "version": "1.0.0",
  "scripts": {
    "build": "babel src/js -w -d dist/js"
  },
  "devDependencies": {
    "@babel/cli": "^7.19.3",
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.20.2"
  }
}
  • build는 src/js 폴더(타깃 폴더)에 있는 모든 자바스크립트 파일들을 트랜스파일링한 후, 그 결과물을 dist/js 폴더에 저장
  • -w: 타깃폴더에 있는 모든 자바스크립트 파일들의 변경을 감지하여 자동으로 트랜스파일함(--watch 옵션의 축약형)
  • -d: 트랜스파일링된 결과물이 저장될 폴더를 지정함, 만약 지정된 폴더가 존재하지 않으면 자동 생성(--out-dir 옵션의 축약형)

src/js/lib.js

export const pi = Math.PI; // ES6 모듈

export function power(x, y) {
    return x ** y; // ES7: 지수 연산자
}

// ES6 클래스
export class Foo {
    #private = 10; // stage 3: 클래스 필드 정의 제안

    foo() {
        // stage 4: 객체 Rest/Spread 프로퍼티 제안
        const { a, b, ... x } = { ...{ a: 1, b: 2 }, c: 3, d: 4 };
        return { a, b, x };
    }

    bar() {
        return this.#private;
    }
}
  • 트랜스파일링 테스트를 위한 자바스크립트 파일 작성

src/js/main.js

import { pi, power, Foo } from './lib'

console.log(pi)
console.log(power(pi, pi));

const f = new Foo();
console.log(f.foo());
console.log(f.bar());
  • 트랜스파일링 테스트를 위한 자바스크립트 파일 작성

트랜스파일링 실행

$ npm run build
  • 트랜스파일링에 성공하면 프로젝트 루트 폴더에 dist/js 폴더가 자동으로 생성되고 트랜스파일링된 main.js와 lib.js가 저장

트랜스파일링된 main.js 실행 및 결과

$ node dist/js/main

# 실행결과
3.141592653589793
36.4621596072079
{ a: 1, b: 2, x: { c: 3, d: 4 } }
10

1.5 브라우저에서 모듈 로딩 테스트

index.html 작성(루트 폴더에 작성)

<!DOCTYPE html>
<html>
<body>
    <script src="dist/js/lib.js"></script>
    <script src="dist/js/main.js"></script>
</body>
</html>

  • 브라우저는 CommonJS 방식의 require 함수를 지원하지 않으므로 트랜스파일링된 결과를 그대로 브라우저에서 실행하면 에러가 발생함
  • Webpack을 통해 해결할 수 있음

2. Webpack

웹팹은 여러개 파일을 하나로 합쳐주는 모듈 번들러이다.
  • Webpack은 의존 관계에 있는 자바스크립트, CSS, 이미지 등의 리소스들을 하나(또는 여러 개)의 파일로 번들링
  • 여러 개의 자바스크립트 파일을 하나로 번들링하므로 HTML 파일에서 script 태그로 여러 개의 자바스크립트 파일을 로드해야하는 번거로움도 사라짐

왜 웹팩을 사용할까?

번들러를 사용하면 여러개 파일을 하나로 묶어주기 때문에 네트워크 접속의 부담을 줄여 더 바른 서비스를 제공할 수 있다.

2.1 Webpack 설치

npm install --save-dev webpack webpack-cli

package.json

{
  "name": "esnext-project",
  "version": "1.0.0",
  "scripts": {
    "build": "babel src/js -w -d dist/js"
  },
  "devDependencies": {
    "@babel/cli": "^7.19.3",
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.20.2",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.0"
  }
}
  • webpack과 webpack-cli가 추가된 것을 확인할 수 있음

2.2 babel-loader 설치

babel-loader 설치

$ npm install --save-dev babel-loader
  • Webpack이 모듈을 번들링할 때 Babel을 사용하여 ES6/ES.NEXT 사양의 소스코드를 ES5 사양의 소스코드로 트랜스파일링하도록함

package.json 파일의 scripts 변경

{
  "name": "esnext-project",
  "version": "1.0.0",
  "scripts": {
    "build": "webpack -w"
  },
  "devDependencies": {
    "@babel/cli": "^7.19.3",
    "@babel/core": "^7.20.5",
    "@babel/preset-env": "^7.20.2",
    "babel-loader": "^9.1.0",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.0"
  }
}

2.3 webpack.config.js 설정 파일 작성

webpack.config.js

const path = require('path');

module.exports = {
    // entry file
    entry: './src/js/main.js',

    // 번들링된 js 파일의 이름(filename)과 저장될 경로(path)를 지정
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/bundle.js'
    },

    module: {
        rules: [
            {
                test: /\.js$/,
                include: [
                    path.resolve(__dirname, 'src/js')
                ],
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env'],
                        plugins: ['@babel/plugin-proposal-class-properties']
                    }
                }
            }
        ]
    },
    devtool: 'source-map',
    mode: 'development'
}
  • 루트폴더에 생성
  • Webpack이 실행될 때 참조하는 설정 파일

Webpack 실행

$ npm run build
  • 트랜스파일링 및 번들링

index.html 수정

<!DOCTYPE html>
<html>
<body>
    <script src="./dist/js/bundle.js"></script>
</body>
</html>

실행 결과

  • main.js, lib.js 모듈이 하나의 bundle.js로 번들링 됨

2.4 babel-polyfill 설치

  • babel-polyfill은 ES6에서 추가된 Promise, Object.assign, Array.from 등을 트랜스파일링

main.js에 polyfill이 필요한 코드 추가

import { pi, power, Foo } from './lib'

console.log(pi)
console.log(power(pi, pi));

const f = new Foo();
console.log(f.foo());
console.log(f.bar());

// polyfill이 필요한 코드
console.log(new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 100);
}));

// polyfill이 필요한 코드
console.log(Object.assign({}, { x: 1 }, { y: 2 }));

// polyfill이 필요한 코드
console.log(Array.from([1, 2, 3], v => v + v));

@babel/polyfill 설치

$ npm install @babel/polyfill

main.js

import "@babel/polyfill"
import { pi, power, Foo } from './lib'
...
  • import시 폴리필을 먼저 로드함

webpack.config.js에 폴리필 추가

const path = require('path');

module.exports = {
    // entry file
    entry: ['@babel/polyfill', './src/js/main.js'],

    ...
}

웹팩 실행 및 결과

$ npm run build





참고자료

Webpack 과 Babel이란 무엇일까?

웹팩은 여러개 파일을 하나로 합쳐주는 모듈 번들러이다.웹팩은 기본적으로 모듈을 지원하고 파일 분할 기능(원하는 코드만 따로 분리해서 하나의 파일로 압축이 가능하다), css loader기능, jsx변

velog.io








반응형
Comments