• 이 글은 React webpack from the scratch의 영상을 보고 간단하게 요약한 글입니다.
  • 이 글을 따라하시더라도 충분하도록 설명을 달아놓았지만 더 자세하게 알고 싶으시다면 위의 링크를 참조하시길 바랍니다.
  • 원본 소스는 버전이 바뀌면서 많이 다릅니다. 참조하실 분들은 저의 github에서 소스코드를 받으실 수 있습니다.

package.json

npm init
  • package.json 생성

react, react-dom

npm react
npm react-dom
  • react
    • 리액트 라이브러리
  • react-dom
    • browser, dom, webapp 관리

webpack

npm install --save-dev webpack webpack-dev-server webpack-cli html-webpack-plugin
  • *webpack *
    • 모든 리액트 파일을 하나의 컴파일된 하나의 자바스크립트 파일에 넣기 위해
  • webpack-dev-server
    • live reload
  • webpack-cli
    • build 스크립트를 통해 webpack 커맨스 사용하기 위해
  • html-webpack-plugin
    • 나중에 webpack.config.js에서 사용할 플러그인

--save-dev : 개발환경에서만 사용되는 라이브러리라는 것을 명시

babel

npm install --save-dev @babel/core babel-loader @babel/preset-react @babel/preset-env 
  • @babel/core
    • 리액트는 es6를 사용하므로 여러 브라우저에서 사용가능하도록 es5문법으로 바꿔줌
  • @babel/preset-react
  • @babel/preset-env
  • babel-loader
    • 자바스크립트 파일을 babel과 webpack을 사용하여 es5로 컴파일 해주는 plugin
    • jsx를 컴파일 해줄 수 있도록
    • html webpack plugin

babel이 7로 업데이트 되면서 scoped package로 전환했다. 간단히 이야기하면 기존의 비공식적인 package들과 네이밍 컨벤션에 문제가 있어서 바꾸게 되었다. 영상에서는 babel-core라고 되어있지만 install하게되면 7, 8이 설치되므로 (특히 babel-loader) package 설정에 유의해야 할 듯하다.

webpack.config

  • webpack을 사용하기 위한 설정파일

webpack.config.js

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',                            // 리액트 파일이 시작하는 곳
    output: {                                           // bundled compiled 파일
        path: path.join(__dirname, '/dist'),            //__dirname : 현재 디렉토리, dist 폴더에 모든 컴파일된 하나의 번들파일을 넣을 예정
        filename: 'index_bundle.js'
    },
    module: {                                           // loader를 module object에 넣을 예정
        rules: [
            {
                test: /\.js$/,                          // .js, .jsx로 끝나는 babel이 컴파일하게 할 모든 파일
                exclude: /node_module/,                 // node module 폴더는 babel 컴파일에서 제외
                use:{
                    loader: 'babel-loader'
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html'                // 생성한 템플릿 파일
        })
    ]
}

위의 설정들을 크게 살펴보자

  • path
    • 파일의 경로를 지정
  • HtmlWebpackPlugin
    • 컴파일 이후 index.html 파일을 생성
  • module.export
    • 출력할 모듈

  • entry
    • 컴파일 할 파일
  • output
    • 컴파일 이후 파일
  • module
    • 모듈의 컴파일 형식
  • plugin
    • 사용할 plugins

html-webpack-plugin

  • html-webpack-plugin은 script 태그안에 넣은 webpack 번들 파일과 함께 html5 파일을 생성한다.

webpack.config.js

onst HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}

위의 코드는 다음과 같이 dist/index.html파일을 생성한다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webpack App</title>
  </head>
  <body>
    <script src="index_bundle.js"></script>
  </body>
</html>

index_bundle.js가 webpack에 의해 컴파일, 번들화된 하나의 js 파일이다.

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>
  • webpack plugin이 index.html의 script 태그안에 컴파일된 bundle 파일을 심어줄 것이다.
  • new HtmlWebpackPlugin()을 위의 예시처럼 그냥 사용하는 것도 좋지만 이렇게 템플릿을 만들어 놓으면 커스터마이징 하기 편하다

.babelrc

  • babel-preset-envbabel-preset-react와 같이 preset을 사용하고 싶으면 root폴더에 .babelrc을 생성하여 사용하고자할 preset을 설정하자
  • plugin들을 각각의 npm dependency를 가지고 있다. 설치시 매번 .bablrc에 설정을 해야하므로 그 두가지를 모두 해결해줄 preset을 사용하므로 preset을 설치하고 설정하므로서 preset이 가진 plugin들을 설정할 필요없이 사용할 수 있게된다.
{
    "presets": [
        "@babel/env",
        "@babel/react"
    ]
}

@babel이 버전이 업데이트 되면서 더이상 babel-core 형태의 dependency를 지원하지 않게되므로서 @babel/env를 사용해야 한다

index.js

import React from 'react';
import ReactDOM from 'react-dome';
import App from './component/App'

ReactDOM.render(<App/>, document.getElementById('app'))                       // dom에 render학 메인 app component, rendering 할 곳

App.js

import React from 'react'

export default class App extends React.Component {
    render(){
        return(
            <div>
                <h1>My React App</h1>
            </div>
        )
    }
}

package.json

"scripts": {
    "start":"webpack-dev-server --mode developemnt --open --hot",                    // webpack-dev-server, --open : 자동으로 브라우저 열어줌, --hot : hot realod 저장했을 때 자동적으로 reload 해줌
    "build":"webpack --mode production"                                              // dist 폴더에 컴파일된 파일 다 넣어줌
  },

이제 지금까지 작성한 프로젝트를 실행해보자

npm start

그렇다면 다음과 같은 화면이 보일 것이다.

스크린샷 2019-09-03 오후 4.34.24.png

그리고 프로젝트를 build해보자

npm run build

그러면 /dist 폴더가 생성되면서 index_bundle.jsindex.html이 생성됨을 알 수 있다.

스크린샷 2019-09-03 오후 4.37.00.png

index.html을 먼저 보면 <script type="text/javascript" src="index_bundle.js"></script> script 태그가 body안에 생성되어 있는 것을 확인할 수 있다. 이는 webpack.config.js 파일의 plugins 에서 Htmlwebplugin의 도움으로 template: './src/index.html'템플릿에 컴파일 된 번들 파일이 script 태그로 자동적으로 들어가게 되는 것이다.

스크린샷 2019-09-03 오후 4.37.27.png

이번에 index_bundle.js 파일을 살펴보면 js, jsx 파일들이 es6에서 es5로 컴파일하여 알아서 순서대로 묶어서 하나의 파일로 넣어 줌을 알 수 있다. 이는 자바스크립트의 모듈 태그 순서에 따라서 문제를 손쉽게 해결 해줄 수 있다.
스크린샷 2019-09-03 오후 4.42.42.png

조금 더 자세한 내용은 ES6, babel 그리고 webpack을 어떻게 사용할까을 참조하시기 바랍니다.