Skip to content

Latest commit

 

History

History
424 lines (319 loc) · 9.07 KB

deck.mdx

File metadata and controls

424 lines (319 loc) · 9.07 KB

import { CodeSurfer, CodeSurferColumns, Step, } from "code-surfer"; import { condensed } from 'mdx-deck/themes' import { github, vsDark } from "@code-surfer/themes";

export const themes = [ condensed, vsDark, { colors: { text: '#FFF', background: "#000" }, styles: { CodeSurfer: { title: { backgroundColor: "#000", color: "#FFF" }, code: { backgroundColor: "#000" }, pre: { backgroundColor: "#000" } } } } ]

Howdy 👋 I'm Daniel

Senior Front-End Engineer @ H-E-B Digital


Server Side Rendering

  • Why SSR?
  • SSR at H-E-B Digital
  • How to SSR your app

Why Server Side Render?


Progressive Enhancement

  • Resolve your data internally
  • Ship only what the client needs
  • Defer javascript parsing after rendering

Tools for SSR

  • Webpack Code Splitting
  • Univeral Component Library
  • React Router
  • Styled Components
  • React Helmet

SSR at H-E-B Digital

Decoupling our Java Monolith


Component Rendering Service

  • API for SSR React components
  • Returns markup, critical CSS and JS
  • Sets up a shared Redux and Apollo context
  • Decouples UI from our Java Application

{
	"components": {
		"Header": {
			"component": "Header",
			"props": {
				"searchTerm": "apples"
			}
		},
		"Footer": {
			"component": "Footer"
		}
	},
  "state": {
    "cartItems": 5
  }
}

{
  "preload": "<link rel=\"preload\" href=\"Header.5438fe62fe34bb6f2a65.js\" as=\"script\" />",
  "styles": "<style data-styled data-styled-version=\"5.0.0\">body {...}</style>",
  "components": {
    "Header": "<div data-heb-key=\"Header\">...</div>"
    "Footer": "<div data-heb-key=\"Footer\">...</div>"
  },
  "state": "<script type=\"text/javascript\">window.__PRELOADED_STATE__ = {...}; </script>",
  "scripts": "<script type=\"text/javascript\" src=\"Header.5438fe62fe34bb6f2a65.js\" defer=\"defer\">"
}

React Single Page Application

  • Full page routes with code splitting
  • Same components as rendering service
  • Fully decoupled from our Java Application

How It's Done


import { Provider as ReduxProvider } from "react-redux";
import { ApolloProvider } from "@apollo/react-hooks";
import { ThemeProvider } from "styled-components";

export function WrappedApp({ apolloClient, reduxStore }) {
  return (
    <ThemeProvider>
        <ApolloProvider client={apolloClient}>
            <ReduxProvider store={reduxStore}>
                <Routes />
            </ReduxProvider>
        </ApolloProvider>
    </ThemeProvider>
  );
}

  import { renderToString } from 'react-dom/server';

  const application = renderToString(
    <App />
  );
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';

  const store = createStore();

  const application = renderToString(
    <App store={store} />
  );

  const state = store.getState();
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';
  import { ServerStyleSheet } from "styled-components";
  
  const store = createStore();
  const sheet = new ServerStyleSheet();

  const application = renderToString(
    sheet.collectStyles(
      <App store={store} />
    )
  );

  const state = store.getState();
  const styles = sheet.getStyleTags();
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';
  import { ServerStyleSheet } from "styled-components";
  import flushChunks from 'webpack-flush-chunks';
  import { flushChunkNames } from 'react-universal-component/server';

  const store = createStore();
  const sheet = new ServerStyleSheet();

  const application = renderToString(
    sheet.collectStyles(
      <App store={store} />
    )
  );

  const state = store.getState();
  const styles = sheet.getStyleTags();

  const chunkNames = flushChunkNames();
  const { js } = flushChunks(clientStats, { chunkNames });
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';
  import { ServerStyleSheet } from "styled-components";
  import flushChunks from 'webpack-flush-chunks';
  import { flushChunkNames } from 'react-universal-component/server';

  const store = createStore();
  const sheet = new ServerStyleSheet();

  const application = renderToString(
    sheet.collectStyles(
      <App store={store} />
    )
  );

  const state = store.getState();
  const styles = sheet.getStyleTags();

  const chunkNames = flushChunkNames();
  const { js } = flushChunks(clientStats, { chunkNames });

  return `<!doctype html>
    <html>
      <head>
        <title>My Application</title>
        ${styles}
      </head>
      <body>
        <div id="root">${application}</div>
        <script type="text/javascript">
          window.__PRELOADED_STATE__ = ${JSON.stringify(state).replace(/</g, '\\u003c')};
        </script>
        ${js}
      </body>
    </html>`;
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';
  import { ServerStyleSheet } from "styled-components";
  import flushChunks from 'webpack-flush-chunks';
  import { clearChunks, flushChunkNames } from 'react-universal-component/server';

  const store = createStore();
  const sheet = new ServerStyleSheet();

  const application = renderToString(
    sheet.collectStyles(
      <App store={store} />
    )
  );

  const state = store.getState();
  const styles = sheet.getStyleTags();

  const chunkNames = flushChunkNames();
  const { js } = flushChunks(clientStats, { chunkNames });

  sheet.seal();
  clearChunks();

  return `<!doctype html>
    <html>
      <head>
        <title>My Application</title>
        ${styles}
      </head>
      <body>
        <div id="root">${application}</div>
        <script type="text/javascript">
          window.__PRELOADED_STATE__ = ${JSON.stringify(state).replace(/</g, '\\u003c')};
        </script>
        ${js}
      </body>
    </html>`;
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';
  import { ServerStyleSheet } from "styled-components";
  import flushChunks from 'webpack-flush-chunks';
  import { clearChunks, flushChunkNames } from 'react-universal-component/server';
  import { createClient } from 'client/create';

  const client = createClient();
  const store = createStore();
  const sheet = new ServerStyleSheet();

  const AppTree = <App store={store} apolloClient={client} />

  await getDataFromTree(AppTree);

  const application = renderToString(
    sheet.collectStyles(AppTree)
  );

  const state = store.getState();
  const styles = sheet.getStyleTags();

  const chunkNames = flushChunkNames();
  const { js } = flushChunks(clientStats, { chunkNames });

  sheet.seal();
  clearChunks();

  return `<!doctype html>
    <html>
      <head>
        <title>My Application</title>
        ${styles}
      </head>
      <body>
        <div id="root">${application}</div>
        <script type="text/javascript">
          window.__PRELOADED_STATE__ = ${JSON.stringify(state).replace(/</g, '\\u003c')};
        </script>
        ${js}
      </body>
    </html>`;
  import { renderToString } from 'react-dom/server';
  import { createStore } from 'store/create';
  import { ServerStyleSheet } from "styled-components";
  import flushChunks from 'webpack-flush-chunks';
  import { clearChunks, flushChunkNames } from 'react-universal-component/server';
  import { createClient } from 'client/create';

  const client = createClient();
  const store = createStore();
  const sheet = new ServerStyleSheet();

  const AppTree = <App store={store} apolloClient={client} />

  await getDataFromTree(AppTree);

  const application = renderToString(
    sheet.collectStyles(AppTree)
  );

  const apolloState = client.extract();
  const state = store.getState();
  const styles = sheet.getStyleTags();

  const chunkNames = flushChunkNames();
  const { js } = flushChunks(clientStats, { chunkNames });

  sheet.seal();
  clearChunks();

  return `<!doctype html>
    <html>
      <head>
        <title>My Application</title>
        ${styles}
      </head>
      <body>
        <div id="root">${application}</div>
        <script type="text/javascript">
          window.__APOLLO_STATE__ = ${JSON.stringify(apolloState).replace(/</g, '\\u003c')};
          window.__PRELOADED_STATE__ = ${JSON.stringify(state).replace(/</g, '\\u003c')};
        </script>
        ${js}
      </body>
    </html>`;


Thanks!

tijerina.daniel@heb.com

https://github.com/ithinkdancan