번들러(요약)

HumbleMincho·2024년 7월 5일

Metro와 ESBuild (+WebPack)은 무엇인가


왜 필요한가?

javascript코드 작성(단일 파일) → JavaScript 엔진(Hermes, V8)실행 → Native코드 호출(UI View, android.view 렌더링)

번들링이란 쪼개진 모듈을 단일 파일로 합쳐서 만들어줌. 그역할을 해주는 친구가 번들러.

과거 EcmaScript 표준 Module 시스템이 없었을 때는 WebPack과 같은 번들러가 작업해줌. (옛날엔 browserify라는 번들러가 있었음)


번들러가 하는 일

Resolution

  1. 번들러가 파일을 합치는 과정에서는 import나 require의 경로를 정확하게 알아야 함.
import { App } from './App';
...

그래서 ./App.js?, ./App.ts?, ./App.tsx?, ./App/index.js?, ./App/index.ts?, ./App/index .ios.js? 인지 모르니, 확장자를 포함한 정확한 경로를 풀어냄(resolve)

  1. 예시
import { Component1 } from 'components/Compnent1';
import { Component2 } from 'components/Compnent2';
...

compoents 라는 npm 패키지인가???
src/components 인가?
lib/components 인가?

  1. 즉, import/require되는 파일 위치를 정확하게 찾아주는 일
    1. ./App → /Users/minsu/workspace/123123/service/A/App.js

Load

  1. TypeScript는 Javascript가 아니다! → 브라우저나 RN에서 바로 실행할 수가 없당 → TS를 JS로 바꿔야 한다!(Flow도 Javascript가 아니다!)
  2. 즉, JavaScript가 아닌 파일을 표준 JavaScript로 옮기는 작업임.
  3. 일반적인 Loader
graph TD
  TypeScript/Flow --> Babel/SWC --> 표준JavaScript

특히, RN 라이브러리는 Flow나 TypeScript등 JavaScript가 아닌 형태를 사용하는 경우가 많음.

metro.config.js

module.exports = {
	transformerPath: /* Transformer JS 파일 경로 */
}

transformer.js

class Transformer {
	async transformFile(
	/*Load할 파일(e.g, TS, Flow, ...)*/
	filePath: string,
	/* Babel 등 관련된 옵션 */
	transformerOptions: TransformerOptions,
	){
		return { result: {data: {code: /* Load된 결과 */}}}
	}
}

Resolution + Load 결과: 완전한 1개의 JavaScript 파일 완성

  • import 파일 모두 찾기
  • Load → 표준 JS로 변환
  • 변환된 파일 모두 합치기

Optimization

  • 번들러의 또 하나의 역할: 파일 크기를 작게 줄이는 테크닉
  • 번들링만으로는 파일이 너무 커서 성능이 떨어짐

1. Minification: 압축 및 이름 바꿔주기

  1. 소스코드에서 압축할 수 있는 텍스트를 최대한 줄임
  2. 압축(Compression)
      undefined ->  void 0 
        2 + 3   ->   5
       !a && !b ->   !(a || b)
       Infinity ->   1/0
  3. 이름 바꿔주기(Mangling)
    function add(num1, num2){ return num1 + num2; }
    
    function add(n, r){ return n + r; }

2. Tree Shaking

  1. import된 코드 가운데 사용하지 않는 것을 선제적으로 삭제하는 것.
      import { add } from '@toss/utils';
      
      add함수 말고 나머지 코드는 제거해도 될 것 같음
      
      import '@scope/some-library/initialize';
      
      어떤 코드도 제거해서는 안될 것 같음
  2. sideEffects
      ```tsx
        {
        	"name" : '@toss/utils',
        	// ...
        	"sideEffects" : false
        }
        
        모든 안 쓰는 파일을 제거할 수 있음
      ```
        
      ```tsx
        {
        	"name" : 'react-native-reanimated',
        	// ...
        	"sideEffects" : [/* 제거 금지 파일 목록 */]
        }
        
        sideEffects 파일은 제거할 수 없음.
      ```
    Minification(Compression, Mangling)은 대부분의 번들러에서 기본 지원
    Tree shaking은 Metro는 미지원, ESBuild는 지원
profile
최고의 효율을 창출하기 위해 겸손히 노력합니다.

0개의 댓글