forked from withspectrum/spectrum
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
440 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// @flow | ||
console.log('Cadmus starting...'); | ||
const debug = require('debug')('hyperion'); | ||
debug('logging with debug enabled'); | ||
// $FlowFixMe | ||
require('isomorphic-fetch'); | ||
import express from 'express'; | ||
import Loadable from 'react-loadable'; | ||
import path from 'path'; | ||
import { getUser } from 'iris/models/user'; | ||
|
||
const PORT = process.env.PORT || 3006; | ||
|
||
const app = express(); | ||
|
||
if (process.env.NODE_ENV === 'development') { | ||
const logging = require('shared/middlewares/logging'); | ||
app.use(logging); | ||
} | ||
|
||
if (process.env.NODE_ENV === 'production' && !process.env.FORCE_DEV) { | ||
// Raven (Sentry client) needs to come before everything else | ||
const raven = require('shared/middlewares/raven').default; | ||
app.use(raven); | ||
} | ||
|
||
// Cross origin request support | ||
import cors from 'shared/middlewares/cors'; | ||
app.use(cors); | ||
|
||
import cookieParser from 'cookie-parser'; | ||
app.use(cookieParser()); | ||
|
||
import bodyParser from 'body-parser'; | ||
app.use(bodyParser.json()); | ||
|
||
import session from 'shared/middlewares/session'; | ||
app.use(session); | ||
|
||
import passport from 'passport'; | ||
passport.serializeUser((user, done) => { | ||
done(null, user.id); | ||
}); | ||
|
||
passport.deserializeUser((id, done) => { | ||
getUser({ id }) | ||
.then(user => { | ||
done(null, user); | ||
}) | ||
.catch(err => { | ||
done(err); | ||
}); | ||
}); | ||
app.use(passport.initialize()); | ||
app.use(passport.session()); | ||
|
||
// This needs to come after passport otherwise we'll always redirect logged-in users | ||
import threadParamRedirect from 'shared/middlewares/thread-param'; | ||
app.use(threadParamRedirect); | ||
|
||
// Static files | ||
app.use( | ||
express.static(path.resolve(__dirname, '..', 'build'), { index: false }) | ||
); | ||
|
||
import renderer from './renderer'; | ||
app.get('*', renderer); | ||
|
||
Loadable.preloadAll().then(() => { | ||
app.listen(PORT); | ||
console.log( | ||
`Cadmus, the server-side renderer, running at http://localhost:${PORT}` | ||
); | ||
}); |
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// Server-side renderer for our React code | ||
import fs from 'fs'; | ||
const debug = require('debug')('hyperion:renderer'); | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/server'; | ||
import { ServerStyleSheet } from 'styled-components'; | ||
import { | ||
ApolloClient, | ||
createNetworkInterface, | ||
ApolloProvider, | ||
renderToStringWithData, | ||
} from 'react-apollo'; | ||
import { StaticRouter } from 'react-router'; | ||
import { createStore } from 'redux'; | ||
import Helmet from 'react-helmet'; | ||
import * as graphql from 'graphql'; | ||
import Loadable from 'react-loadable'; | ||
import { getBundles } from 'react-loadable/webpack'; | ||
import stats from '../../build/react-loadable.json'; | ||
|
||
import getSharedApolloClientOptions from 'shared/graphql/apollo-client-options'; | ||
import { getHTML, createScriptTag } from './get-html'; | ||
|
||
// Browser shim has to come before any client imports | ||
import './browser-shim'; | ||
const Routes = require('../../src/routes').default; | ||
import { initStore } from '../../src/store'; | ||
|
||
const IN_MAINTENANCE_MODE = | ||
process.env.REACT_APP_MAINTENANCE_MODE === 'enabled'; | ||
const IS_PROD = process.env.NODE_ENV === 'production'; | ||
const FORCE_DEV = process.env.FORCE_DEV; | ||
|
||
if (!IS_PROD || FORCE_DEV) console.log('Querying API at localhost:3001/api'); | ||
|
||
const renderer = (req, res) => { | ||
debug(`server-side render ${req.url}`); | ||
// Create an Apollo Client with a local network interface | ||
const client = new ApolloClient({ | ||
ssrMode: true, | ||
networkInterface: createNetworkInterface({ | ||
uri: | ||
IS_PROD && !FORCE_DEV | ||
? `https://alpha.spectrum.chat/api` | ||
: 'http://localhost:3001/api', | ||
opts: { | ||
credentials: 'include', | ||
}, | ||
}), | ||
...getSharedApolloClientOptions(), | ||
}); | ||
// Define the initial redux state | ||
const initialReduxState = { | ||
users: { | ||
currentUser: req.user, | ||
}, | ||
}; | ||
// Create the Redux store | ||
const store = initStore(initialReduxState, { | ||
// Inject the server-side client's middleware and reducer | ||
middleware: [client.middleware()], | ||
reducers: { | ||
apollo: client.reducer(), | ||
}, | ||
}); | ||
let modules = []; | ||
const report = moduleName => { | ||
debug(`codesplitted module ${moduleName} used`); | ||
modules.push(moduleName); | ||
}; | ||
const context = {}; | ||
// The client-side app will instead use <BrowserRouter> | ||
const frontend = ( | ||
<Loadable.Capture report={report}> | ||
<ApolloProvider store={store} client={client}> | ||
<StaticRouter location={req.url} context={context}> | ||
<Routes maintenanceMode={IN_MAINTENANCE_MODE} /> | ||
</StaticRouter> | ||
</ApolloProvider> | ||
</Loadable.Capture> | ||
); | ||
// Initialise the styled-components stylesheet and wrap the app with it | ||
const sheet = new ServerStyleSheet(); | ||
debug(`render frontend`); | ||
renderToStringWithData(sheet.collectStyles(frontend)) | ||
.then(content => { | ||
if (context.url) { | ||
debug('found redirect on frontend, redirecting'); | ||
// Somewhere a `<Redirect>` was rendered, so let's redirect server-side | ||
res.redirect(301, context.url); | ||
return; | ||
} | ||
// Get the resulting data | ||
const state = store.getState(); | ||
const helmet = Helmet.renderStatic(); | ||
if (IN_MAINTENANCE_MODE) { | ||
debug('maintainance mode enabled, sending 503'); | ||
res.status(503); | ||
res.set('Retry-After', 3600); | ||
} else { | ||
res.status(200); | ||
} | ||
const bundles = getBundles(stats, modules) | ||
// Create <script defer> tags from bundle objects | ||
.map(bundle => | ||
createScriptTag({ src: `/${bundle.file.replace(/\.map$/, '')}` }) | ||
) | ||
// Make sure only unique bundles are included | ||
.filter((value, index, self) => self.indexOf(value) === index); | ||
debug('compile and send html'); | ||
const scriptTags = [...bundles].join('\n'); | ||
debug(`script tags: ${scriptTags}`); | ||
// Compile the HTML and send it down | ||
res.send( | ||
getHTML({ | ||
content, | ||
state, | ||
styleTags: sheet.getStyleTags(), | ||
metaTags: | ||
helmet.title.toString() + | ||
helmet.meta.toString() + | ||
helmet.link.toString(), | ||
scriptTags, | ||
}) | ||
); | ||
res.end(); | ||
}) | ||
.catch(err => { | ||
console.log(err); | ||
res.status(500); | ||
res.end(); | ||
throw err; | ||
}); | ||
}; | ||
|
||
export default renderer; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.