Webpack4 그리고 babel7으로 React 개발환경 구축하기

시작하기

Create-react-app을 이용해서 작업을 해오면서 eject를 하지 않는 이상 webpack과 babel의 설정을 해볼 기회는 많이 없습니다.
하지만 webpack과 babel을 알고 개발환경을 구축하면서 이해를 돕도록 하겠습니다.

설치하기

프로젝트 폴더를 만들어 주도록 합니다.

1
2
3
mkdir ft-webpack
cd ft-webpack
npm init

package.json 파일이 생성되었습니다.
설치시 -D 혹은 --save-dev로 설치를 합니다.
이것은 개발환경에서만 사용되는 라이브러리를 뜻합니다. package.json의 "devDependencies"에 추가됩니다.

Babel (바벨) 알아보기

바벨 패키지를 설치합니다.

1
npm install --D @babel/core @babel/preset-react @babel/preset-env babel-loader
  • @babel/core : es6를 여러 브라우저에서 사용가능하도록 es5문법으로 바꿔주는 역할을 합니다.
  • @babel/preset-react : jsx 파일을 js로 변환시켜줍니다.
  • @babel/preset-env : es6뿐만 아니라 브라우저에 맞춰서 컴파일 해줍니다.
  • babel-loader
    • 자바스크립트 파일을 babel preset/plugin과 webpack을 사용하여 es5로 컴파일 해주는 plugin입니다.
    • jsx 파일을 js로 컴파일하는 기능을 합니다.

Webpack (웹팩) 알아보기

웹팩 패키지를 설치합니다.

1
npm install -D webpack webpack-dev-server webpack-cli html-loader html-webpack-plugin clean-webpack-plugin
  • webpack: 많은 자바스크립트 파일을 컴파일된 하나의 자바스크립트 파일에 넣기 위해 사용합니다.
  • webpack-dev-server : 실시간으로 리로드해주는 기능을 합니다.
  • webpack-cli : build 스크립트를 통해 webpack 커맨드를 사용할수 있게 해줍니다.
  • html-webpack-plugin : html 파일을 생성해주는 플러그인입니다.
  • html-loader: html 파일을 읽을수 있게 해주는 기능을 합니다.
  • clean-webpack-plugin : 사용하지 않는 빌드 파일을 자동으로 삭제해줍니다.

설명

plugin
plugin은 컴파일러입니다.
Webpack의 핵심 기능으로 많은 플러그인이 존재합니다.
기본적으로 대부분의 source 코드를 bundle 파일로 번환합니다.

preset
플러그인이 필요할때마다 각자 선택해서 설치후 추가하는것은 손이 많이 가는 일입니다.
preset은 주로 사용하는 플러그인이 집합되어 있어 preset으로 한번에 추가 및 관리 할 수 있습니다.

Webpack-javascript 파일 빌드

웹팩으로 자바스크립트 파일을 빌드해보겠습니다.
src폴더내부에 index.js파일을 만듭니다.

src/index.js
1
console.log('webpack bundle');

최상위 폴더에서 config폴더를 만들고 그 내부에 webpack.config.js 파일을 만듭니다.

config/webpack.config.js
1
2
3
4
5
6
7
8
9
10
const path = require('path');

module.exports = {
entry: "./src/index.js",
output: {
filename: 'bundle.js',
path: path.resolve(__dirname + '/build') // __dirname는 현재 파일경로를 나타냅니다.
},
mode: 'none'
}

entry는 빌드할 파일을 설정해주는 역할을 합니다.
output은 output에 명시되어 있는 정보를 통해 빌드 파일을 생성합니다.
mode는 웹팩 빌드 옵션 입니다.
production은 최적화되서 빌드됩니다.
development는 빠르게 빌드합니다.
none 같은 경우는 아무 기능 없이 웹팩으로 빌드합니다.
webpack config에 직접 설정을 하거나 package.json에서 webpack --mode production 형식으로 작성할 수도 있습니다.

package.json 파일로 이동하신 후 다음과 같이 build: webpack 스크립트를 추가해 주세요

package.json
1
2
3
//...
"build": "webpack",
//...

npm run build

javascript-build

Html-loader 빌드

웹팩에서는 로더(loader)라는 기능을 사용할 수 있습니다.
로더는 자바스크립트 파일이 아닌 파일을 웹팩 인식하여 사용할 수 있게 해줍니다.

1
2
3
4
5
6
7
8
9
10
11
module : {
rules: {
test: "/Regex/",
use: [
{
loader: "loader",
options: { "loader-option" }
}
]
}
}

loadermodule내부 rule에서 적용할 파일 정규식과 사용할 로더와 로더의 옵션을 설정해주면됩니다.

루트폴더에서 public폴더를 만들고 index.html파일을 생성합니다.

/public/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<title>ft-webpack</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

webpack.config.js파일을 수정합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/index.js",
output: {
filename: 'bundle.js',
path: path.resolve(__dirname + '/build')
},
module: {
rules: [
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './public/index.html',
filename: 'index.html'
})
],
mode: 'none'
}

html-build

React 웹팩 설정

index.js 파일에 dom을 연동하고 App을 불러옵니다.
App.js파일을 생성합니다.

src/index.js
1
2
3
4
5
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("root"));
src/App.js
1
2
3
4
5
6
7
import React from 'react';

const App = () => {
return (<div>App</div>)
}

export default App;

이후 루트 폴더에서 .babelrc파일을 생성하고 다음을 저장해주도록 합니다.

.babelrc
1
2
3
{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}
  • @babel/preset-react : jsx 파일을 js로 변환시켜줍니다.
  • @babel/preset-env : es6뿐만 아니라 브라우저에 맞춰서 컴파일 해줍니다.

이제 webpack.config.js파일을 수정해주겠습니다.

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");

module.exports = {
entry: "./src/index.js",
output: {
filename: 'bundle.js',
path: path.resolve(__dirname + '/build')
},
module: {
rules: [
{
test: /\.(js|jsx)/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './public/index.html',
filename: 'index.html'
})
],
mode: 'none'
}

npm run build를 하고 build/index.html파일을 브라우저로 실행하면 React App컴포넌트에 있던 App텍스트가 나오는것을 확인할 수 있습니다.
react-build

Webpack-dev-server 설정하기

지금까지 build를 통해서 수동으로 파일을 새로고침을 하며 확인을 해보았습니다.
이 과정은 실제로 개발을 할 시에 매우 번거롭습니다. 이것을 보완하기 위한것으로 webpack-dev-server로 소스코드를 수정할때마다 알아서 웹팩이 빌드해주는 webpack-dev-server가 있습니다.

devServer 설정을 해주도록 하겠습니다.

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
//...
output: {
filename: 'bundle.js',
path: path.resolve(__dirname + '/build')
},
devServer: {
contentBase: path.resolve("./build"),
index: "index.html",
port: 9000
},
module: {
rules: [
//...

devServer추가 하지 않으면 http://localhost:8080/로 연결이 됩니다.
devServer 속성값

속성명 description CLI 사용
host 사용될 호스트 지정 webpack-dev-server –host 127.0.0.1
contentBase 콘텐츠를 제공할 경로지정 (정적파일을 제공하려는 경우에만 필요) webpack-dev-server –content-base /path/to/content/dir
compress 모든 항목에 대해 gzip압축 사용 webpack-dev-server –compress
hot webpack의 HMR 기능 활성화 webpack-dev-server -hot
inline inline 모드 활성화 webpack-dev-server –inline=true
port 접속 포트 설정 webpack-dev-server –port 9000
open dev server 구동 후 브라우저 열기 webpack-dev-server –open

package.json 파일을 수정해주도록 합니다.

pacakge.json
1
2
3
4
"scripts":{
"build": "webpack",
"start": "webpack-dev-server --hot"
}

npm run start를 하면 개발 서버가 시작 됩니다.
webpack-dev-server

클린 웹팩 플러그인

사용하지 않는 빌드 파일을 자동으로 삭제해줍니다.

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
//...
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
//...
},
plugins: [
//...
new CleanWebpackPlugin()
],
//...
}

플러그인에 추가합니다.

모드 설정하기

production모드와 development모드 설정을 하겠습니다.
환경변수를 이용해 웹팩설정 가장 밑에 mode를 수정합니다.
환경변수를 모른다면 환경변수 포스트를 참고해주세요

webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const __DEV__ = process.env.NODE_ENV === 'development';
const webpackDevServer = __DEV__ ? {
devServer: {
contentBase: path.resolve("./build"),
index: "index.html",
port: 5000
}
} : {};

module.exports = {
entry: "./src/index.js",
output: {
filename: __DEV__ ? '[name].js' : '[name].[chunkhash].js',
path: path.resolve(__dirname + '/build')
},
...webpackDevServer,
mode: __DEV__ ? "development" : "production",
module: {
rules: [
{
test: /\.(js|jsx)/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: './public/index.html',
filename: 'index.html'
}),
new CleanWebpackPlugin()
]
}

filename: __DEV__ ? '[name].js':'[name].[chunkhash].js',
환경변수를 변경하면서 파일이름도 변경하였습니다.
name은 이름이 항상 같기에 파일이 덮어쓰기로 작성이 됩니다.
하지만 chunkhash는 매번 실행할때마다 다른 고유의 이름으로 만들어지기 때문에 덮어씌우기가 되는것이 아니라 새로운 파일이 생성이 됩니다.
[chunkhash]의 경우 잘 사용해야 하는 것이 개발모드에서 빌드를 계속하다보면 점점 메모리가 쌓이게 되고 결국에는 서버가 뻩는 상황이 오게 됩니다. 그렇기 때문에 development모드에서는 고정이름인 [name]을 사용합니다.

package.json의 스크립트도 수정합니다.
npm i -D cross-env
cross-env 라이브러리는 프로그램을 CLI 환경에서 실행시킬 때에 환경변수를 설정하는 기능을 가지고 있습니다.

package.json
1
2
3
4
"scripts": {
"start": "cross-env NODE_ENV=development webpack-dev-server --hot",
"build": "cross-env NODE_ENV=production webpack"
}

이것으로 webpack과 babel을 이용해서 리액트 개발 초기설정을 해보았습니다.

Share