Skip to content

Instantly share code, notes, and snippets.

@RyanCCollins
Last active February 20, 2017 23:06
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 RyanCCollins/31d55d9ba48fd872591447ef59a88fbf to your computer and use it in GitHub Desktop.
Save RyanCCollins/31d55d9ba48fd872591447ef59a88fbf to your computer and use it in GitHub Desktop.
import * as React from 'react';
import { ApolloClient, createNetworkInterface } from 'apollo-client';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import morgan from 'morgan';
import express from 'express';
import compression from 'compression';
import path from 'path';
import { ApolloProvider } from 'react-apollo';
import store from '../client/store';
import { routes } from '../client/routes';
import Html from '../client/containers/Html';
import graphQlEntry from './graphqlEntry';
const env = require('node-env-file');
env(path.join(process.cwd(), '.env'));
require('./db');
const styleSheet = require('styled-components/lib/models/StyleSheet');
const manifest = require('../../public/manifest.json');
const expressApp = express();
graphQlEntry(expressApp).then((app) => {
app.use(compression());
// Need to set this to your api url
const IP = process.env.IP || '0.0.0.0';
const PORT = process.env.PORT || 1338;
const API_URL = process.env.API_URL;
const apiUrl = API_URL || `http://${PORT}:${IP}/api`;
const debug = process.env.DEBUG === 'true' || false;
if (debug) {
app.use(morgan('combined'));
}
app.use('/public', express.static(path.join(__dirname, '../../public')));
// Much of this is for rendering React on the server and has nothing to do with graphql.
app.use((req, res) => {
match({ routes, location: req.url },
(error, redirectLocation, renderProps) => {
if (redirectLocation) {
res.redirect(redirectLocation.pathname + redirectLocation.search);
} else if (error) {
console.error('ROUTER ERROR:', error); // eslint-disable-line no-console
res.status(500);
} else if (renderProps) {
const styles = styleSheet.rules().map((rule) => rule.cssText).join('\n');
const state = store.getState();
// Create a network interface for Apollo to use to connect
// The server-rendered app to the graphql endpoint.
const networkInterface = createNetworkInterface({
uri: apiUrl,
opts: {
headers: req.headers,
credentials: 'same-origin',
},
});
const client = new ApolloClient({
networkInterface,
ssrMode: true,
});
// Wrap the server rendered app with the ApolloProvider
// passing the client and store to it
const content = renderToString(
<ApolloProvider store={store} client={client}>
<RouterContext {...renderProps} />
</ApolloProvider>,
);
const html = (
<Html
content={content}
scriptHash={manifest['/main.js']}
vendorHash={manifest['/vendor.js']}
cssHash={manifest['/main.css']}
styles={styles}
state={state}
/>
);
res.status(200).send(`<!doctype html>\n${renderToStaticMarkup(html)}`);
} else {
res.status(404).send('Not found');
}
});
});
app.listen(PORT, IP, (err) => {
if (err) {
throw err;
}
return console.info(`==> 😎 Listening on port ${PORT}. Open http://${IP}:${PORT} in your browser.`);
});
})
.catch((err) => console.error(err));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment