Skip to content

Commit

Permalink
Cadmus -> Hyperion
Browse files Browse the repository at this point in the history
  • Loading branch information
mxstbr committed Dec 4, 2017
1 parent 0a723c2 commit f733df5
Show file tree
Hide file tree
Showing 12 changed files with 440 additions and 8 deletions.
74 changes: 74 additions & 0 deletions hyperion/index.js
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.
136 changes: 136 additions & 0 deletions hyperion/renderer/index.js
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.
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
"fbjs": "0.8.16"
},
"scripts": {
"start": "cross-env NODE_ENV=production node build-cadmus/main.js",
"start": "cross-env NODE_ENV=production node build-hyperion/main.js",
"start:athena": "cross-env NODE_ENV=production node build-athena/main.js",
"start:hermes": "cross-env NODE_ENV=production node build-hermes/main.js",
"start:chronos": "cross-env NODE_ENV=production node build-chronos/main.js",
Expand All @@ -154,8 +154,8 @@
"dev:hermes": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=hermes*shared:middlewares*, cross-env DIR=hermes backpack",
"dev:chronos": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=chronos*,shared:middlewares*,-chronos:resolvers cross-env DIR=chronos backpack",
"dev:mercury": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=mercury*,shared:middlewares*,-mercury:resolvers cross-env DIR=mercury backpack",
"dev:cadmus": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=cadmus*,shared:middlewares*,-cadmus:resolvers cross-env DIR=cadmus backpack",
"build": "npm run build:client && npm run build:cadmus",
"dev:hyperion": "cross-env NODE_PATH=./ cross-env NODE_ENV=development cross-env DEBUG=hyperion*,shared:middlewares*,-hyperion:resolvers cross-env DIR=hyperion backpack",
"build": "npm run build:client && npm run build:hyperion",
"prebuild:iris": "rimraf build-iris",
"build:iris": "cross-env NODE_PATH=./ cross-env DIR=iris backpack build",
"postbuild:iris": "cp iris/package.json build-iris/package.json && cp now.json build-iris/now.json",
Expand All @@ -171,9 +171,9 @@
"prebuild:mercury": "rimraf build-mercury",
"build:mercury": "cross-env NODE_PATH=./ cross-env DIR=mercury backpack build",
"postbuild:mercury": "cp mercury/package.json build-mercury/package.json && cp now.json build-mercury/now.json",
"prebuild:cadmus": "rimraf build-cadmus",
"build:cadmus": "cross-env NODE_PATH=./ cross-env DIR=cadmus backpack build",
"postbuild:cadmus": "cp now.json build-cadmus/now.json",
"prebuild:hyperion": "rimraf build-hyperion",
"build:hyperion": "cross-env NODE_PATH=./ cross-env DIR=hyperion backpack build",
"postbuild:hyperion": "cp now.json build-hyperion/now.json",
"build:client": "cross-env NODE_PATH=./ react-app-rewired build",
"jest": "cross-env NODE_PATH=./ jest",
"pretest": "cross-env NODE_PATH=./ NODE_ENV=test npm run db:migrate && babel-node shared/testing/setup-db.js",
Expand Down
Loading

0 comments on commit f733df5

Please sign in to comment.