현대 웹 개발에서, 사용자에게 웹 애플리케이션을 제공하기 위한 파일 묶음
사용자가 브라우저를 열고 주소를 입력하면 해당 주소에서 프론트엔드 개발자가 번들링한 여러 파일을 받는다.
이 파일을 브라우저가 실행해서 웹 애플리케이션을 사용자에게 제공하게 된다.
⇒ 여러 제품이나 코드 프로그램을 묶어서 패키지로 제공하는 행위
HTML, CSS, JavaScript 파일을 그대로 전송하는 것은 무슨 문제가 있을까?
번들링 작업에서는 필연적으로 용량을 줄이고 파일을 통일하는 툴링작업
이 필요하게 된다.
⇒ 소프트웨어를 잘 만들어도 사용자에게 배포하기 위해 번들링이 꼭 필요하다
웹팩은 프론트엔드 애플리케이션 배포를 위해 가장 많이 사용하는 번들러(프론트엔드 애플리케이션을 대규모 유저에게 제공하기 위해 가장 많이 사용하는 방법)
⇒ 개발자 경험(DX) 개선에도 기여하고, 사용자 경험(UX) 개선에도 기여한다.
⇒ 코드 관리 용이 / 렌더 금방!
여러개의 파일을 하나의 파일로 합쳐주는 모듈 번들러
모듈 번들러랑 HTML, CSS, JavaScript 등의 자원을 전부 각각의 모듈로 보고 이를 조합해 하나의 묶음으로 번들링(빌드)하는 도구
모던 웹으로 발전하면서 JS 코드의 양이 많아졌고, 대규모 의존성 트리를 가지고 있는 대형 웹 애플리케이션이 등장해 세분화된 모듈 파일이 증가했다.
이 모듈 단위의 파일들을 호출 해 브라우저에 띄워야 하는데,, JS 언어의 특성에 따라 발생하기 쉬운 각 변수들의 스코프 문제를 해결해야하고, 각 자원을 호출할 때 생겨나는 네트워크 코스트도 신경써줘야만 했다.
⇒ 이런 복잡성에 대응하기 위해 하나의 시작점(ex. React App의 index.js등) 으로부터 의존성을 가지는 모듈을 모두 추적해 하나의 결과물을 만들어내는 모듈 번들러가 등장
JS 뿐 아니라 HTML, CSS, 이미지 파일들도 포함한 포괄적인 개념
따라서 Webpack은 주요 구성 요소인 로더(loader)를 통해 다양한 파일도 번들링이 가능하다.
빌드
: 개발이 완료된 앱을 배포하기 위해 하나의 폴더 로 구성하여 준비하는 작업
⇒ 예) React앱 기준 npm run build
실행하면 React build 작업이 진행되고, index.html
파일에 압축되어 배포에 최적화된 상태를 제공해준다.
번들링
: 묶음의 개념, 파일을 묶는 작업 그자체를 말하는데 모듈간의 의존성 관계를 파악해 그룹화 하는 작업
⇒ 파일은 의존적 관계에 있는 파일들(import, export) 자체 혹은 내부적으로 포함되어 있는 모듈을 의미
웹 애플리케이션의 빠른 로딩 속도와 높은 성능을 위함!!
코드의 양이 많은 것을 무겁다
고 표현하는데, 무거울수록 로딩 속도와 성능은 저하된다.(일반 유저는 3초 이내에 페이지가 뜨지 않으면 이탈을 선택)
⇒ 로딩 속도를 개선하기 위한 많은 노력이 필요했는데 대표적으로 브라우저에서 서버로 요청하는 파일의 숫자를 줄이는 것이 있다.
Webpack(웹팩) 이 없다면 각각 알아서 서버에 요청해 얻어와야 했지만,
Webpack(웹팩) 이 있다면 같은 타입의 파일들은 묶어서 요청 및 응답을 받을 수 있기 때문에 네트워크 코스트가 많이 줄어든다.
Webpack4 버전 이상부터는 Development
, Production
두가지의 모드를 지원한다.
Production
모드로 번들링할 경우, 코드 난독화, 압축, 최적화 작업을 지원한다.
⇒ 상용화 된 프로그램을 사용자에게 더 쾌적한 환경 및 보안까지 신경쓰면서 노출시킬 수 있다.
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(),
]
}
};
Webpack 은 다양한 환경과 target을 컴파일한다. (기본값은 web
)
web
외에도 다양한 환경을 컴파일 할 수 있는데, esX
를 넣으면 지정된 ECMAScript 버전으로 컴파일 할 수 있다.
module.exports = {
target: ["web", "es5"],
}
⇒ 이 config 파일은 브라우저와 동일한 환경에서 사용하기 위해 컴파일할 것이며,
작성된 코드를 es5버전으로 컴파일 하겠다고 지정한 것. (Browser Compatibility와 연관된 속성)
시작점
React 도 index.js에서 HTML 엘리먼트 하나에 React 코드를 적용하는 것 부터 시작한다.( 실제 webpack을 사용하기도 했음)
Entry 속성은 Entry point 라고도 하고, webpack이 내부의 디펜던시 그래프를 생성하기 위해 사용해야 하는 모듈이다.
webpack은 Entry point로 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾아낼 수 있다.
// 기본값
module.exports = {
...
entry: "./src/index.js",
}
// 지정값
module.exports = {
...
entry: "./src/script.js",
}
⇒ 기본값은 ./src/index.js 이지만 webpack 설정에서 이런식으로 Entry 속성을 설정해 다른 또는 여러 entry point 를 지정할 수 있다.
생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 방법을 webpack 에게 알려주는 역할
const path = require('path')
module.export = {
...
output: {
path: path.resolve(__dirname, "docs"), // 절대 경로로 설정 해야 한다.
filename: "app.bundle.js",
clean: true
},
};
기본 출력 파일의 경우에는 ./dist/main.js 로, 생성된 기타 파일의 경우에는 ./dist 폴더로 설정된다.
output.filename
: webpack 에 번들의 이름을 알려준다.
output.path
: webpack 에 내보낼 위치를 알려준다. path 속성을 사용할 때는 path 모듈을 사용해야만 한다.
Webpack은 기본적으로 JavaScript와 JSON파일만 이해한다.
하지만 loader 를 사용하면 Webpack 이 다른 유형의 파일을 처리하거나, 그들을 유효한 모듈로 변환해 애플리케이션에 사용하거나 디펜던시 그래프에 추가할 수 있다.
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
exclude: /node_modules/,
},
],
},
};
test
(필수속성) : 변환이 필요한 파일들을 식별하기 위한 속성use
(필수속성) : 변환을 수행하는데 사용되는 로더를 가리키는 속성exclude
: 바벨로 컴파일하지 않을 파일이나 폴더를 지정이런 속성을 넣어 규칙을 정하기 위해선 module.rules
아래에 정의해야 한다.
그냥 rules
에 정의하면 webpack 은 경고를 함
번들을 최적화하거나 에셋을 관리하고 환경변수 주입 등의 광범위한 작업을 수행할 수 있게 된다.
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(),
]
}
⇒ 위 예제에서 html-webpack-plugin
은 생성된 모든 번들을 자동으로 삽입하여 애플리케이션용 HTML 파일을 생성해준다.
mini-css-extract-plugin
은 CSS를 별도의 파일로 추출해 CSS 를 포함하는 JS 파일당 CSS 파일을 작성해주게끔 지원한다.
require()
를 통해 플러그인을 먼저 요청해야한다.new
연산자로 호출해 플러그인의 인스턴스를 만들어줘야 한다.webpack 버전 4부터 선택한 항목에 따라 최적화를 실행한다.
module.exports = {
...
optimization: {
minimizer: [
new CssMinimizerPlugin(),
//MiniCssExtractPlugin????
]
}
};
최적화하기 위해 다양한 옵션이 지원되는데, 대표적으로 minimize
minimizer
등을 사용한다.
minimize
: TerserPlugin
또는 optimization.minimize
에 명시된 plugins로 bundle 파일을 최소화(=압축) 시키는 작업 여부를 결정minimizer
: defualt minimizer
을 커스텀된 TerserPlugin
인스턴스를 제공해 재정의할 수 있다.⇒ 위 예제는 mini-css-extract-plugin
에 관련된 번들을 최소화하도록 지시하고 있다.
npm i
또는 npm init -y
npm install -D webpack webpack-cli
우선 src 폴더를 만들고 그 안에 index.js
파일을 만든다.
매개변수를 console.log
하는 간단한 함수를 만들고, underbar.js 라는 파일도 만들어서
그 안에 once 를 구현해본다.(webpack 작동원리 파악을 위한 예시)
const path = require('path')
를 상단에 꼮!!! 입력해주고
module.exports={}
안에 entry
와 output
을 입력해준다.
👊 시행착오
처음에 webpack.config.js
파일을 src 폴더 안에 만들었는데, 번들링을 하면
계속 dist 폴더 안에 내가 설정한 filename에 app.bundle.js
가 안 생기고 main.js
가 생겼다.
⇒ 왜냐면 entry 위치를 잘못해줬으니까.. index.js
와 webpack.config.js
가 같은 파일안에 있으니까
./src/index.js
라고 하면 안됐따!!! webpack.config.js 파일은 꼭 src 폴더 밖에 두도록 하자
CLI 에 npx webpack
으로 번들링하기
번들링이 잘 됐다면 이전에 node src/index.js
로 나온 출력 결과물과 node dist/app.bundle.js
가 같아야한다. 만약 잘 나왔다면 성공
추후에 다른 개발자와 협업할 때, 지금까지의 여정을 간단하게 대신할 수 있는 스크립트를 만드는 것
CLI에 npm run build
를 입력했을 때 바로 npx webpack
이 실행될 수 있게
package.json
에 "script"
안에 "build":"webpack",
을 추가한다.
그러면 npm run build
이걸로 번들링을 할 수 있다.
src 폴더 안에 index.html 만들고, <body>
안에 <script src="index.js"></script>
추가하고 확인하면 에러가 나옴.
⇒ 그럼 이 파일은 dist
폴더로 옮겨서 번들 파일과 연결 시킨 후에 script src 를 app.bundle.js
로 바꾸기
index.js
코드를 바꿨다면 npm run build
로 번들링을 진행하고 dist/index.html
을 열면 바뀐 확인 가능
index.html
을 꾸며줄 index.css
를 dist 파일 안에 만든 후
index.html
<title>
위에 <link rel="stylesheet" href="style.css">
추가하면
CSS가 적용된 index.html
을 확인할 수 있다.
webpack 은 JS와 CSS를 함께 배포해야할 때 더 쉽게 배포할 수 있게 loader
를 제공!
dist/index.css
를 src 로 옮기고, 해당 파일을 src/index.js
에서 require('./style.css');
로 불러오면
node src/index.js
명령어로 확인했을 때 CSS를 읽을 수 없어서 문법 에러가 발생한다.
npm run build
를 해도 오류가 설정
이 에러 없애고 webpack에서 css 를 제대로 불러오게하기 위해
로더 설치하고 불러온다!
CLI 에 npm i -D css-loader style-loader
로 설치하고
webpack.config.js
에 module.exports ={}
안의 output
아래에 module:{rules:[]}
의 배열 안에 test
, use
, exclude
추가한다.
test: \/.css$/
: .css 인 파일들을 변환하겠다.use: ['style-loader', 'css-loader']
: style-loader , css-loader 를 사용해서css-loader
가 끝에 있어야 함exclude: /node_modules/
: 근데 node_modules 라는게 들어간 애들은 컴파일하지 않을거야npm run build
명령어로 번들링이 잘 됐는지 확인하고(경고 있어도 에러 없으면 성공)
dist/index.html
파일 라이브서버로 열면 CSS 가 잘 적용된 걸 볼 수 있고
<link rel="stylesheet" href="style.css">
이 코드는 필요없다.
dist/index.html
을 다시 src 폴더 안으로 옮기고!CLI 에 npm i -D html-webpack-plugin
로 플러그인 설치하기
webpack.config.js
파일 제일 상단에 있는 path
밑에
const HtmlWebpackPlugin = require('html-webpack-plugin')
추가하기(변수명은 뭐든 상관 없음!)
그리고 module.exports={}
안에 module:{}
밑에 plugins:[]
안에 new HtmlWebpackPlugin({template: path.resolve(__dirname, "src", "index.html")})
추가하기
⇒ src 폴더 안에 index.html
파일 선택
CLI에 npm run build
입력하면, dist 폴더 안에 index.html
이 생성된다.
⇒ CSS는 app.bundle.js 파일에 넣어주고(CSS loader로), JS는 html-webpack-plugin
이 자동으로
dist/index.html
파일 안에 <script defer="defer" src="app.bundle.js"></script>
를 추가해준다.