WEB/react
react - next 프레임워크를 활용해 ssr(server side rendering) 간단히 해결
Woogamza
2019. 8. 20. 03:06
728x90
server side rendering을 next의 getInitialProps를 활용해 간단하게 해결해보자.
redux와 redux-saga를 활용해 문제를 해결한다.
다양한 액션 중 블로그에서 포스팅한 글들을 프론트 서버에서 백엔드 서버로 요청하는 것을 해보자.
pages 폴더의 _app.js 에서 useEffect를 활용해 dispatch를 한다고 하면
1. next와 redux-saga를 연결할 패키지를 다운 받는다
npm i next-redux-saga
npm i next-redux-wrapper
npm i redux-saga
2. saga를 config 하자.
(_app.js) 파일
import rootSaga from './saga.js' // saga를 지정해 놓은 파일
import withRedux from 'next-redux-wrapper' //next와 redux의 미들웨어( 여기서는 saga)를 연결
import withReduxSaga from 'next-redux-saga'
import createSagaMiddleware from 'redux-saga'
///대충
///redux관련
const App = ({Component, store, pageProps}) =>{
//대충 redux 관련 코드, 모든 페이지에 적용할 코드 들 (ex Provider로 store 건내주기)
}
//...
//대충 propTypes 관련 코드
//...
App.getInitialProps = async (context) => {
let pageProps = {}
const {ctx, Component} = context //ctx는 프론트 서버가 실행하면서 next가 context를 전달해줌.
const state = ctx.store.getState() // redux의 store에서 state를 getState를 통해 꺼내온다
ctx.store.dispatch({
type: LOAD_POST_REQUEST //포스팅한 글들을 reducer를 이용한 dispatch
})
pageProps = await Component.getInitialProps(ctx)
return pageProps
}
const storeConfig = (initialState, options) =>{
const sagaMiddleware = createSagaMiddleWare()
const middlewares = [sagaMiddleware] //middleware들 다 여기로 모여라~
const enhancer = process.env.NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: compose(
applyMiddleware(...middlewares),
!options.isServer && typeof window.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined' ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f,
) // chrome redux devtools 에 대한 설정. (redux devtools를 개발모드에서만 사용하고 싶어요 라는 내용)
const store = createStore(reducer, initialState, enhancer);
store.sagaTask = sagaMiddleware.run(rootSaga);
return store;
}
export default withRedux(storeConfig)(withReduxSaga(App))
그런데, withcredential 옵션을 사용할때 쿠키를 넣어주어야 한다면은
App.getInitialProps = async (context) => {
let pageProps = {}
const {ctx, Component} = context //ctx는 프론트 서버가 실행하면서 next가 context를 전달해줌.
const state = ctx.store.getState() // redux의 store에서 state를 getState를 통해 꺼내온다
const cookie = ctx.isServer ? ctx.req.headers.cookie : '' // 서버에서 요청할때 ctx에 req객체가 붙는다.
if(ctx.isServer &&cookie){
axios.defaults.headers.cookie = cookie
}
ctx.store.dispatch({
type: LOAD_POST_REQUEST //포스팅한 글들을 reducer를 이용한 dispatch
})
pageProps = await Component.getInitialProps(ctx)
return pageProps
}
+추가
storeConfig 에서 getInitialProps의 action을 로깅해주는 커스텀 미들웨어를 만들어보자
const storeConfig = (initialState, options) =>{
const sagaMiddleware = createSagaMiddleWare()
const middlewares = [sagaMiddleware, (store)=>(next)=>(action)=>{
console.log(store)
next(action)
}] // 커스텀 미들웨어
const enhancer = process.env.NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: compose(
applyMiddleware(...middlewares),
!options.isServer && typeof window.__REDUX_DEVTOOLS_EXTENSION__ !== 'undefined' ? window.__REDUX_DEVTOOLS_EXTENSION__() : f => f,
) // chrome redux devtools 에 대한 설정. (redux devtools를 개발모드에서만 사용하고 싶어요 라는 내용)
const store = createStore(reducer, initialState, enhancer);
store.sagaTask = sagaMiddleware.run(rootSaga);
return store;
}