A 10 minute primer to JavaScript modules, module formats, module loaders and module bundlers - Lee-hyuna/33-js-concepts-kr GitHub Wiki
A 10 minute primer to JavaScript modules, module formats, module loaders and module bundlers
μ΅μ μ JS κ°λ°μ κ°λ ₯ν©λλ€.
νλ‘μ νΈλ₯Ό μ§νν λ μ μ΅μ μ λꡬμ ν΄λ€μ΄ νμνμ§ κΆκΈν μ μμ΅λλ€.
Webpack κ³Ό SystemJS μ κ°μ ν΄λ€μ 무μμΈκ°μ ? λ AMD, UMD, CommonJS λ λ¬΄μ¨ μλ―ΈμΈκ°μ ? κ·Έκ²λ€μ λ¬΄μ¨ μ°κ΄μ΄ μλμ? μ νμλ‘ νκ°μ ?
μ΄ κΈμμλ λ€λ₯Έ JS λͺ¨λμ λͺ¨λμ νμ, λ‘λ λ° λ²λ€μ λνμ¬ νμ΅ν©λλ€.
λ€λ₯Έ λꡬμ ν¨ν΄λ€μ μ΄ν΄λΏλ§ μλλΌ μ΅μ JS κ°λ°μ λν κ°λ λ μ΄ν΄ν μ μμ κ² μ λλ€.
What is a module?
λͺ¨λμ΄λ μ¬μ¬μ© ν μ μλ μ½λ μ‘°κ°μ λλ€. κ·Έκ² μΈλΆ ꡬνμ μΊ‘μννκ³ public api μ λ ΈμΆνκ³ μ¬μ©νκΈ° μ½κ² ν©λλ€.
Why do we need modules?
λͺ¨λ μμ΄ μ½λλ₯Ό μμ±ν μ μμ΅λλ€.
λͺ¨λν¨ν΄μ κ°λ°μκ° 60λ λ 70λ λ μ΄ν λ€μν ννμ νλ‘κ·Έλλ° μΈμ΄λ‘ μ¬μ©ν΄μ¨ ν¨ν΄μ λλ€.
JS λͺ¨λμ λ€μκ³Ό κ°μ ννκ° μ΄μμ μ λλ€:
- μΆμν: λΌμ΄λΈλ¬λ¦¬μ κΈ°λ₯μ μμν©λλ€. ꡬνμ 볡μ‘μ±μ μ΄ν΄ν νμ μμ΅λλ€.
- μΊ‘μν: λͺ¨λ λ΄λΆμ μ½λλ₯Ό μ¨κΉλλ€.
- μ¬μ¬μ©: λμΌ μ½λμ λ°λ³΅μ νΌν©λλ€.
- μμ‘΄μ±: μμ‘΄μ±μ μ½κ² λ³κ²½ν μ μμ΅λλ€.
Module patterns in ES5
ES5 μ΄μ λ²μ μ λͺ¨λμ μΌλνμ¬ μ€κ³λμ§ μμμ΅λλ€. κ°λ°μλ€μ JS μμμ λͺ¨λν¨ν΄μ ꡬννκΈ°μν΄ λ€μν λ°©λ²μ μκ°νμ΅λλ€.
λ κ°μ§μ μ¬μ΄ ν¨ν΄μ μ΄ν΄λ³΄κ² μ΅λλ€. μ¦μ μ€νν¨μ:
(function(){
// ...
})()
IIFE λ μ μΈ λ λ νΈμΆλλ μ΅λͺ ν¨μμ λλ€.
JS μμλ function μ΄λΌλ λ¨μ΄λ‘ μμνλ μ€μ ν¨μ μ μΈμΌλ‘ νλ¨ν©λλ€.
// Function declaration
function(){
console.log('test');
}
μ¦μ ν¨μλ₯Ό νΈμΆνλ©΄ μ€λ₯κ° λ°μν©λλ€.
// Immediately Invoked Function Declaration
function(){
console.log('test');
}()
// => Uncaught SyntaxError: Unexpected token )
ν¨μλ₯Ό κ΄νΈλ‘ κ°μΈμ£Όλ©΄ ν¨μ ννμμ΄ λ©λλ€.
// Function expression
(function(){
console.log('test');
})
// => returns function(){ console.log('test') }
ν¨μ ννμμ ν¨μλ₯Ό λ°ννλ―λ‘ μ¦μ νΈμΆμ΄ κ°λ₯ν΄μ§λλ€.
// Immediately Invoked Function Expression
(function(){
console.log('test');
})()
// => writes 'test' to the console and returns undefined
μ¦μ ν¨μλ₯Ό λΆλ₯΄λ©΄ λ€μκ³Ό κ°μ λμμ΄ κ°λ₯ν©λλ€.
IIFE μμμ μ½λλ₯Ό μΊ‘μνν©λλ€. IIFE λ΄μμ λ³μλ₯Ό μ μνκΈ° λλ¬Έμ μ μ λ²μλ₯Ό μ€μΌμν€μ§ μμ΅λλ€.
κ·Έλ¬λ, μ’ μμ±μ λν κ΄λ¦¬λ₯Ό μ 곡ν΄μ£Όμ§λ μμ΅λλ€.
Revealing Module
Revealing Module ν¨ν΄μ IIFE μ μ μ¬ νμ§λ§ λ°νλ κ°μ λ³μμ ν λΉν©λλ€.
// Expose module as global variable
var singleton = function(){
// Inner logic
function sayHello(){
console.log('Hello');
}
// Expose API
return {
sayHello: sayHello
}
}()
function μ΄λΌλ λ¨μ΄κ° μ€μ μμμ μμ§ μκΈ° λλ¬Έμ κ΄νΈκ° νμ μμ΅λλ€. λ³μλ₯Ό ν΅νμ¬ λͺ¨λμ μ κ·Όν μ μμ΅λλ€.
// Access module functionality
singleton.sayHello();
// => Hello
singleton λμ μμ±μ ν¨μλ₯Ό λ ΈμΆ ν μλ μμ΅λλ€.
// Expose module as global variable
var Module = function(){
// Inner logic
function sayHello(){
console.log('Hello');
}
// Expose API
return {
sayHello: sayHello
}
}
μ μΈμ ν¨μλ₯Ό μ€ννμ§ μλμ§ μ£Όμν΄μΌν©λλ€. μμ±μ ν¨μλ₯Ό μ¬μ©νμ¬ λͺ¨λμ μΈμ€ν΄μ€ν ν©λλ€.
var module = new Module();
public api μ μ κ·Όνλ €λ©΄ μλμ κ°μ΄ ν©λλ€.
module.sayHello();
// => Hello
IIFE μ λΉμ·ν μ΄μ μ μ 곡ν©λλ€. μ’ μμ± κ΄λ¦¬λ μ§μνμ§ μμ΅λλ€.
JS κ° λ°μ λ¨μ λ°λΌ λ§μ κ΅¬λ¬Έμ΄ λ§λ€μ΄μ§λλ€. μ΄λ κ°κ° μ₯μ κ³Ό λ¨μ μ΄ μμ΅λλ€.
μ°λ¦¬λ μ΄κ²μ λͺ¨λ νμμ΄λΌκ³ λΆλ¦ λλ€.
Module formats
λͺ¨λ νμμ΄λ λͺ¨λμ μ μνλλ° μ¬μ©ν μ μλ ꡬ문μ λλ€. ES6 μ΄μ μλ JS μ μ μ λͺ¨λ νμμ΄ μμμ΅λλ€. κ°λ°μλ€μ λ€μν νμμΌλ‘ JS μμ λͺ¨λμ μ μνμμ΅λλ€.
λ§μ΄ μ±νλκ³ μλ €μ§ νμμ μλμ κ°μ΅λλ€.
- Asynchronous Module Definition (AMD)
- CommonJS
- Universal Module Definition (UMD)
- System.register
- ES6 module format
κ°κ°μ ꡬ문μ κ°λ΅νκ² μ΄ν΄λ³΄κ² μ΅λλ€.
Asynchronous Module Definition (AMD)
AMD νμμ λΈλΌμ°μ μμ μ¬μ©λλ©° μ μ ν¨μλ₯Ό λͺ¨λμ μ μν©λλ€.
//Calling define with a dependency array and a factory function
define(['dep1', 'dep2'], function (dep1, dep2) {
//Define the module value by returning a value.
return function () {};
});
CommonJS format
CommonJs λ Node μμ μ¬μ©λλ©° require λ° module exports λ₯Ό μ¬μ©νμ¬ μ’ μμ±κ³Ό λͺ¨λμ κ΄λ¦¬ν©λλ€.
var dep1 = require('./dep1');
var dep2 = require('./dep2');
module.exports = function(){
// ...
}
Universal Module Definition (UMD)
λΈλΌμ°μ μ Node μμ λͺ¨λ μ¬μ©ν μ μμ΅λλ€.
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['b'], factory);
} else if (typeof module === 'object' && module.exports) {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory(require('b'));
} else {
// Browser globals (root is window)
root.returnExports = factory(root.b);
}
}(this, function (b) {
//use b in some fashion.
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
return {};
}));
System.register
ES5 μμ ES6 λͺ¨λ ꡬ문μ μ§μνλλ‘ μ€κ³λμμ΅λλ€
ES6 module format
ES6 μμ JS λ κΈ°λ³Έμ μΌλ‘ λͺ¨λ νμμ μ§μν©λλ€. export token μ μ΄μ©νμ¬ api λ₯Ό λ΄λ³΄λ λλ€.
// lib.js
// Export the function
export function sayHello(){
console.log('Hello');
}
// Do not export the function
function somePrivateFunction(){
// ...
}
export λ λͺ¨λμ κ°μ Έμ€κΈ° μν:
import { sayHello } from './lib';
sayHello();
// => Hello
alias λ₯Ό μ΄μ©νμ¬ κ°μ Έ μ¬ μλ μμ΅λλ€.
import { sayHello as say } from './lib';
say();
// => Hello
νλ²μ μ 체 λͺ¨λμ κ°μ Έμ¬ μλ μμ΅λλ€.
import * as lib from './lib';
lib.sayHello();
// => Hello
default export λ μ§μν©λλ€.
// lib.js
// Export default function
export default function sayHello(){
console.log('Hello');
}
// Export non-default function
export function sayGoodbye(){
console.log('Goodbye');
}
λ€μκ³Ό κ°μ΄ κ°μ Έμ¬ μ μμ΅λλ€.
import sayHello, { sayGoodbye } from './lib';
sayHello();
// => Hello
sayGoodbye();
// => Goodbye
ν¨μλΏλ§μλλΌ μνλ κ²μ λ΄λ³΄λΌ μ μμ΅λλ€.
// lib.js
// Export default function
export default function sayHello(){
console.log('Hello');
}
// Export non-default function
export function sayGoodbye(){
console.log('Goodbye');
}
// Export simple value
export const apiUrl = '...';
// Export object
export const settings = {
debug: true
}
ES6 μ λͺ¨λνμμ μνκΉκ²λ λͺ¨λ λΈλΌμ°μ μμ μ§μλμ§ μμ΅λλ€. ES6 λͺ¨λ ν¬λ§·μ μ¬μ©νκΈ° μν΄ ES5 λ¬Έλ²μΌλ‘ λ³ννκΈ° μν Babel κ°μ λ³νκΈ°κ° νμν©λλ€.
Module loaders
λͺ¨λ λ‘λλ νΉμ λͺ¨λμ νμμΌλ‘ μμ±λ λͺ¨λμ ν΄μνκ³ μ½μ΅λλ€.
λ°νμμ λͺ¨λ λ‘λκ° μ€νλ©λλ€.
- λΈλΌμ°μ μ λͺ¨λ λ‘λλ₯Ό λ‘λν©λλ€.
- μ΄λ€ νμΌμ λ‘λν κ²μΈμ§ μλ €μ€λλ€.
- μ± νμΌμ λ€μ΄λ‘λνκ³ ν΄μν©λλ€.
- νμν κ²½μ° νμΌμ λ€μ΄λ‘λν©λλ€.
λΈλΌμ°μ μ κ°λ°μ μ½μμμ λ€νΈμν¬ νμ 보면 λ§μ νμΌμ΄ νμμ λ°λΌ λͺ¨λ λ‘λμ λ‘λλλ€λ κ²μ μ μ μμ΅λλ€. λ§μ΄ μ¬μ©λμ΄μ§λ λͺ¨λ λ‘λλ μλμ κ°μ΅λλ€.
- RequireJS: AMD νμμ λͺ¨λ λ‘λ
- SystemJS: AMD, common JS, UMD λλ System.gister νμμ λͺ¨λ λ‘λ
Module bundlers
λͺ¨λ λ²λ€λ¬λ λͺ¨λ λ‘λλ₯Ό λ체ν©λλ€.
λͺ¨λ λ‘λμ λ¬λ¦¬ λ²λ€μ λΉλμμ μ€νλ©λλ€.
λΉλν λ λͺ¨λ λ²λ€μ μ€ννμ¬ λ²λ€ νμΌμ μμ±ν©λλ€. λΈλΌμ°μ μμ λ²λ€νμΌμ λ‘λν©λλ€. λ€νΈμν¬ νμ νμΈνλ©΄ νλμ νμΌλ§ λ‘λν©λλ€. λΈλΌμ°μ μλ λͺ¨λ λ‘λκ° νμνμ§ μμ΅λλ€. λͺ¨λ μ½λλ λ²λ€νμΌμ ν¬ν¨λμ΄μ Έμμ΅λλ€.
λ§μ΄ μ°μ΄λ λͺ¨λ λ²λ€μ μλμ κ°μ΅λλ€.
- Browserify: bundler for CommonJS modules
- Webpack: bundler for AMD, CommonJS, ES6 modules