
웹팩(Webpack 또는 webpack)은 오픈 소스 자바스크립트(JS) 모듈 번들러이다. 웹팩은 의존성이 있는 모듈을 취하여 해당 모듈을 대표하는 정적 자산들을 생성한다.
예시코드
// math.js
function sum(a, b) {
return a + b;
}
// app.js
console.log(sum(1, 2));
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script src="src/math.js"></script>
<script src="src/app.js"></script>
</body>
</html>
var math = math || {};
(function () {
function sum(a, b) {
return a + b;
}
math.sum = sum;
})();
// math.sum(a,b)으로 접근가능
CommonJS(http://www.commonjs.org/) 는 JavaScript를 브라우저에서뿐만 아니라, 서버사이드 애플리케이션이나 데스크톱 애플리케이션에서도 사용하려고 조직한 자발적 워킹 그룹이다. 이 그룹은 JavaScript를 범용적으로 사용하기 위해 필요한 '명세(Specification)'를 만드는 일을 한다.
자바스크립트가 브라우저용 언어를 범어 범용적으로 쓰이려면 모듈화가 필요했고, CommonJS의 주요 명세는 이 모듈을 어떻게 정의하고, 어떻게 사용할 것인가에 대한 것이다.
// math.js
exports function sum(a,b){
return a+b;
}
// app.js
const sum = require('./math.js');
console.log(sum(1, 2));
또 다른 Javascript 표준 API 라이브러리 제작 그룹이다. 비동기 상황에서도 Javascript 모듈을 쓰기 위해 CommonJS에서 함께 논의하다 합의점을 이루지 못하고 독립했다. AMD의 목표는 필요한 모듈을 네트워크를 이용해 내려받아야 하는 브라우저 환경에서도 모듈을 사용할 수 있도록 표준을 만드는 일이다. CommonJS와 같이 require() 함수를 사용할 수 있고, exprts 형태로 모듈을 정의한다. AMD만의 특징인 define() 함수는 파일 스코프의 역할을 한다. 브라우저 환경의 javascript는 파일 스코프가 따로 존재하지 않기 때문에, 이 함수가 일종의 네임스페이스 역할을 해 모듈에서 사용하는 변수와 전역변수를 분리한다.
// math.js
export function sum(a,b){
return a+b;
}
// app.js
import * as math from './math.js';
console.log(math.sum(1, 2));
그러나 모듈 시스템을 지원하지 않는 브라우저가 있다. 브라우저에 무관하게 모듈을 사용하고 싶을 때!! 웹팩을 사용함!!!!

웹팩설치
$ npm install -D webpack webpack-cli

아래의 명령어로 번들링하면 gist/main.js에 번들링 된 파일이 생김


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script src="dist/main.js"></script>
</body>
</html>
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/app.js' // 아웃풋 이름을 동적으로 생성할 수 있음
},
output: {
path: path.resolve('./dist'),
filename: '[name].js'
}
};
npm run build
웹팩은 모든 파일을 모듈로 바라본다. 자바스크립트로 만든 모듈 뿐만 아니라 스타일시트, 이미지, 폰트까지도 전부 모듈로 보기 때문에 imort 구문을 사용하면 자바스크립트 코드 안으로 가져올 수 있다.
이것이 가능한 이유는 웹팩의 로더 덕분이다. 로더는 타입스크립트 같은 다른 언어를 자바스크립트 문법으로 변환해 주거나 이미지를 data URL 형식의 문자열로 변환한다. 뿐만 아니라 CSS 파일을 자바스크립트에서 직접 로딩할 수 있도록 해준다.
my-webpack-loader.js
// my-webpack-loader.js
module.exports = function myebpackLoader(content) {
console.log('myWebpackLoader가 동작함');
return content;
};
webpack.config.js

module 객체에 rules의 배열에 들어감test는 로더가 처리해야할 파일의 패턴 - 정규표현식을 사용한다. 위 예제의 경우 모든 자바스크립트 파일마다 로더가 실행됨use는 패턴에 걸리면 실행될 로더 함수들을 명시. 배열 뒤에 순서부터 실행됨$ npm install css-loader style-loader 설치
$ npm install file-loader 설치

사용하는 이미지 갯수가 많다면 네트웍 리소스를 사용하는 부담이 있고 사이트 성능에 영향을 줄 수도 있다. 만약 한 페이지에서 작은 이미지를 여러개 사용한다면 Data URI Scheme(작은 파일을 Base64로 인코딩하여 문자열 형태로 소스코드에 넣는 형식)를 이용하는 방법이 더 낫다. url-loader는 이런 처리를 자동화해준다.
$ npm install -D url-loader

로더가 파일 단위로 처리하는 반면 플러그인은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화 한다거나 특정 텍스트를 추출하는 용도로 사용한다.
compliation이라는 객체를 이용해 웹팩이 번들링한 결과물에 접근할 수 있다.my-webpack-plugin.js
class MyPlugin {
apply(compiler) {
compiler.hooks.done.tap('My Plugin', (stats) => {
console.log('MyPlugin: done');
});
compiler.plugin("emit", (compilation, callback) => {
// 웹팩 내장 플러그인 중 하나인 banner plugin - compilation 객체를 parameter로 갖는다
const source = compilation.assets["main.js"].source()
console.log(source)
callback()
})
}
}
module.exports = MyPlugin;
webpack.config.js

const webpack = require('webpack');
const childProcess = require('child_process');
...
plugins: [
new webpack.BannerPlugin({
banner: `
Build Date:${new Date().toLocaleDateString()}
Commit Version:${childProcess.execSync('git rev-parse --short HEAD')}
Author:${childProcess.execSync('git config user.name')}
`
})
]
웹팩 설정의 mode에 설정한 값이 process.env.NODEENV(노드 환경 정보)가 들어간다. "development"를 설정했을 경우 어플리케이션 코드에서 process.env.NODEENV 변수로 접근하면 "development" 값을 얻을 수 있다.webpack.config.js
const webpack = require('webpack');
...
plugins: [
new webpack.DefinePlugin()
]
$ npm install -D html-webpack-plugin
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
templateParameters: {
env: process.env.NODE_ENV === 'development' ? '(개발용)' : ''
},
minify:
process.env.NODE_ENV === 'production'
? {
collapseWhitespace: true, // 빈칸 없애기
removeComments: true // 주석제거
}
: false
})
]
$ npm install clean-webpack-plugin
webpack.config.js
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
...
plugins: [
new CleanWebpackPlugin()
]
$ npm install mini-css-extract-plugin
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
...
module: {
rules: [
{
test: /\.css$/,
use: [
process.env.NODE_ENV === 'productoin'
? MiniCssExtractPlugin.loader
: 'style-loader',
'css-loader'
]
},
]
},
plugins: [
...(process.env.NODE_ENV === 'production'
? [
new MiniCssExtractPlugin({
filename: '[name].css'
})
]
: [])
]
📑 reference