react hot-loader와 webpack-dev-server적용

국물빌런·2020년 8월 2일
1

react-hot-loader와 webpack-dev server를 이용하여 자동 빌드 시스템을 구축해보자

리액트 핫 로더 설치 - 수정사항을 바로 반영해줌

#npm i -D react-hot-loader

웹팩 개발서버 설치 - 웹팩 서버 역할을 해준다.

  • npm i -D webpack-dev-server

package.json에 webpack 명령어 수정

{
  "name": "wordrelay",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    **"dev": "webpack-dev-server --hot",**
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "devDependencies": {
    "@babel/core": "^7.10.5",
    "@babel/plugin-proposal-class-properties": "^7.10.4",
    "@babel/preset-env": "^7.10.4",
    "@babel/preset-react": "^7.10.4",
    "babel-loader": "^8.1.0",
    "react-hot-loader": "^4.12.21",
    "webpack": "^4.44.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  }
}

client.jsx 수정

const React = require('react');
const ReactDom = require('react-dom');

const WordRelay = require('./WordRelay'); //불러올 컴포넌트
**const { hot } = require('react-hot-loader/root'); //hot-loader불러오기**
	**const Hot = hot(WordRelay); //hot-loader적용**

//hot-loader가 적용된 Hot변수로 변경함
ReactDom.render(<**Hot** />, document.getElementById('root')); //렌더링

webpack.config.js의 babel loader option의 plugin에 hot-loader를 추가한다

const path = require('path');

module.exports = {
    name : 'wordrelay-setting', //웹팩 이름
    mode : 'development', //실서비스는 production
    devtool : 'eval',
    resolve : { //확장자를 생략하기 위한 설정
        extensions : ['.js', '.jsx'] //여기에 확장자를 적어줌
    },

    module : {
        rules : [
            {
                test: /\.jsx?/,
                loader: 'babel-loader',
                options: {
                    presets: [
                        ['@babel/preset-env', {
                            targets: {
                                browsers: ['> 5% in KR','last 2 chrome versions'],
                            },
                            debug: true,
                        }],
                        '@babel/preset-react'],
                    plugins: [
                        "@babel/plugin-proposal-class-properties",
                        **"react-hot-loader/babel",**
                    ],
                },//options end
            },
        ],
    },

    entry : {
        app : ['./client'] //client.jsx에서 불러오는 모듈은 안적어줘도 자동으로 같이 패킹함
    }, //입력 파일 설정
    output : {
        path : path.join(__dirname,'dist'), //현재디렉토리 + dist
        filename : 'app.js',
				// webpack-dev-server 사용 시 <script src="./dist/app.js"></script> /dist 경로 추가
        // 추가 없을 시에 html 에서 <script src="./dist/app.js"></script> 가 아닌 <script src="./app.js"></script> 로 해줘야 동작
        publicPath: '/dist/'
    }, //출력 파일 설정

};

이제 테스트 해보자

#npm run dev

새로 고침해야 적용이 된다..?왜지..

로컬호스트로 접속해서 디버그 콘솔을 찍었더니

loader: detected appcontainer unmount on module './client.jsx' update. did you use "hot(wordrelay)" and "reactdom.render()" in the same file? "hot(wordrelay)" shall only be used as export.

리로드 될 때 이런 메시지가 뜸.

hot모듈은 export로만 쓰라고 한다. 같은 파일에서 바로 쓰지말래..

시키는대로 해보자.

client.jsx 원복

const React = require('react');
const ReactDom = require('react-dom');

const WordRelay = require('./WordRelay'); //불러올 컴포넌트

ReactDom.render(<WordRelay />, document.getElementById('root')); //렌더링

WordRelay.jsx에서 Hot모듈 사용하여 export

const React = require('react');
const ReactDom = require('react-dom');

class WordRelay extends React.Component {
    state = {
        word: '국물',
        value: '',
        result: ''
    };

    onSubmitForm = (e) => {
        e.preventDefault();
        if (this.state.word[this.state.word.length -1] === this.state.value[0]) { //right
            this.setState({
                word: this.state.value,
                value: '',
                result: '정답입니다.'
            });
        }
        else { //failed
            this.setState({
                value: '',
                result: '틀렸습니다.'
            });
        }
        this.input.focus(); //커서는 항상 input박스로!
    }

    input;
    onRefInput = (c) => {
        this.input = c;
    }

    onChangeInput = (e) => { //text박스에 입력 이벤트가 발생할때마다 value를 새로 렌더링
        this.setState({ value: e.target.value })
    }

    render() {
        return (
            <>
                <div>{this.state.word}</div>
                <form onSubmit={this.onSubmitForm}>
                    <input ref={this.onRefInput} value={this.state.value} onChange={this.onChangeInput}/>
                    <button>클릭</button>
                </form>
                <div>{this.state.result}</div>
            </>
        );
    }
}

**const { hot } = require('react-hot-loader/root');
const Hot = hot(WordRelay);
module.exports = Hot;**

시키는 대로 하니까 잘 된다..

profile
국물을 달라

0개의 댓글