Programming/Frontend

Parcel 번들러 Migration 후기 (parcel-bundler -> parcel)

sangsangjin 2023. 1. 6. 17:25

인턴 때부터 지금까지 맡은 프로젝트 중 하나는 데이터 수집 SDK이다.

사내 웹/앱 서비스 개발자 분들이, SDK를 이용하여 브라우저에 생성하면,

기 정의된 로그 포맷에 해당하는 data들을 서버로 전송하는 역할을 한다.

 

해당 SDK는 여러가지의 js 파일로 구성되어 있고, 번들러를 이용하여 빌드 된 파일을 다른 개발자분들이 로드해서 사용한다.

 

번들러에는 webpack, RequireJS, Browserify, Rollup, Parcel 등이 있는데, 해당 프로젝트에는 Parcel v1이 적용되어 있었다.

올해(2022) 업무 중 하나는 번들러인 Parcel의 마이그레이션 작업이었다. (버전 업그레이드)

 

Parcel v1은 npm에서 parcel-bundler로 명시되어있고, v2는 parcel로 명시되어 있다.

(v1인 parcel-bundler는 현재 deprecated이다!!)

이름이 비슷해서 잘못 설치할 가능성이 있다...

 

https://www.npmjs.com/package/parcel-bundler.

 

parcel-bundler

Blazing fast, zero configuration web application bundler. Latest version: 1.12.5, last published: 2 years ago. Start using parcel-bundler in your project by running `npm i parcel-bundler`. There are 522 other projects in the npm registry using parcel-bundl

www.npmjs.com

https://www.npmjs.com/package/parcel

 

parcel

Blazing fast, zero configuration web application bundler. Latest version: 2.8.1, last published: a day ago. Start using parcel in your project by running `npm i parcel`. There are 231 other projects in the npm registry using parcel.

www.npmjs.com

또, 구글에 parcel를 검색하면 맨 위에, 한글 번역본 docs가 있는데, 패키지 이름으로 알 수 있듯이, v1에 관한 docs이다.

 

가볍게 무시하고, 영어 docs 읽기 시작하면 된다. 왜냐면 내가 무시 안하고 다 읽었다..

https://parceljs.org/

 

Parcel – The zero configuration build tool for the web.

Parcel combines a great out-of-the-box development experience with a scalable architecture that can take your project from just getting started to massive production application.

parceljs.org

결론은 위 페이지를 읽고, 적용해 보면 되는데 v1인 parcel-bundler에서 v2인 parcel로 마이그레이션 과정에서 겪었던 에러에 대해 공유하고자 한다. (번들러가 뭔지, 사용 방법 같은 건 사실 구글링하면 다 나오기도 하니까 적어봤자 별 의미 없..)

 

https://parceljs.org/getting-started/migration/ 는 번들러 업그레이드 가이드인데,

 

해당 Docs를 읽으며 진행하였다. (Docs는 천천히 똑바로 읽자.)

 

1. 빌드 결과물의 경로를 지정하는 옵션이라 그냥 이름만 바꿔주면 된다.

2. 다양한 버전을 지원해야하는 SDK 특성상 v1에서는 -o라는 --out-file 옵션을 통해 다양한 버전 (IE버전,Modern Browser 버전)의 빌드가 가능했다. 하지만 v2로 오면서 --out-file 옵션이 제거되었고, targets 옵션을 통해 다양한 버전의 빌드를 진행했다.

Docs에서 이 부분 찾느라 시간이 좀 걸렸다.

나의 경우 v1의 빌드 scripts는 다음과 같았는데

    "build-rake:ie": "parcel build src/js/components/Rake/RakeIE.js --no-source-maps --dist-dir build/output/rake --detailed-report",
    "build-rake:ie8": "parcel build src/js/components/Rake/RakeIE8.js --no-source-maps --dist-dir build/output/rake --detailed-report && npm run gulp-build",
    "build-rake:modern": "parcel build src/js/components/Rake/RakeModern.js --no-source-maps --dist-dir build/output/rake --detailed-report",

 

v2의 빌드 scripts는 다음처럼 변경 되었다.

  "RakeModern": "build/output/rake/rake.bundle.js",
  "RakeIE": "build/output/rake/rake.bundle-ie.js",
  "targets": {
    "RakeModern": {
      "source": "src/js/components/Rake/RakeModern.js",
      "distDir": "build/output/rake",
      "sourceMap": false
    },
    "RakeIE": {
      "source": "src/js/components/Rake/RakeIE.js",
      "distDir": "build/output/rake",
      "sourceMap": false
    }
  },

 

3. --experimental-scope-hoisting (문제의 그것..)

업그레이드를 진행하면서 가장 시간이 오래 걸렸으면서, 해결법이 참 어이없게 쉬운 것이어서 힘을 뺐었다.

 

그 전에, scope-hosting이 무엇일까?

https://parceljs.org/features/scope-hoisting/ 에 자세히 나와 있지만, 쉽게 이해가 가지 않았다.

 

그래도 읽어보아야 한다. Blog Driven Development는 위험하다.


나의 언어로 정리해 보자면 다음과 같다. (세 줄 요약 간다.)

 

  1. Parcel 말고 다른 번들러들은 함수의 모듈들을 wrapping하는 방식으로 동작해 왔다. (그런데 이게 비용이나 성능적으로 별로다.)
  2. build할 때, Parcel는 다른 번들러들처럼 wrapping하는 방식말고, single scope로 연결해버리겠다. 그리고 우리는 이거를 scope-hoisting이라고 부르겠다.(지들 맘대로 만든다.) (이 방식이 비용,성능적으로 더 낫다고 한다.)
  3. build시 필요 없는 코드를 제거하는 tree-shaking도 하겠다.

결론) tree-shaking + single scope로 연결해서 성능을 높이는 빌드 방법 => scope-hoisting


위 사진의 내용은

v1에서는 --experimental-scope-hoisting 즉 실험적인 기능으로 해당 옵션을 작성해야만 빌드시 작동했는데,

v2에서부터는 default로 scope-hoisting이 동작하고, 원치 않을 경우 --no-scop-hoist를 작성해라 라는 뜻이다.

 

하지만 멍청하게도 제대로 읽지 않은 나는 저 사진 보이는 그대로 

--experimental-scope-hoisting 을 --no-scoipe-hoist로 바꿔버렸다. (기능을 그대로 쓰려면 --no-scope-hoist를 붙이지 않아야했다. 이것이 삽질의 시작이었다.)

 

script에 이 한 단어를 붙이는 실수는 다음의 결과를 초래했다.

얍! 오류 발생!

이처럼 arrow function이 변환되지 않아, IE를 지원해야하는 sdk가 동작하지 않는 것이었다.

 

옵션 문제인 줄 모르고, 나는 babel이 문제인가? polyfill을 까먹었나? 이러면서 온갖 삽질을 다 해보기 시작했다.

 

그리고 ' 아 이것은 parcel v2의 문제일 수도 있겠다.' '나도 한번 오픈소스에 기여하는 PR 날려보자' 라는 자신만만한 멍청이의 방향으로 흘러갔다.

https://github.com/parcel-bundler/parcel/issues/7830

 

parcel 2: @parcel/transformer-js/src/esmodule-helpers.js is not being transpiled correctly when building for IE11 · Issue #783

🐛 bug report Parcel includes an internal file when building for IE11 (@parcel/transformer-js/src/esmodule-helpers.js), but that file is not transpiled (arrow function is not compiled) The error is ...

github.com

(다시 보니 참 부끄럽다...)

그렇다. 위에서 언급한 것 처럼 내가 그냥 docs 제대로 안 읽고, default로 장착된 scope-hoist 옵션 빼놓고, 컴파일 오류난다고 난리였던 것이다. (해당 issue 제기하고 혼자 close하고, 북치고 장구치고 다했다...)

 

해당 똥꼬쇼 이 후, Docs를 읽을 때 좀 더 주의를 기울이게 되었고, 파파고 번역 익스텐션을 추가로 설치했다. 

그래도 이런 경험 통해서, 마이그레이션도 진행해보고 재미있었다.

(이 글을 보시는 분들은 나와 같은 실수를 하지 마세요..)