Webpack
번들링
- 여러 제품이나, 코드, 프로그램을 묶어서 패키지로 제공하는 행위
- 프론트엔드 개발자에게 번들은 '사용자에게 웹 애플리케이션을 제공하기 위한 파일 묶음'
- 사용자가 브라우저를 열고 주소를 입력하면 → 해당 주소에서 프론트엔드 개발자가 번들링한 여러 파일을 받음
Webpack
- 현재 프론트엔드 애플리케이션 배포를 위해 가장 많이 사용하는 번들러
- 여러 개의 파일을 하나로 합쳐주는 모듈 번들러
* 모듈 번들러(Module Bundler)란?
- HTML, CSS, JavaScirpt 등의 자원을 전부 각각의 모듈로 보고 이를 조합해 하나의 묶음으로 번들링(빌드)하는 도구
모듈 번들러의 등장
- 자바스트립트 코드의 양, 세분화 된 모듈의 양 증가 → 이 파일들을 호출해 브라우저에 띄워야 함
- 이 때 발생하는 변수들의 스코프 문제, 자원을 호출 할 때 생겨나는 네트워크 쪽 코스트 해결 문제 발생
- 이런 복잡성에 대응하기 위해 하나의 시작점(ex. React App의 index.js 등)으로 부터 의존성을 가지는 모듈을 모두 추적하여 하나의 결과물을 만들어 내는 모듈 번들러가 등장
Webpack에서의 모듈
- Webpack에서의 모듈은 자바스크립트에서의 모듈에만 국한되지 않고 HTML, CSS, 이미지 파일도 모듈 포함한 포괄적인 개념
- 따라서 Webpack은 주요 구성 요소인 로더(loader)를 통해 다양한 파일도 번들링이 가능함
빌드와 번들링
* 빌드
: 개발이 완료된 앱을 배포하기 위해 하나의 폴더(directory)로 구성하여 준비하는 작업
- ex. React 앱을 기준으로 npm run build를 실행하면 React build 작업이 진행되고→index.html 파일에 압축되어 배포에 최적화 된 상태를 제공해줌
* 번들링
: 파일을 묶는 작업 그 자체를 말함
- 파일은 의존적 관계에 있는 파일들(import, export) 그 자체 혹은 내부적으로 포함되어 있는 모듈을 의미
- 모듈 간의 의존성 관계를 파악해 그룹화 하는 작업
Webpack의 필요성
- 코드의 양이 무거워질수록 웹 페이지의 로딩 속도와 성능이 저하됨→속도 개선을 위해 브라우저에서 서버로 요청하는 파일의 숫자를 줄이고자 함
- 웹 팩이 없다면 각 자원을 일일이 서버에 요청해 얻어와야 하지만 웹 팩이 있다면 같은 타입의 파일들은 묶어서 요청 및 응답을 받을 수 있기 때문에 네트워크 코스트가 줄음
- 웹 팩 로더를 사용하면 일부 브라우저에서 지원하지 않는 자바스크립트 ES6 문법들을 ES5로 변환해주는 babel-loader를 사용할 수 있게 됨
- 다양한 로더들을 사용해서 개발자가 원하는 최선의 개발 방식의 선택의 폭이 넓어짐
Webpack의 핵심 개념
1. Target
2. Entry
3. Output
4. Loader
5.Plugins
6. Optimization
1. Target
- 웹 팩은 다양한 환경과 target을 컴파일함
- Target의 기본값은 web임. 적용하지 않으면 이 기본 값으로 적용
- 이 외에도 다양하게 컴파일 할 수 있음 . esX를 넣으면 지정된 ECMAScirpt 버전으로 컴파일 할 수 있음
module.exports = {
target: ["web", "es5"],
};
- 예시의 config 파일에서는 es5를 배열 안에 둠 → 이 파일은 브라우저와 동일한 환경에서 사용하기 위하여 컴파일할 것이며, 작성된 코드를 es5 버전으로 컴파일하겠다고 지정
- 브라우저 호환성과 연관된 속성
2. Entry(엔트리)
- 개발자가 작성한 코드의 '시작점'
- Entry 속성은 Entry point라고도 하며 웹 팩 내부의 디펜던시 그래프를 생성하기 위해 사용해야 하는 모듈
- 웹 팩은 이 Entry point를 기반으로 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾아낼 수 있음
//기본 값
module.exports = {
...
entry: "./src/index.js",
};
//지정 값
module.exports = {
...
entry: "./src/script.js",
};
- 기본값은 ./src/index.js 이지만 webpack 설정에서 지정값을 넣을 수 있음
3. Output(출력)
- 생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 방법을 웹 팩에 알려주는 역할
const path = require('path');
module.exports = {
...
output: {
path: path.resolve(__dirname, "docs"), // 절대 경로로 설정을 해야 합니다.
filename: "app.bundle.js",
clean: true
},
};
- 기본 출력 파일의 경우에는 ./dist/main.js로, 생성된 기타 파일의 경우에는 ./dist 폴더로 설정
- 위의 예제에서는 output.filename과 output.path 속성을 사용하여 웹팩 번들의 이름과 내보낼 위치를 알려주고 있음
- path 속성을 사용할 때는 path 모듈을 사용해야만 함
4. Loader(로더)
- 웹팩은 기본적으로 자바스크립트와 JSON 파일만 이해함
- 그러나 로더를 사용하면 웹팩의 다른 유형의 파일을 처리하거나, 그들을 유효한 모듈로 변환해 애플리케이션에 이용하거나 디펜던시 그래프를 추가할 수 있음
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
exclude: /node_modules/,
},
],
},
};
상위 수준에서 loader는 웹팩 설정에 몇 가지 속성을 가짐 (test, use는 필수 속성, 이 속성을 넣어 규칙을 정하기 위해서는 module.rules 아래에서 정의해야 함!)
- test : 변환이 필요한 파일들을 식별하기 위한 속성
- use : 변환을 수행하는데 사용되는 로더를 가리키는 속성
- exclude : 바벨로 컴파일하지 않을 파일이나 폴더를 지정 (반대로 include 속성을 이용해 반드시 컴파일해야 할 파일이나 폴더 지정)
5. Plugins(플러그인)
- 번들을 최적화하거나 에엣을 관리하고, 또는 환경 변수 주입 등의 광범위한 작업을 수행할 수 있게 됨
const webpack = require('webpack');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
...
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
new MiniCssExtractPlugin(),
],
};
- 플러그인을 사용하기 위해서는 require를 통해 요청해야 함
- 그리고 plugins 배열에 사용하고자 하는 플러그인 추가, 대부분의 플러그인은 사용자가 옵션을 통해 지정할 수 있음
- 다른 목적으로 플럭그인을 여러 번 사용하도록 설정할 수 있기 때문에 new 연산자를 사용해 호출하여 플러그인의 인스턴스를 만들어 줘야 함
- 위의 예제에서 html-webpack-plugin은 생성된 모든 번들을 자동으로 삽입하여 애플리케이션용 HTML 파일을 생성해 줌
- mini-css-extract-plugin은 CSS를 별도의 파일로 추출해 CSS를 포함하는 JS 파일 당 CSS 파일을 작성해 주게끔 지원
6. Opimization(최적화)
- 웹팩은 버전 4부터는 선택한 항목에 따라 최적화를 실행
- 아래의 예제는 mini-css-extract-plugin 에 관련된 번들을 최소화하도록 지시
module.exports = {
...
optimization: {
minimizer: [
new CssMinimizerPlugin(),
]
}
};
최적화하기 위해 다양한 옵션이 지원
- minimize : TerserPlugin 또는 optimization.minimize 에 명시된 plugins로 번들 파일을 최소화(=압축) 시키는 작업 여부를 결정
- minimizer : defualt minimizer을 커스텀 된 TerserPlugin 인스턴스를 제공해서 재정의 할 수 있음
위의 예시를 모두 모으면 이런 config 파일 탄생
module.exports = {
target: ["web", "es5"],
entry: "./src/script.js",
output: {
path: path.resolve(__dirname, "docs"),
filename: "app.bundle.js",
clean: true
},
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
exclude: /node_modules/,
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html"),
}),
new MiniCssExtractPlugin(),
],
optimization: {
minimizer: [
new CssMinimizerPlugin(),
]
}
};