test( 'initial state should serialize and deserialize without errors or warnings', () => { const consoleErrorSpy = jest .spyOn( global.console, 'error' ) .mockImplementation( () => () => {} ); const consoleWarnSpy = jest .spyOn( global.console, 'warn' ) .mockImplementation( () => () => {} ); const initialState = createReduxStore().getState(); reducer( reducer( initialState, { type: SERIALIZE } ), { type: DESERIALIZE } ); expect( consoleErrorSpy ).not.toHaveBeenCalled(); expect( consoleWarnSpy ).not.toHaveBeenCalled(); } );
function getInitialServerState() { // Bootstrapped state from a server-render if ( typeof window === 'object' && window.initialReduxState && ! isSupportUserSession() ) { const serverState = reducer( window.initialReduxState, { type: DESERIALIZE } ); return pick( serverState, Object.keys( window.initialReduxState ) ); } return {}; }
function deserialize( state ) { delete state._timestamp; return reducer( state, { type: DESERIALIZE } ); }
function serialize( state ) { const serializedState = reducer( state, { type: SERIALIZE } ); return Object.assign( serializedState, { _timestamp: Date.now() } ); }
export function serverRender( req, res ) { const context = req.context; let title, metas = [], links = [], cacheKey = false; if ( ! isDefaultLocale( context.lang ) ) { const langFileName = getCurrentLocaleVariant( context.store.getState() ) || context.lang; context.i18nLocaleScript = '//widgets.wp.com/languages/calypso/' + langFileName + '.js'; } if ( shouldServerSideRender( context ) ) { cacheKey = getNormalizedPath( context.pathname, context.query ); context.renderedLayout = render( context.layout, req.error ? req.error.message : cacheKey, req ); } if ( context.store ) { title = getDocumentHeadFormattedTitle( context.store.getState() ); metas = getDocumentHeadMeta( context.store.getState() ); links = getDocumentHeadLink( context.store.getState() ); const cacheableReduxSubtrees = [ 'documentHead' ]; let reduxSubtrees; if ( isSectionIsomorphic( context.store.getState() ) ) { reduxSubtrees = cacheableReduxSubtrees.concat( [ 'ui', 'themes' ] ); } else { reduxSubtrees = cacheableReduxSubtrees; } // Send state to client context.initialReduxState = pick( context.store.getState(), reduxSubtrees ); // And cache on the server, too. if ( cacheKey ) { const cacheableInitialState = pick( context.store.getState(), cacheableReduxSubtrees ); const serverState = reducer( cacheableInitialState, { type: SERIALIZE } ); stateCache.set( cacheKey, serverState ); } context.lang = getCurrentLocaleSlug( context.store.getState() ) || context.lang; const isLocaleRTL = isRTL( context.store.getState() ); context.isRTL = isLocaleRTL !== null ? isLocaleRTL : context.isRTL; } context.head = { title, metas, links }; context.clientData = config.clientData; if ( config.isEnabled( 'desktop' ) ) { res.send( renderJsx( 'desktop', context ) ); return; } res.send( renderJsx( 'index', context ) ); }