mirror of
https://github.com/vale981/Vulcan
synced 2025-03-09 20:16:39 -04:00

This method allows for access to the SSR app component and associated css in the routing's hook functions without needing to hack core files. This makes it possible, for example, to add MUI wrapper components and inject compiled css with the JSS library (see https://material-ui-1dab0.firebaseapp.com/guides/server-rendering). Here's how I'd implement the callbacks in my own custom module: https://gist.github.com/wayfarerboy/96c0f1d13b3b7d3d2743501a1c7c0187
76 lines
2.6 KiB
JavaScript
76 lines
2.6 KiB
JavaScript
import React from 'react';
|
|
import Helmet from 'react-helmet';
|
|
import { getDataFromTree, ApolloProvider } from 'react-apollo';
|
|
|
|
import { Meteor } from 'meteor/meteor';
|
|
|
|
import {
|
|
Components,
|
|
addRoute,
|
|
Routes, populateComponentsApp, populateRoutesApp, initializeFragments,
|
|
getRenderContext,
|
|
runCallbacks,
|
|
} from 'meteor/vulcan:lib';
|
|
|
|
import { RouterServer } from './router.jsx';
|
|
|
|
Meteor.startup(() => {
|
|
// note: route defined here because it "shouldn't be removable"
|
|
addRoute({name:"app.notfound", path:"*", componentName: 'Error404'});
|
|
|
|
// init the application components and routes, including components & routes from 3rd-party packages
|
|
initializeFragments();
|
|
populateComponentsApp();
|
|
populateRoutesApp();
|
|
|
|
const indexRoute = _.filter(Routes, route => route.path === '/')[0];
|
|
const childRoutes = _.reject(Routes, route => route.path === '/');
|
|
|
|
const indexRouteWithoutPath = _.clone(indexRoute);
|
|
|
|
if (indexRouteWithoutPath) {
|
|
delete indexRouteWithoutPath.path; // delete path to avoid warning
|
|
}
|
|
|
|
const AppRoutes = {
|
|
path: '/',
|
|
component: Components.App,
|
|
indexRoute: indexRouteWithoutPath,
|
|
childRoutes,
|
|
};
|
|
|
|
const options = {
|
|
historyHook(req, res, newHistory) {
|
|
let { history } = getRenderContext();
|
|
history = runCallbacks('router.server.history', history, { req, res, newHistory });
|
|
return history;
|
|
},
|
|
wrapperHook(req, res, appGenerator) {
|
|
const { apolloClient, store } = getRenderContext();
|
|
store.reload();
|
|
store.dispatch({ type: '@@nova/INIT' }) // the first dispatch will generate a newDispatch function from middleware
|
|
const app = runCallbacks('router.server.wrapper', appGenerator(), { req, res, store, apolloClient });
|
|
return <ApolloProvider store={store} client={apolloClient}>{app}</ApolloProvider>;
|
|
},
|
|
preRender(req, res, app) {
|
|
runCallbacks('router.server.preRender', { req, res, app });
|
|
return Promise.await(getDataFromTree(app));
|
|
},
|
|
dehydrateHook(req, res) {
|
|
const context = runCallbacks('router.server.dehydrate', getRenderContext(), { req, res });
|
|
return context.apolloClient.store.getState();
|
|
},
|
|
postRender(req, res) {
|
|
runCallbacks('router.server.postRender', { req, res });
|
|
},
|
|
htmlHook(req, res, dynamicHead, dynamicBody) {
|
|
const head = runCallbacks('router.server.html', Helmet.rewind(), { req, res, dynamicHead, dynamicBody });
|
|
return {
|
|
dynamicHead: `${head.title}${head.meta}${head.link}${head.script}${dynamicHead}`,
|
|
dynamicBody,
|
|
};
|
|
},
|
|
};
|
|
|
|
RouterServer.run(AppRoutes, options);
|
|
});
|