Skip to content

Instantly share code, notes, and snippets.

@velopert
Created November 7, 2017 07:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save velopert/eaf43495de3b2155993ff36a0dc166f1 to your computer and use it in GitHub Desktop.
Save velopert/eaf43495de3b2155993ff36a0dc166f1 to your computer and use it in GitHub Desktop.
SSR 참고 자료
import React from 'react';
import ReactDOM from 'react-dom';
import Root from './Root';
import registerServiceWorker from './registerServiceWorker';
import routes from './routes';
import { matchPath } from 'react-router';
import 'styles/base.scss';
const render = async () => {
// 코드스플리팅된 라우트들을 먼저 불러온 다음에 렌더링
const getComponents = [];
routes.forEach(
route => {
const match = matchPath(window.location.pathname, route);
if(!match) return;
const { getComponent } = route.component;
if(getComponent) {
getComponents.push(getComponent());
}
}
);
await Promise.all(getComponents);
ReactDOM.hydrate(<Root />, document.getElementById('root'));
};
render();
registerServiceWorker();
import React from 'react';
import PageTemplate from 'components/common/PageTemplate';
import PostContainer from 'containers/post/PostContainer';
import AskRemoveModalContainer from 'containers/modal/AskRemoveModalContainer';
import * as postActions from 'store/modules/post';
const PostPage = ({match}) => {
const { id } = match.params;
return (
<PageTemplate>
<PostContainer id={id}/>
<AskRemoveModalContainer id={id}/>
</PageTemplate>
);
};
PostPage.preload = (dispatch, params, query) => {
const { id } = params;
return dispatch(postActions.getPost(id));
}
export default PostPage;
import { ListPage, PostPage, EditorPage } from 'pages';
export default [
{
path: '/',
exact: true,
component: ListPage
},
{
path: '/post/:id',
component: PostPage
},
{
path: '/page/:page',
component: ListPage
},
{
path: '/tag/:tag/:page?',
component: ListPage
},
{
path: '/editor',
component: EditorPage
}
];
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { StaticRouter, matchPath } from 'react-router';
import App from 'components/App';
import { Provider } from 'react-redux';
import configure from 'store/configure';
import transit from 'transit-immutable-js';
import { Helmet } from 'react-helmet';
import axios from 'axios';
import routes from './routes';
import queryString from 'query-string';
function parseQuery(url) {
return queryString.parse(url.substring(url.indexOf('?') + 1));
}
const render = async (url, apiBaseURL) => {
if(apiBaseURL) {
axios.defaults.baseURL = apiBaseURL;
}
const store = configure();
const promises = [];
// 서브 라우트도 있는 경우를 대비하여 forEach 사용
routes.forEach(
route => {
const match = matchPath(url, route);
if(match) {
// redux connect 를 사용한 경우 WrappedComponent 조사
const { component } = route;
const { preload } = component;
if(!preload) return;
const { params } = match;
const promise = preload(store.dispatch, params, parseQuery(url));
promises.push(promise);
}
}
);
try {
await Promise.all(promises);
} catch (e) {
}
const html = ReactDOMServer.renderToString(
<Provider store={store}>
<StaticRouter location={url}>
<App/>
</StaticRouter>
</Provider>
);
const helmet = Helmet.renderStatic();
return {
helmet,
html,
preloadedState: JSON.stringify(transit.toJSON(store.getState())).replace(/</g, '\\u003c')
};
};
export default render;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment