Skip to content

Commit

Permalink
withRenderContext
Browse files Browse the repository at this point in the history
  • Loading branch information
comus committed Feb 8, 2017
1 parent 665547e commit 3968e49
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 40 deletions.
8 changes: 4 additions & 4 deletions packages/nova-core/lib/modules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export {
Headtags,
// redux
getActions, addAction, getReducers, addReducer, getMiddlewares, addMiddleware,
// render
renderContext, getRenderContext,
// render context
renderContext, getRenderContext, withRenderContext,
// routes
Routes, addRoute, getRoute, populateRoutesApp,
// settings
Expand All @@ -32,8 +32,8 @@ export {
configureStore,
// mutations (for server only)
newMutation, editMutation, removeMutation,
// ssr (for server only)
ssr, ssrNext
// render context (for server only)
withRenderContextRaw,
} from 'meteor/nova:lib';

export { default as App } from "./components/App.jsx";
Expand Down
2 changes: 1 addition & 1 deletion packages/nova-lib/lib/client/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import cookie from 'react-cookie';

import { Meteor } from 'meteor/meteor';

import { getRenderContext } from './render.js';
import { getRenderContext } from './render_context.js';

const context = getRenderContext();

Expand Down
2 changes: 1 addition & 1 deletion packages/nova-lib/lib/client/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import './auth.js';

export * from '../modules/index.js';
export * from './mongo_redux.js';
export * from './render.js';
export * from './render_context.js';
2 changes: 1 addition & 1 deletion packages/nova-lib/lib/client/mongo_redux.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getRenderContext } from './render.js';
import { getRenderContext } from './render_context.js';

const { store } = getRenderContext;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import { browserHistory } from 'react-router';

import { createApolloClient, addReducer, addMiddleware, getReducers, getMiddlewares } from '../modules/index.js';

const history = browserHistory;

const loginToken = global.localStorage['Meteor.loginToken'];
const apolloClient = createApolloClient();

Expand Down Expand Up @@ -32,6 +35,7 @@ store.reload = function reload() {
};

const context = {
history,
loginToken,
apolloClient,
reducers,
Expand All @@ -46,3 +50,7 @@ export const renderContext = {
};

export const getRenderContext = () => renderContext.get();

export const withRenderContext = (func) => {
func();
};
2 changes: 1 addition & 1 deletion packages/nova-lib/lib/server/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ import './oauth_config.js';
export * from '../modules/index.js';
export * from './store.js';
export * from './mutations.js';
export * from './render.js';
export * from './render_context.js';
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { createMemoryHistory } from 'react-router';

import { Meteor } from 'meteor/meteor';
import { DDP } from 'meteor/ddp';
import { Accounts } from 'meteor/accounts-base';
import { RoutePolicy } from 'meteor/routepolicy';

import { createApolloClient, getReducers, getMiddlewares } from '../modules/index.js';
import { configureStore } from './store.js';
Expand All @@ -11,6 +14,26 @@ export const renderContext = new Meteor.EnvironmentVariable();

export const getRenderContext = () => renderContext.get();

function isAppUrl(req) {
const url = req.url;
if (url === '/favicon.ico' || url === '/robots.txt') {
return false;
}

if (url === '/app.manifest') {
return false;
}

// Avoid serving app HTML for declared routes such as /sockjs/.
if (RoutePolicy.classify(url)) {
return false;
}

// we only need to support HTML pages only
// this is a check to do it
return /html/.test(req.headers.accept);
}

const LoginContext = function LoginContext(loginToken) {
this._loginToken = loginToken;

Expand All @@ -32,22 +55,8 @@ const LoginContext = function LoginContext(loginToken) {
}
};

export const ssr = (func, options = {}) => {
export const withRenderContextRaw = (func, options = {}) => {
const newFunc = Meteor.bindEnvironment((req, res, next) => {
req.loginToken = req.loginToken || (req.cookies && req.cookies.meteor_login_token);
req.apolloClient = req.apolloClient || createApolloClient({ currentUserToken: req.loginToken });
req.reducers = req.reducers || { ...getReducers(), apollo: req.apolloClient.reducer() };
req.middlewares = req.middlewares || [...getMiddlewares(), req.apolloClient.middleware()];
req.store = req.store || configureStore(req.reducers, {}, req.middlewares);
req.loginContext = req.loginContext || new LoginContext(req.loginToken);
req.renderContext = req.renderContext || {
loginToken: req.loginToken,
apolloClient: req.apolloClient,
reducers: req.reducers,
middlewares: req.middlewares,
store: req.store,
};

Fiber.current._meteor_dynamics = Fiber.current._meteor_dynamics || [];
Fiber.current._meteor_dynamics[DDP._CurrentInvocation.slot] = req.loginContext;
Fiber.current._meteor_dynamics[renderContext.slot] = req.renderContext;
Expand All @@ -65,12 +74,30 @@ export const ssr = (func, options = {}) => {
WebApp.connectHandlers.use(newFunc);
}

export const ssrNext = (func) => {
ssr(func, { autoNext: true });
}
export const withRenderContext = (func) => {
withRenderContextRaw(func, { autoNext: true });
};

WebApp.connectHandlers.use(Meteor.bindEnvironment((req, res, next) => {
if (!isAppUrl(req)) {
next();
return;
}

ssr((req, res, next) => {
// initialize
// console.log(Fiber.current)
req.history = createMemoryHistory(req.url);
req.loginToken = req.cookies && req.cookies.meteor_login_token;
req.apolloClient = createApolloClient({ currentUserToken: req.loginToken });
req.reducers = { ...getReducers(), apollo: req.apolloClient.reducer() };
req.middlewares = [...getMiddlewares(), req.apolloClient.middleware()];
req.store = configureStore(req.reducers, {}, req.middlewares);
req.loginContext = new LoginContext(req.loginToken);
req.renderContext = {
history: req.history,
loginToken: req.loginToken,
apolloClient: req.apolloClient,
reducers: req.reducers,
middlewares: req.middlewares,
store: req.store,
};
next();
});
}));
4 changes: 1 addition & 3 deletions packages/nova-routing/lib/client/routing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ Meteor.startup(() => {
store.reload();
},
historyHook(newHistory) {
const context = getRenderContext();
const history = newHistory;
context.history = history;
const { history } = getRenderContext();
return history;
},
wrapperHook(appGenerator) {
Expand Down
6 changes: 3 additions & 3 deletions packages/nova-routing/lib/server/router.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cookieParser from 'cookie-parser';
import { RoutePolicy } from 'meteor/routepolicy';
import { WebApp } from 'meteor/webapp';

import { ssr, ssrNext } from 'meteor/nova:core';
import { withRenderContext, withRenderContextRaw } from 'meteor/nova:core';

import { InjectData } from './inject_data.js';

Expand Down Expand Up @@ -117,7 +117,7 @@ export const RouterServer = {
WebApp.rawConnectHandlers.use(cookieParser());

// Ensure router middleware is at the end
ssrNext(() => {
withRenderContext(() => {
const stack = WebApp.connectHandlers.stack;
if (stack[stack.length - 1].handle.name === 'routerMiddleware') {
return;
Expand All @@ -129,7 +129,7 @@ export const RouterServer = {
}
});

ssr((req, res, next) => {
withRenderContextRaw((req, res, next) => {
if (!isAppUrl(req)) {
next();
return;
Expand Down
6 changes: 2 additions & 4 deletions packages/nova-routing/lib/server/routing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ Meteor.startup(() => {

const options = {
historyHook(req, res, newHistory) {
req.history = newHistory;
const context = getRenderContext();
context.history = req.history;
return req.history;
const { history } = getRenderContext();
return history;
},
wrapperHook(req, res, appGenerator) {
const { apolloClient, store } = getRenderContext();
Expand Down

0 comments on commit 3968e49

Please sign in to comment.