react-hot-loader와 webpack-dev server를 이용하여 자동 빌드 시스템을 구축해보자
리액트 핫 로더 설치 - 수정사항을 바로 반영해줌
#npm i -D react-hot-loader
웹팩 개발서버 설치 - 웹팩 서버 역할을 해준다.
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;**
시키는 대로 하니까 잘 된다..