연습장

02. ES6 -> babel + Webpack 본문

클론코딩해보기/환경 세팅

02. ES6 -> babel + Webpack

js0616 2024. 8. 11. 21:44

https://poiemaweb.com/es6-babel-webpack-2

 

Webpack | PoiemaWeb

앞에서 테스트해 본 바와 같이 ES6 모듈을 현재의 브라우저에서 사용하려면 [RequireJS](http://requirejs.org/) 또는 [SystemJS](https://github.com/systemjs/systemjs)와 같은 모듈 로더가 필요하다. [Webpack](https://webpac

poiemaweb.com

 

이전내용

main.js와 lib.js 모듈을 babel로 트랜스파일링하여 ES5로 변환된 main.js을 node 에서 실행할 수 있지만,

브라우저에서 실행 시 에러가 발생한다. 이에 대한 해결 방법으로 webpack 이 있다.. ?

 

2.1 Webpack이란?
Webpack은 의존 관계에 있는 모듈들을 하나의 자바스크립트 파일로 번들링하는 모듈 번들러이다. 

Webpack을 사용하면 의존 모듈이 하나의 파일로 번들링되므로 별도의 모듈 로더가 필요없다. 

그리고 다수의 자바스크립트 파일을 하나의 파일로 번들링하므로 html 파일에서 script 태그로 다수의 자바스크립트 파일을 로드해야 하는 번거로움도 사라진다.

 

번들링 : 묶는것 

의존 관계 : 코드간에 영향을 주고 받음

 

 

Webpack 설치

npm install --save-dev webpack webpack-cli

 

package.json

{
  "name": "es6_setting",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "build": "babel src/js -w -d dist/js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@babel/cli": "^7.24.8",
    "@babel/core": "^7.25.2",
    "@babel/preset-env": "^7.25.3",
    "webpack": "^5.93.0",
    "webpack-cli": "^5.1.4"
  }
}

 

앞서 했던 babel 과 함께 webpack 이 설치된것을 확인

 


babel-loader
Webpack이 모듈을 번들링할 때, Babel을 사용하여 ES6+ 코드를 ES5 코드로 트랜스파일링하도록 babel-loader를 설치한다.

npm install --save-dev babel-loader

 

npm script를 변경하여 Babel 대신 Webpack을 실행하도록 수정

{
  "name": "es6_setting",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "build": "webpack -w"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@babel/cli": "^7.24.8",
    "@babel/core": "^7.25.2",
    "@babel/preset-env": "^7.25.3",
    "babel-loader": "^9.1.3",
    "webpack": "^5.93.0",
    "webpack-cli": "^5.1.4"
  }
}

 

 

webpack.config.js 작성

webpack.config.js은 Webpack이 실행될 때 참조하는 설정 파일이다.

프로젝트 루트에 webpack.config.js 파일을 생성하고 아래와 같이 작성한다.

const path = require('path');

module.exports = {
  // enntry file
  entry: './src/js/main.js',
  // 컴파일 + 번들링된 js 파일이 저장될 경로와 이름 지정
  output: {
    path: path.resolve(__dirname, 'dist/js'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [
          path.resolve(__dirname, 'src/js')
        ],
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },
  devtool: 'source-map',
  mode: 'development'
};

 

 

Webpack을 실행하여 트랜스파일링 및 번들링을 실행한다. 트랜스파일링은 Babel이 실행하고 번들링은 Webpack이 실행한다.

npm run build

dist/js/bundle.js 가 생성된다.

 

index.html 을 수정하고

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

 

실행

 

main.js, lib.js 모듈이 하나로 번들링된 bundle.js가 브라우저에서 문제없이 실행

 


2.5 babel-polyfill

Babel을 사용하여 ES6+ 코드를 ES5 이하로 트랜스파일링하여도 브라우저가 지원하지 않는 코드가 남아 있을 수 있다.

예를 들어, ES6에서 추가된 Promise, Object.assign, Array.from 등은 ES5 이하로 트랜스파일링하여도 대체할 ES5 기능이 없기 때문에 그대로 남아 있다.

 

src/js/main.js를 아래와 같이 수정하여 ES6에서 추가된 Promise, Object.assign, Array.from 등이 어떻게 트랜스파일링되는지 확인해 보자.

// 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());

// 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));

 

다시 트랜스파일링과 번들링을 실행한 다음, dist/js/bundle.js을 확인

Promise, Object.assign, Array.from 등과 같이 ES5 이하로 대체할 수 없는 기능은 트랜스파일링이 되지 않는다.

따라서 오래된 브라우저에서도 ES6+에서 새롭게 추가된 객체나 메소드를 사용하기 위해서는 @babel/polyfill을 설치해야 한다.

 

babel-polyfill은 실제 환경에서도 사용하여야 하므로 --save-dev 옵션으로 개발 설치를 하지 않도록 한다.

npm install @babel/polyfill

 

 

ES6의 import를 사용하는 경우

진입점(Entry point) 의 선두(Head)에서 먼저 폴리필을 로드하도록 한다.

// src/js/main.js
import "@babel/polyfill";

 

 

webpack을 사용하는 경우

폴리필을 webpack.config.js 파일의 entry 배열에 추가한다.

// webpack.config.js
const path = require('path');

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

 

다시 npm run build 실행

 

dist/js/bundle.js을 확인해보면 polyfill이 추가된 것을 확인할 수 있다.

 

갑자기 코드가 1만줄이 넘어가는데, 이게 맞게 된건지 모르겠네 ..