first working draft

This commit is contained in:
eric-burel 2018-11-20 14:41:46 +01:00
parent 93a317af24
commit 42ac3c37db
4 changed files with 73 additions and 2 deletions

View file

@ -91,7 +91,7 @@ const createApolloServer = ({ options: givenOptions = {}, config: givenConfig =
// ssr
WebApp.connectHandlers.use(ssrMiddleware)
//WebApp.connectHandlers.use(ssrMiddleware)
/*
* Alternative syntax with Express instead of Connect

View file

@ -0,0 +1,16 @@
import React from 'react';
import { Helmet } from 'react-helmet';
const Head = () => {
// Helmet.rewind() is deprecated in favour of renderStatic() for better readability
//@see https://github.com/nfl/react-helmet/releases/tag/5.0.0
const helmet = Helmet.renderStatic();
return (
<head>
{helmet.title.toComponent()}
{helmet.meta.toComponent()}
{helmet.link.toComponent()}
</head>
);
};
export default Head;

View file

@ -3,11 +3,25 @@
/* eslint-disable react/no-danger */
import React from 'react';
import { Helmet } from 'react-helmet'
const Head = () => {
// Helmet.rewind() is deprecated in favour of renderStatic() for better readability
//@see https://github.com/nfl/react-helmet/releases/tag/5.0.0
const helmet = Helmet.renderStatic()
return (
<head>
{helmet.title.toComponent()}
{helmet.meta.toComponent()}
{helmet.link.toComponent()}
</head>
)
}
// this render the page and add a script that will load the serialized data
const Html = ({ content, state }) => {
return (
<html>
<Head />
<body>
<div id="root" dangerouslySetInnerHTML={{ __html: content }} />
<script dangerouslySetInnerHTML={{

View file

@ -14,9 +14,50 @@ import createClient from './createClient';
import React from 'react';
import ReactDOM from 'react-dom/server';
// onPageLoad is mostly equivalent to an Express middleware
// excepts it is tailored to handle Meteor server side rendering
import { onPageLoad } from 'meteor/server-render'
import Html from './Html';
import Head from './Head'
import appGenerator from './appGenerator';
onPageLoad(async (sink) => {
const req = sink.request
// according to the Apollo doc, client needs to be recreated on every request
// this avoids caching server side
const client = createClient(req);
// TODO adapt to Vulcan
const context = {};
const App = appGenerator({ req, client, context })
// Alternative that relies on Meteor server-render:
// @see https://github.com/szomolanyi/MeteorApolloStarter/blob/master/imports/startup/server/ssr.js
// TODO: adapt to Vulcan
// @see https://github.com/apollographql/GitHunt-React/blob/master/src/server.js
// @see https://www.apollographql.com/docs/react/features/server-side-rendering.html#renderToStringWithData
// equivalent to calling getDataFromTree and then renderToStringWithData
//sink.appendToBody(ReactDOM.renderToStaticMarkup(<div id='react-app'></div>))
const content = await renderToStringWithData(App)
console.log(content.slice(0,100))
const wrappedContent = `<div id="react-app">${content}</div>`
sink.appendToBody(wrappedContent)
//sink.renderIntoElementById('react-app', 'HI')//content)
// add headers
const head = ReactDOM.renderToString(Head)
sink.appendToHead(head)
// add data
const initialState = client.extract();
sink.appendToBody(ReactDOM.renderToString(
<script dangerouslySetInnerHTML={{
__html: `window.__APOLLO_STATE__ = ${JSON.stringify(initialState).replace(/</g, '\\u003c')};`,
}} />
))
})
const ssrMiddleware = (req, res) => {
// according to the Apollo doc, client needs to be recreated on every request
// this avoids caching server side