20220203 TIL

bandor·2022년 2월 4일
0

TIL

목록 보기
10/11

babel 설정에서 module type이 commonJS일 경우 dynamic import를 통한 code splitting이 적용되지 않는 문제(미해결)

과거 만들었던 MBTI 사이트에서 json파일을 import하지 못하는 문제가 발생했었다. 이를 해결하기 위해 구글링을 하다가 카카오 개발블로그에 기재된 방식을 적용함으로서 문제를 해결했다.

🤔 왜 해결되었는가?

"commonJS와 ESModule을 함께 사용하기 위해서 @babel/plugin-transform-modules-commonjs, 즉 preset-envmodules 옵션을 "cjs"로 설정함으로서 해결할 수 있다".

는 내용이 있다.

지금 생각해보면 json파일 import와 module type이 무슨 연관이 있다고 덜컥 적용했는지 모르겠지만, 놀랍게도 preset-env 옵션에 modules: "cjs"를 추가함으로서 해결할 수 있었다.🥲

(문제의 진짜 원인은 ESModule 형식에서 json파일을 destructuring하듯이 import한 것이었는데 말이다..)

// data.json
{
  "questions": [...]
}
// ESModule : ❌ / CommonJS : ✅
import { questions } from "./data.json"; 

// 둘 다 ✅
import data from "./data.json";
const { questions } = data;	

default import가 ESModule에서 동작하는 이유를 확인하기위해 bundle된 파일을 확인해보니, json을 읽으면서 key값을 임의의 값으로 변경해오고 있었다.

const data_namespaceObject = JSON.parse('{"X":[...]}'); // questions이란 key를 X로 바꿨다.
var questions = data_namespaceObject.X;

commonJS에서 두 방식이 어떻게 변환되는지 확인하기위해 bundle 파일을 확인해봤다.

// __webpack_require__
// :인자로 받은 moduleId로 __webpack_modules__에서 module을 탐색해 돌려주는 함수.
// 9497은 JSON.parse('{"questions":[...]}')을 의미함.

// import data from "./data.json";
var _sample = _interopRequireDefault(__webpack_require__(9497));
var questions = _sample["default"].questions;
console.log(questions);

// import { question } from "./data.json";
var _sample = __webpack_require__(9497);
console.log(_sample.questions);

정확한 동작원인은 babel core를 찬찬히 뜯어봐야 알겠지만, 변환된 결과가 이렇게 다르구나~ 정도는 쉽게 확인했다.. (언제 뜯어보나..🥲)

하지만 또다른 문제가 발생했다...

page component들을 splitting하기 위해 React.lazy와 dynamic import를 적용했는데, 의도한대로 chunk가 만들어지지 않았다..

babel CLI로 직접 transpiling을 했을 땐, 코드상 차이는 없었다.
오히려 bundling 결과에서 많은 차이를 보였다..

해결하려 했던 문제와는 상관없지만, 참고했던 게시글대로 modules: "cjs" 를 추가하지 않으면 commonJS와 ESModule을 함께 사용할 수 없는 지 직접 알아보기 위해 테스트 해봤다. babel만 돌린 결과에선 modules: "cjs" 여부와 상관없이 _interopRequireDefault가 추가되면서 에러가 재현되지 않았다..

아무래도 babel-loader 혹은 webpack에서 관련 설정을 건드는 게 있는 모양이다.. 좀 더 살펴봐야겠다..

profile
빵돌입니다. 빵 좋아합니다.

0개의 댓글