Skip to content

Instantly share code, notes, and snippets.

@sujin2f
Last active June 20, 2018 17:56
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 sujin2f/349daa102cc628a9fc81a792cc7c874f to your computer and use it in GitHub Desktop.
Save sujin2f/349daa102cc628a9fc81a792cc7c874f to your computer and use it in GitHub Desktop.
import React, { Component } from 'react';
import { withRouter } from 'react-router';
import ArchiveContainer from 'app/components/ArchiveContainer';
import GlobalFooter from 'app/components/Layout/GlobalFooter';
import { getServerPosts, getPostsSuccess, getPostsFail } from 'app/actions/archive';
// getServerPosts function from app/actions/archive
export function getServerPosts(queryVars, source) {
const params = {
per_page: PAGING.postsPerPage,
category_names: queryVars.category || null,
tag_names: queryVars.tag || null,
search: queryVars.searchString || null,
page: queryVars.paged || 1,
};
const cancelToken = source ? { cancelToken: source.token } : {};
return axios.get(
'wp-json/sujin/v1/posts/',
{ params },
{ ...cancelToken },
);
}
class Archive extends Component {
static serverFetch(url) {
const arrUrl = url.split('/').filter(v => v);
const queryVars = {
category: arrUrl[0] === 'category' ? arrUrl[1] : null,
tag: arrUrl[0] === 'tag' ? arrUrl[1] : null,
searchString: arrUrl[0] === 'search' ? arrUrl[1] : null,
paged: arrUrl[3] || null,
};
return getServerPosts(queryVars)
.then(response => getPostsSuccess(response))
.catch(error => getPostsFail(error));
}
render() {
return (
<section className="template-archive">
<main className="page-wrapper">
<ArchiveContainer push={this.props.history.push} params={this.props.match.params} />
</main>
<GlobalFooter />
</section>
);
}
}
export default withRouter(Archive);
import React from 'react';
// Screens
import FrontPage from 'app/scenes/public/screens/FrontPage';
import Page from 'app/scenes/public/screens/Page';
import Archive from 'app/scenes/public/screens/Archive';
import Post from 'app/scenes/public/screens/Post';
import NotFound from 'app/scenes/public/screens/NotFound';
export default {
public: [
{
path: `${process.env.SUJIN_BASE_URL}`,
component: FrontPage,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}:pageSlug`,
exact: true,
render: (props) => {
if (props.match.params.pageSlug === '404') {
return (<NotFound {...props} />);
}
return (<Page {...props} />);
},
},
{
path: `${process.env.SUJIN_BASE_URL}:year(\\d+)/:month(\\d+)/:day(\\d+)/:postSlug`,
component: Post,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}category/:category`,
component: Archive,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}category/:category/page/:paged?`,
component: Archive,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}tag/:tag`,
component: Archive,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}tag/:tag/page/:paged?`,
component: Archive,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}search/:searchString`,
component: Archive,
exact: true,
},
{
path: `${process.env.SUJIN_BASE_URL}search/:searchString/page/:paged?`,
component: Archive,
exact: true,
},
{
path: null,
component: NotFound,
},
],
};
import express from 'express';
import compression from 'compression';
import path from 'path';
import React from 'react';
import config from 'config';
import { renderToString } from 'react-dom/server';
import { StaticRouter, matchPath } from 'react-router-dom';
import { ConnectedRouter } from 'react-router-redux';
import { Provider as ReduxProvider } from 'react-redux';
import Helmet from 'react-helmet';
import Prerender from 'prerender-node';
import routes from 'app/routes';
import App from 'src/components/App';
import Page from 'app/scenes/public/screens/Page';
import configureStore, { initializeSession } from './store';
import manifest from '../../../build/manifest.json';
const app = express();
app.use(compression());
app.use(express.static(path.resolve(__dirname, '../../../', process.env.npm_package_config_paths_output)));
app.use(Prerender);
app.get('/*', (req, res) => {
const context = {};
const { history, store } = configureStore();
store.dispatch(initializeSession());
const dataRequirements =
routes.public
.filter(route => route.path) // filter matching paths
.filter(route => matchPath(req.url, route)) // filter matching paths
.map(route => route.path === '/:pageSlug' ? Page : route.component) // map to components
.filter(comp => comp ? comp.serverFetch : false) // check if components have data requirement
.map(comp => comp.serverFetch(req.url)); // dispatch data requirement
Promise.all(dataRequirements).then((result) => {
if (result && result.length > 0) {
store.dispatch(result.pop());
}
const jsx = (
<ReduxProvider store={store}>
<StaticRouter context={context} location={req.url}>
<App />
</StaticRouter>
</ReduxProvider>
);
const reactDom = renderToString(jsx);
const reduxState = store.getState();
const helmetData = Helmet.renderStatic();
res.writeHead(200, { 'Content-Type': 'text/html' });
const html = htmlTemplate(reactDom, reduxState, helmetData);
res.end(html);
});
});
app.listen(8080);
console.log('Server listening on port 8080!');
function htmlTemplate(reactDom, reduxState, helmetData) {
let vendor = '';
if (manifest['vendor.js']) {
vendor = `<script src="/${manifest['vendor.js']}"></script>`;
}
return `
<!DOCTYPE html>
<html>
<head>
${helmetData.title.toString()}
${helmetData.base.toString()}
${helmetData.meta.toString()}
${helmetData.link.toString()}
${helmetData.script.toString()}
<link rel="stylesheet" href="/${manifest['style.css']}" type="text/css" />
</head>
<body>
<div id="app">${reactDom}</div>
<script>
window.REDUX_DATA = ${JSON.stringify(reduxState)}
</script>
${vendor}
<script src="/${manifest['app.js']}"></script>
</body>
</html>
`;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment