자바스크립트 모듈 번들러
- 웹 애플리케이션 제작 시 여러가지 구성자원(HTML, CSS ,JS)를 각각의 모듈로 조합해서 하나 혹은 몇개의 파일로 변환해주는 도구
- 의존 모듈이 하나의 파일로 번들링되므로 별도의 모듈 로더가 필요없음
- 자바스크립트 코드가 많아지면 하나의 파일로 관리하는데 한계가 존재,그렇다고 여러개 파일을 브라우져에서 로딩하는 것은 그만큼 통신 비용을 치뤄야하는 단점이 있다. 뿐만 아니라 각 파일은 서로의 스코프를 침범하지 않아야 하는데 잘못 작성할 경우 변수 충돌의 위험성도 있다
=> 위의 처럼 통신 비용 및 변수 충돌 위험성을 해결 가능
npm install --save-dev @babel/core babel-loader @babel/preset-react @babel/preset-env babel-eslint
--save-dev : 개발환경에서만 사용되는 라이브러리라는 것을 명시
npm install --save-dev webpack webpack-dev-server webpack-cli html-webpack-plugin
Webpack의 핵심 기능
- babel plugins에서는 번들로 babel preset이 함께 온다
- 사실 babel은 그 자체로는 아무것도 하지 않는다. 만약 preset과 - plugin을 추가하지 않는다면 babel은 아무것도 하지 않는다
- babel 자체로는 아무것도 안함(plugins이 사실상 compile 작업 역할)
- 매번 plugin 패키지 설치을 통하여 기존에 있던 수동적인 방식인 .babelrc에 추가하는 방법에서 plugin 패키지 설치를 통하여 좀 더 효율적으로 관리 가능
- preset으로 plugin 그룹 한번에 설치
- 공식 preset 사용 (@bable/core)
Preset에 대해
원래 동작은 css loader에 의해 css파일에서 css코드들을 부릅니다. 그리고 csso loader에 의해 최적화 작업과 text를 추출하는 plugin에 의해 style.css라는 파일에 원하는 css 코드를 담습니다
webpack 설정이 들어가면, text plugin에 의해 css 파일에서 css 코드를 추출하고 webpack 안의 csso plugin에 의해 중복되는 코드를 최적하여 style.css에 담음(webpack plugin이 좀더 밀도 있는 작업을 진행)
npm --save-dev install node-sass style-loader css-loader sass-loader
webpack.config.js 안에 modules에 추가
module: {
rules: [
{
test: /\.js$/,
exclude: /node_module/,
use: {
loader: "babel-loader",
},
},
{
test: /\.scss$/,
use: [
"style-loader",
"css-loader",
"sass-loader",
],
exclude: /node_modules/,
},
],
},
npm install --save-dev file-loader
webpack.config.js 안에 modules에 추가
module: {
rules: [
...
{
test: /\.(gif|png|jpe?g|svg)$/i,
exclude: /node_modules/,
use: [
'file-loader'
]
},
{
test: /\.(woff|woff2|eot|ttf|otf|)$/,
exclude: /node_modules/,
use: [
'file-loader'
]
}
]
},
const path = require('path') // core nodejs 모듈 중 하나, 파일 경로 설정할 때 사용
const HtmlWebpackPlugin = require('html-webpack-plugin') // index.html 파일을 dist 폴더에 index_bundle.js 파일과 함께 자동으로 생성, 우리는 그냥 시작만 하고싶지 귀찮게 index.html 파일까지 만들고 싶지 않다.!!
module.exports = { // moduel export (옛날 방식..)
entry: './src/index.js', // 리액트 파일이 시작하는 곳
// devserver 설정
devServer: {
hot: true,
// 부분 리로드(컴포넌트 일부수정 부분)
inline: true,
// 전체 페이지 리로드
// hot, inline, open 등 여기서 선언 했으면 아래 package.json에서 script부분에서 빼도 된다!!
port: 3000,
host: 'localhost',
},
output: { // bundled compiled 파일
path: path.join(__dirname, '/dist'), //__dirname : 현재 디렉토리, dist 폴더에 모든 컴파일된 하나의 번들파일을 넣을 예정
filename: 'index_bundle.js'
},
module: { // javascript 모듈을 생성할 규칙을 지정 (node_module을 제외한.js 파일을 babel-loader로 불러와 모듈을 생성
rules: [
{
test: /\.js$/, // .js, .jsx로 끝나는 babel이 컴파일하게 할 모든 파일
exclude: /node_module/, // node module 폴더는 babel 컴파일에서 제외
use:{
loader: 'babel-loader' // babel loader가 파이프를 통해 js 코드를 불러옴
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html' // 생성한 템플릿 파일
})
]
}
코드 설명
- path :파일의 경로를 지정
- __dirname : 노드 변수로 현재 모듈의 디렉토리를 리턴합니다.
- HtmlWebpackPlugin :컴파일 이후 index.html 파일을 생성
template에 지정된 index.html에 모든 static 파일들을 긁어모은 index_bundle.js 파일을<script src='index_bundle.js'></script>
형식으로 연결- module.export : 출력할 모듈
- entry : 컴파일 할 파일, index.js
- output : 컴파일 이후 파일, __dirname/dist/index_bundle.js
- module :모듈의 컴파일 형식
es6 문법을 es5으로 바꾸기 위해 webpack이 js, jsx를 포함한 모든 파일을 babel을 통하여 컴파일- plugin : 사용할 plugins
여기서는 htmlwebpackPlugin을 사용하여 index.html과 index_bundle.js에 연결해 줌- html-webpack-plugin
html-webpack-plugin은 script 태그안에 넣은 webpack 번들 파일과 함께 html5 파일을 생성
HTMLWebpackPlugin이 index.html의 script 태그안에 컴파일된 bundle 파일을 심어줌
new HtmlWebpackPlugin()을 위의 예시처럼 그냥 사용하는 것도 좋지만 이렇게 템플릿을 만들어 놓으면 커스터마이징 하기 편리
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
]
}
---
// 위의 코드가 dist/index.html파일을 생성
// index_bundle.js가 webpack에 의해 컴파일, 번들화된 하나의 js 파일
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
다음은 웹페이지의 가장 기본이 될 index.html 파일을 src/index.html 경로로 아래와 같이 생성
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My React App</title>
</head>
<body>
<div id="app"></div> // 템플릿
</body>
</html>
{
"presets": [
"@babel/env",
"@babel/react"
]
}
@babel이 버전이 업데이트 되면서 더이상 babel-core 형태(-)의 dependency를 지원하지 않게되므로서 @babel/env 형태(/)를 사용해야 합니다.
npm i --save-dev babel-plugin-module-resolver
플러그인을 설치한 뒤 babelrc에 추가
// babelrc
{
...,
"plugins": [
["module-resolver", {
"root": ["./src"],
"alias": {
"test": "./test",
"underscore": "lodash"
}
}]
]
}
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './component/App'
ReactDOM.render(<App/>, document.getElementById('app'))
// src/App.js
import React from 'react'
export default class App extends React.Component {
render(){
return(
<div>
<h1>My React App</h1>
</div>
)
}
}
"scripts": {
"start":"webpack-dev-server --mode development --open --hot --inline",
// webpack-dev-server, --open : 자동으로 브라우저 열어줌, --hot : hot realod 저장했을 때 자동적으로 reload 해줌
"build":"webpack --mode production"
// dist 폴더에 컴파일된 파일 다 넣어줌
}
/dist 폴더가 생성되면서 index_bundle.js와 index.html이 생성
index.html을 먼저 보면 script 태그가 body안에 생성되어 있는 것을 확인 가능
webpack.config.js 파일의 plugins 에서 Htmlwebplugin의 도움으로 template: './src/index.html'
템플릿에 컴파일 된 번들 파일이 script 태그로 자동적으로 들어가게 되는 것
```
// webpack.config.js
module.exports = {
entry: {
main: './src/main.js',
}
}
index.html:
// webpack.config.js
module.exports = {
output: {
filename: 'bundle.js',
path: './dist'
}
}
// index.html
<body>
<script src="./dist/bundle.js"></script>
</body>
- 사용 babel 로더 사용 전 npm 설치
npm install --save-dev @babel/core babel-loader @babel/preset-react @babel/preset-env
// webpack.config.js
module.exports = {
module: {
rules: [{
test: /\.js$/,
exclude: 'node_modules',
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}]
}
}
참고사이트