How webpack is handling JS modules? - 웹팩 딥다이브
글을 쓰게 된 이유?
매일 같이 Bundling을 위해 사용하는 webpack에 대하여 알아야 할 필요를 느꼈고, 서로 다른 타입의 모듈을 웹팩이 어떻게 처리하는지 궁금해져서 medium, 블로그, 칼럼들을 읽고 정리해보게 되었다.
ES 모듈 vs CommonJS 모듈
1. CommonJS 모듈 내보내기 방법
바로 module.exports 객체를 변경하는 방식이다. 여기에 Property를 추가하거나 다른 객체로 변경해서 내보낼 수 있다.
module.exports.copy = function() {};
module.exports.paste = function() {};
module.exports = {
copy: function() {},
paste: function() {}
};
2. CommonJS 모듈 가져오기 방법
바로 require 함수의 return 값을 사용할 수 있다.
const word = require('word');
word.copy();
word.paste();
3. ES 모듈 내보내기 방법
Named export 와 Default value export 방법이 존재한다.
// word.js
export const copy = function() {};
export const paste = function() {};
import {copy, paste} from './word';
copy();
paste();
// word.js
const wordNames = ['copy', 'paste'];
export default wordNames;
import word from './word';
word[0]; // 'copy'
word[1]; // 'paste'
4. ES 모듈 가져오기 방법
이때는 import , from 으로 가져올 수 있다.
import {copy, paste} from 'word'; // named
import Word from 'word'; // default
이름을 붙인 경우, 모듈 파일에 정의된 객체 이름을 중괄호 안에 넣어 가져오고 기본값의 경우 이름만 사용하면 된다.
여기서부터는 Webpack Bundle에 대한 내용이 나온다.
Webpack이 모듈들의 내보내기를 어떻게 Handling 하고 있는지 살펴보자.
Webpack은 어떻게 처리하나
import a, {aName} from './a';
import b, {bName} from './b';
let isB = true;
export function sayName(name) {
const formatter = isB ? b : a;
isB = !isB;
return `Hello! ${formatter(name)}!`;
}
B는 commonjs 방식으로 내보내기 하였으며,
module.exports = function(name) {
return '<b>' + name + '</b>';
};
module.exports.bName = 'b'
A는 es 방식으로 내보내기 하였다.
export const aName = 'i';
export default function(name) {
return '<i>' + name + '</i>';
}
그런데 이때 두 모듈 모두 es 방식으로 가져오기를 할 수도 있다.
import a, {aName} from './a';
import b, {bName} from './b';
그 이유는 번들된 코드를 살펴보면 힌트를 얻을 수 있는데
var _b__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("./src/b.js");
var _b__WEBPACK_IMPORTED_MODULE_0___default = __webpack_require__.n(_b__WEBPACK_IMPORTED_MODULE_0__);
b모듈은 commonjs 방식으로 내보내기 했기 때문에 __webpack_require_.n 으로 한번 감싼다음 새로운 변수명인 유심히 보아야 할곳을 볼드 처리 해봤다. 자세히 보면, bold 모듈이 commonjs 방식으로 내보내졌기 때문에 _b__WEBPACK_IMPORTED_MODULE_0___default 에 모듈을 할당한 것을 확인할 수 있다.
const formatter = isB ?
_b__WEBPACK_IMPORTED_MODULE_0___default.a
:_a__WEBPACK_IMPORTED_MODULE_1__["default"];
이처럼 _b__WEBPACK_IMPORTED_MODULE_0___default.a 모듈 가져오기를 실행하는 걸 확인할 수 있다.