과거 만들었던 MBTI 사이트에서 json파일을 import하지 못하는 문제가 발생했었다. 이를 해결하기 위해 구글링을 하다가 카카오 개발블로그에 기재된 방식을 적용함으로서 문제를 해결했다.
🤔 왜 해결되었는가?
"commonJS와 ESModule을 함께 사용하기 위해서
@babel/plugin-transform-modules-commonjs
, 즉preset-env
의modules
옵션을"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에서 관련 설정을 건드는 게 있는 모양이다.. 좀 더 살펴봐야겠다..