웹팩은 개발용 서버를 제공해주는 것 뿐만 아니라 Mock api도 제공한다.
이를 사용하기 위해서 devServer의 onBeforeSetupMiddleware 속성을 이용하면 된다.
onAfterSetupMiddleware: 다른 모든 미들웨어 이후에 커스텀 미들웨어를 실행할 수 있는 기능을 제공한다.
onBeforeSetupMiddleware: 다른 모든 미들웨어보다 먼저 실행할 수 있는 기능을 제공한다.
( 여기서 언급되는 미들웨어는 Express의 미들웨어를 생각하면된다. )
// webpack.config.js
module.exports = {
devServer: {
port: 9000,
client: {
overlay: true,
},
onBeforeSetupMiddleware: function (devServer) {
if (!devServer) {
throw new Error('webpack-dev-server is not defined');
}
devServer.app.get("/api/keywords", (req, res) => {
res.json([
{ keyword: "이탈리아" },
{ keyword: "세프의요리" },
{ keyword: "제철" },
{ keyword: "홈파티" },
])
});
},
},
}
설정한 url로 요청하면 mock data를 얻을 수 있게 된다.
하지만 mock api에 대한 요청이 많게 되면 해당 웹팩 설정 파일의 코드가 길어지게 될텐데 이를 분리해주는 패키지가 존재한다.
connect-api-mocker 패키지는 특정 폴더를 만들어 api 응답을 담은 파일을 저장하면 이 폴더를 api로 제공해준다.
$ npm i -D connect-api-mocker
// webpack.config.js:
const apiMocker = require("connect-api-mocker")
module.exports = {
devServer: {
port: 9000,
client: {
overlay: true,
},
onBeforeSetupMiddleware: function (devServer) {
if (!devServer) {
throw new Error('webpack-dev-server is not defined');
}
devServer.app.use(apiMocker('/api', 'mocks/api'));
},
},
}
mock data가 잘 받아지는것을 확인 할 수 있었다.
// app.js:
document.addEventListener('DOMContentLoaded', async () => {
const ul = document.querySelector('#list');
const res = await axios.get("/api/keywords");
ul.innerHTML= (res.data || []).map(item => {
return `<li>${item.keyword}</li>`;
}).join('');
});
위에서 사용했던 로컬환경이 아닌 실제 서버와 연동을 하게되면 CORS정책으로 인한 오류가 발생하게 되는데 이를 해결하기 위해서 웹팩 설정파일의 proxy 속성을 이용하면 된다.
CORS
브라우져와 서버간의 보안상의 정책으로 브라우저가 최초로 접속한 서버에서만 ajax 요청을 할 수 있다.
만약 백엔드가 localhost:3000에서 돌아가고 있다면, 아래와 같은 설정을 통해 브라우저에서 벗어나 웹팩 개발 서버에서 서버(백엔드)로 요청할 수 있어 CORS 에러가 나지 않게된다.
// webpack.config.js
module.exports = {
devServer: {
proxy: {
"/api": "http://localhost:3000", // 프록시
// changeOrigin: true // 가상이름일 경우
},
},
}
만약 도메인 이름이 IP주소가 아니라 가상이름일 경우에 changeOrigin: true 옵션을 추가로 작성해줘야한다.
현재는 코드가 변화하면 전체화면을 갱신한다.
SPA에서는 리프레시가 되면 데이터가 날라가기 때문에 이를 방지하기 위해 웹팩 개발서버에서 제공해주는 옵션인 hot 옵션을 사용해야 한다.
// webpack.config.js:
module.exports = {
devServer = {
hot: true,
},
}
hot 옵션을 true로 주면 웹팩 서버의 HMR가 활성화된다.
그리고 추가적으로 Hot Module Replacement(모든 종류의 모듈을 새로고침 할 필요 없이 런타임에 업데이트) interface를 사용해야 한다.
HMR은 프로덕션용이 아니므로 개발용으로만 사용
위와 같은 상황에서 list에 대한 코드를 변화하면 검색한 키워드가 날라가게 된다.
위와 같은 상황에서 list에 대한 코드를 변화해도 검색한 키워드가 날라가지 않는다.
샘플 코드:
import './style.scss';
import form from './form';
import list from './list';
document.addEventListener('DOMContentLoaded', async () => {
const ulEl = document.querySelector('#list');
const formEl = document.createElement('div');
formEl.innerHTML = form.render();
document.body.appendChild(formEl);
ulEl.innerHTML= await list.render();
// Hot Module Replacement interface를 사용
if (module.hot) {
module.hot.accept("./list", async () => {
console.log("list 모듈 변경됨");
ulEl.innerHTML= await list.render();
})
}
});
이러한 방식으로 react-hot-loader, style-loader, file-loader등도 핫 모듈 리플레이스먼트를 지원한다.