Notice
Recent Posts
Recent Comments
관리 메뉴

즐겁게, 코드

esbuild 가볍게 살펴보기 본문

💬 언어/Javascript

esbuild 가볍게 살펴보기

Chamming2 2022. 7. 1. 16:44

TL;DR

  • esbuild는 정말 빠른 도구지만, 실제 환경에서 웹팩을 대체하기에는 아직은 시간이 더 필요할 것 같다.

웹 프론트엔드 분야를 학습해보신 분들이라면 한번쯤은 "이제 웹팩이 뭔지 공부해볼까?" 했다가, 복잡한 웹팩 설정과 플러그인들로 인해 좌절된 적이 있을 것입니다.

 

이번 글에서는 웹팩을 언젠가는 대체할 가능성이 있는 차세대 번들러, esbuild를 알아보며 느낀 점을 가볍게 적어보려 합니다.

이게 가능하다고? : esbuild의 번들링 속도

go가 빠르다 빠르다 해도 이 정도까지일줄은...

esbuild는 go로 만들어진 차세대 번들러로, 공식 홈페이지 의 대문에서부터 기존의 도구들과는 차원이 다른 번들링 속도를 어필합니다.

 

esbuild의 큰 장점은 기존의 주류 번들러인 Webpack 5와 비교했을 때 압도적인 퍼포먼스를 보여준다는 점과, 별도의 플러그인 없이도 타입스크립트 트랜스파일과 minify가 가능하다는 점이 장점으로 느껴졌습니다.

Webpack과의 번들링 성능 비교

과연 esbuild의 번들링이 정말로 웹팩보다 100배나 빠른지도 궁금했고, 한번 실제로 사용해보고 싶어 간단한 테스트를 수행해 보았습니다.

테스트는 제가 최근에 진행했던 프로젝트를 Webpack 5와 esbuild 0.14 버전으로 번들링해 진행했습니다.

 

GitHub - C17AN/KAUBOARD-2.0: 🛫 한국항공대 종합정보 크롬 익스텐션 🖥

🛫 한국항공대 종합정보 크롬 익스텐션 🖥. Contribute to C17AN/KAUBOARD-2.0 development by creating an account on GitHub.

github.com

  • 빌드 스크립트
"scripts": {
  "esbuild-build": "esbuild src/index.tsx --bundle --minify --outdir=dist",
  "webpack-build": "webpack ./src/index.tsx --mode=production"
},
  • 웹팩 설정 파일
    • 순수 번들링 성능만을 보기 위해 린트 및 타입 체크 플러그인은 생략했습니다. 
    • esbuild의 번들링은 별도의 설정 파일 없이 진행했습니다.
const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: path.join(__dirname, 'src', 'index'),
  watch: true,
  output: {
    path: path.join(__dirname, 'dist'),
    publicPath: '/dist/',
    filename: "bundle.js",
    chunkFilename: '[name].js'
  },
  module: {
    rules: [{
      test: /.jsx?$/,
      include: [
        path.resolve(__dirname, 'src')
      ],
      exclude: [
        path.resolve(__dirname, 'node_modules')
      ],
      loader: 'babel-loader',
    }, {
      test: /\.tsx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/,
      options: {
        transpileOnly: true
      }
    }, {
      test: /\.css$/,
      use: ['style-loader', 'css-loader'],
    },
    {
      test: /\.s[ac]ss$/i,
      use: ['css-loader', 'sass-loader'],
      exclude: /node_modules/
    }
    ]
  },
  externalsPresets: { node: true },
  externals: [nodeExternals()],
  resolve: {
    extensions: ['.json', '.js', '.jsx', ".ts", ".tsx"]
  },
};

그리고 TS → JS 트랜스파일링, 번들링, minify를 수행한 결과물입니다.

  • 실제 프로젝트 디렉토리에서의 react-scripts build : 약 40초 
  • 웹팩 : 약 3.6 ~ 3.8초
  • esbuild: 약 1 ~ 1.5초

웹팩 작업 결과물 (약 4초)
esbuild 작업 결과물 (약 1초)

느꼈던 esbuild의 장단점

JS → TS 트랜스파일링 + 번들링 + minify 과정을 별도의 플러그인 없이 수행할 수 있는 점은 분명 장점으로 느껴졌습니다.

하지만 단점 역시 없지만은 않았는데요, 한번 좋았던 점과 몇 가지 아쉽게 느껴졌던 점을 적어 보도록 하겠습니다.

  • 장점  : 빠른 번들링 속도와 편리성
    • 당연한 이야기일 수 있지만 웹팩에 비해 빨랐습니다!
    • 위에서 실행한 테스트 이후 전체 firebase 모듈을 번들링해보기도 했는데, 그 때도 약 0.8초 ~ 1초라는 시간 안에 번들링을 마쳐 속도 하나만큼은 정말 빠르다고 느낄 수 있었습니다.
  • 단점 : 커뮤니티 플러그인의 부족
    • 대표적으로 esbuild에는 아직 공식 문서에서 sc(a)ss 로더를 지원하지 않고 있습니다.
      커뮤니티에서 제작한 로더(esbuild-plugin-sass, esbuild-sass-plugin)들 역시 아직 완전해 보이지는 않았습니다.
    • esbuild 자체가 아직 정식 버전이 아니라 그럴 수는 있겠지만, 아직은 웹팩 플러그인의 생태계를 완전히 따라가기는 어려울 것 같았습니다.
  • 단점 : es6 이상만을 지원하는 트랜스파일링
    • '모던 자바스크립트' 라고 불리는 es6(es2015) 미만 버전으로의 트랜스파일이 불가능한 점은 상황에 따라 치명적인 약점이 될 수 있을 것 같았습니다. (Ex. 구버전 브라우저만을 실행할 수 있는 POS 기기용 프로젝트)

추가 : esbuild-wasm

go로 만들어진 esbuild를 웹어셈블리로 이식한 esbuild-wasm을 사용할 수도 있습니다.

 

하지만 esbuild-wasm은 코드를 실행할 때마다 웹어셈블리 코드를 node.js로 컴파일해야 하고, node.js가 웹어셈블리를 처리할 때 발생할 수 있는 잔여 이슈들로 인해 권장되지는 않는 방법입니다. 

⛔️ 이로 인해 공식 문서에서도 esbuild-wasm은 esbuild보다 훨씬 느릴 수 있다고 경고하고 있습니다.

그럼에도 불구하고 런타임에서 esbuild를 사용한 트랜스파일이 가능하다는 점을 살려 아래처럼 온라인 트랜스파일러를 만들 수도 있습니다. (글을 처음 작성할 때는 몰랐는데, 나중에 알고 나니 바벨에서도 이미 지원하는 기능이라고 하네요 🥲)

 

반응형
Comments
소소한 팁 : 광고를 눌러주시면, 제가 뮤지컬을 마음껏 보러다닐 수 있어요!
와!! 바로 눌러야겠네요! 😆