들어가기전...
- 웹을 개발하다보면 다양한 확장자의 파일을 만들게 된다.
이렇게 다양한 소스는 웹 어플리케이션을 무겁게 만든다.
통신이 있을 때마다 이 소스들을 로딩하는 작업은 고비용이다.
만약 많은 JS 패키지를 사용하다보면 예상하지 못한 충돌로 인해 어플리케이션이 깨지게 될 수도 있다(같은 이름을 변수를 사용하는 등).
이를 해결하기 위해 등장한 도구가 Bundler이다.
bundle은 묶는다는 뜻이다.
여러개의 파일을 묶어주는 어떠한 정리 방법이다.
구체적인 기술로는 WebPack, Broserify, Parcel이 있다.
여러 제품이나, 코드, 프로그램을 나누어서 패키지로 제공하는 행위를 의미한다.
- 프론트 엔드에서 번들이란?
사용자에게 웹 애플리케이션을 제공하기 위한 파일 묶음이다
위와 같은 이유를 위해
번들링 작업에서는 필연적으로 용량을 줄이고 파일을 통일하는 툴링 작업이 필요하다.
즉, 소프트웨어를 잘 만들어도 사용자에게 배포하기 위해 번들링이 꼭 필요하다.
여러 개의 파일을 하나의 파일로 합쳐주는 모듈 번들러이다.
- 모듈 번들러란 HTML, CSS, JavaScript 등의 자원을 전부 각각의 모듈로 보고 이를 조합해 하나의 묶음으로 번들링(빌드)하는 도구이다
- Webpack에서의 모듈은 JavaScript 모듈과 HTML, CSS, 혹은 .jpg나 .png 같은 이미지 파일들도 전부 포함한 포괄적인 개념이다.
- 성능을 향상시키기 위해 필요하다면 다시 분리할 수도 있다.
- Webpack은 현재 프론트엔드 애플리케이션 배포를 위해서 가장 많이 사용하는 번들러이며 다양한 다른 번들러 들도 있다.
(WebPack을 둘러싼 방대한 생태계 덕분에 다양한 확장 기능 등이 있기 떄문에 많은 작업들을 자동화 하기 편하다.)
- 빌드는 개발이 완료된 앱을 배포하기 위해 하나의 폴더(directory)로 구성하여 준비하는 작업이다
- React 앱 같은 경우
npm run build
커맨드를 통해 React build 작업이 진행되고, index.html 파일에 압축되어 배포에 최적화된 상태를 제공한다.빌드와 번들링의 차이
먼저 빌드과정에 번들링은 포함된다. (빌드 > 번들링)
- 빌드 : 개발자가 작성한 코드를 웹서버(인터넷)에 실행 가능한 형태로 제공한다.
- 번들링 : 단순히 여러개의 소스 코드를 1개의 파일로 결합하는 과정
웹 애플리케이션의 빠른 로딩 속도와 높은 성능을 위해서다.
- Webpack이 없다면 각 자원들을 일일히 서버에 요청해 얻어와야 하지만, Webpack이 있다면 같은 타입의 파일들은 묶어서 요청 및 응답을 받을 수 있기 때문에 네트워크 비용이 획기적으로 줄어든다.
- Webpack loader를 사용하면 일부 브라우저에서 지원하지 않는 JavaScript ES6의 문법들을 ES5로 번환해주는 babel-loader를 사용할 수 있다.
Vue인 경우는 vue-loader를, scss 파일 같은 경우는 css 파일로 변환해주는 scss-loader 등의 loader도 사용할 수 있기 때문에 개발자는 본인이 원하는 최선의 개발 방식을 선택해 개발할 수도와준다.- ebpack4 버전 이상부터는 Develoment, Production 두 가지의 모드를 지원하고 여기서 Production 모드로 번들링을 진행할 경우, 코드 난독화, 압축, 최적화(Tree Shaking) 작업을 지원해준다.
웹팩 공식문서에서는 핵심 개념을 제안하고 있다.
웹팩 공식 홈페이지의 컨셉
참고로 babel은 웹팩에서 사용되는 로더 중 하나로 ES6 문법으로 작성된 코드를 ES5 문법으로 변환시켜준다(트랜스 파일러임).
즉 이를 통해 구형브라우저에서도 동작할 수 있도록 코드를 바꿔주는 로더다. (CRA로 리액트앱생성시 자동설치된다.)
npm i -D bable-loader @babel/core @babel/preset-env @babel/preset-react
- babel-core : 바벨을 이용해 코드를 변환하는데 필요한 기능을 제공(트랜스 파일러 역할을 함)
- @babel/preset-env : 언어를 변환시 특정한 변환 규칙들이 있는 것을 모은것...
그래서 아래와 같이 웹팩의 config 파일의 설정이 필요하다.
- Entry
- Output
- Loaders
- Plugins
- Mode
- Browser Compatibility
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(),
]
}
};
target
: 코드가 실행될 플랫폼을 지정,entry
: 응용 프로그램의 진입점을 지정,src/script.js
파일output
: 빌드된 파일의 출력 경로와 파일 이름을 정의,app.bundle.js
파일을 docs
폴더에 생성clean
옵션은 이전에 빌드된 파일을 자동으로 삭제module
: 사용자 지정 모듈을 정의,.css
확장자를 갖는 파일에 대해 css-loader
및 MiniCssExtractPlugin.loader
를 사용plugins
: 추가적인 기능을 제공하는 플러그인을 설정,HtmlWebpackPlugin
과 MiniCssExtractPlugin
을 사용. HtmlWebpackPlugin
은 HTML 파일을 빌드된 JS 파일에 링크하는 index.html
템플릿 파일을 생성. MiniCssExtractPlugin
은 CSS 파일을 별도의 파일로 추출optimization
: 웹팩이 최적화할 옵션을 설정, 이 경우 CssMinimizerPlugin
을 사용하여 CSS 파일을 압축module.exports = {
mode: 'development',
};
mode 옵션을 사용하면 webpack에 내장된 최적화 기능을 사용할 수 있다.
기본값은 production
이다
development
: DefinePlugin의 process.env.NODE_ENV를 development로 설정한다.production
: DefinePlugin의 process.env.NODE_ENV를 production으로 설정한다. (배포를 위함, 가장 코드가 압축됨)none
: 기본 최적화 옵션에서 제외module.exports = {
target: ["web", "es5"],
Webpack은 다양한 환경과 target을 컴파일한다
target의 기본값은 web이다.
만약 esX를 넣으면 지정된 ECMAScript 버전으로 컴파일할 수 있다.
//기본 값
module.exports = {
...
entry: "./src/index.js",
};
//지정 값
module.exports = {
...
entry: "./src/script.js",
};
프론트엔드 개발자가 작성한 코드의 “시작점"이다.
기본 값은 ./src/index.js
React도 index.js에서 HTML 엘리먼트 하나에 React 코드를 적용하는 것 부터 시작한다.
webpack이 내부의 디펜던시 그래프를 생성하기 위해 사용해야 하는 모듈이다.
Webpack은 이 Entry point를 기반으로 직간접적으로 의존하는 다른 모듈과 라이브러리를 찾아낼 수 있다.
const path = require('path');
module.exports = {
...
output: {
path: path.resolve(__dirname, "docs"), // 절대 경로로 설정을 해야 합니다.
filename: "app.bundle.js",
clean: true
},
};
Output 속성은 생성된 번들을 내보낼 위치와 이 파일의 이름을 지정하는 방법을 webpack에 알려준다.
기본 출력 파일의 경우에는 ./dist/main.js로 ,
생성된 기타 파일의 경우에는 ./dist 폴더로 설정된다.
위의 예제에서 output.filename
과 output.path
속성을 사용하여 webpack에 번들의 이름과 내보낼 위치를 나타냈으며
path
속성을 사용할 때는 path 모듈을 사용해야만 합니다.
output.clean:true
이므로 번들링 할 때 마다 output 디렉토리의 이전 파일이 삭제된다.
filename:'[name].[hash].js'
와 같이 작성한다면
output이 동적으로 변해 파일이름이 달라진다.
[name]
의 기본은 main이 된다.
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"], //style-loader 대신 CSS minify를 위한 로더를 쓰자
exclude: /node_modules/,
},
],
},
};
npm i -D css-loader style-loader
로 설치 후 사용가능
Webpack은 기본적으로 JavaScript와 JSON 파일만 이해하지만 loader를 사용하면 Webpack이 다른 유형의 파일을 처리하거나, 그들을 유효한 모듈로 변환해 애플리케이션에 사용하거나 디펜던시 그래프에 추가할 수 있다.
즉, loader는 JavaScript, JSON이 아닌 파일을 불러오는 역할을 한다.
상위 수준에서 loader는 webpack 설정에 몇 가지 속성을 가진다.
test
(필수): 변환이 필요한 파일들을 식별하기 위한 속성use
(필수): 변환을 수행하는데 사용되는 로더를 가리키는 속성exclude
: 바벨로 컴파일하지 않을 파일이나 폴더를 지정. (반대로 include
속성을 이용해 반드시 컴파일해야 할 파일이나 폴더 지정 가능)이런 속성을 넣어 규칙을 정하기 위해서는 module.rules
아래에 정의해야 한다 그냥 rules
아래에 정의하면 webpack은 경고날림
Plugins를 사용하면 번들을 최적화하거나 에셋을 관리하고, 또는 환경변수 주입 등의 광범위한 작업 수행
npm i -D html-webpack-plugin
로 설치후 require()
로 불러와야 사용가능 (로더랑 달리 require 필요)
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 파일을 작성해주도록 지원한다.
Webpack은 버전 4부터는 선택한 항목에 따라 최적화를 실행
module.exports = {
...
optimization: {
minimizer: [
new CssMinimizerPlugin(),
]
}
};
최적화하기 위해 다양한 옵션이 지원이 되는데, 대표적으로 minimize
와 minimizer
등을 사용한다.
TerserPlugin
또는 optimization.minimize
에 명시된 plugins로 bundle 파일을 최소화(=압축)시키는 작업 여부를 결정defualt minimizer
을 커스텀된 TerserPlugin
인스턴스를 제공해서 재정의mini-css-extract-plugin
에 관련된 번들을 최소화하도록 한다.npm i --save-dev webpack-dev-server
로 설치후
//webpack.config.js
entry:....,
devServer:{ //추가
static:'./docs' //npm script 등 했을 때 개발 서버를 띄워주며 최적화가 필요함
},
...
optimization:{
minimizer:[
new CsMinimizerPlugin()
],
runtimeChunk:'single' // 최적화 추가
}
위와 같이 웹팩 config파일을 작성후
package.json 의 script에
"dev-server":"webpack serve --open"
작성하면
$ npm run dev-server
로 내 로컬 서버에서 열 수 있게 된다.
npm i react-scripts
를 통해 설치 후
package.json 의 script에
"start":"react-scripts start"
작성하면
$ npm run start
가능하며 추가적인 submit 등과 같은 것도 할 수 있다..