SSR and

web rendering

References

  • web rendering
    • https://developers.google.com/web/updates/2019/02/rendering-on-the-web
    • https://www.youtube.com/watch?reload=9&v=k-A2VfuUROg&ab_channel=GoogleChromeDevelopers
  • SSR, partial SSR
    • https://medium.com/@luke_schmuke/how-we-achieved-the-best-web-performance-with-partial-hydration-20fab9c808d5
  • SSR 實作
    • https://medium.com/%E6%89%8B%E5%AF%AB%E7%AD%86%E8%A8%98/server-side-rendering-ssr-in-reactjs-part1-d2a11890abfc
  • Others
    • https://addyosmani.com/blog/rehydration/

Summary

  • Summary of Web architecture and Page rendering
  • About SSR
  • Trade-off
  • Different Hydrate Strategies
  • Re-thinking of SSR

Summary of

Web architecture and Page rendering

MPA, SSR

https://caffeinecoding.com/universal-javascript-server-client-rendering/

SPA, CSR

CSR Drawbacks

  • Long FCP (First Contentful Paint) time
  • SEO

SSR + CSR

Universal Rendering

SSR with rehydration

...

 

 

  • 結合了 SSR + CSR
  • 是為了解決 SPA/純CSR 的一些 Drawbacks

It's More than "SSR"

About SSR

假設今天你有個 Single page application,
想要實作SSR, 你需要:

  • 一個負責 SSR 的 server (rendering server)

  • 根據不同的 path,讀取 SPA 的架構, pre-render components 然後 generate static 的 html

  • NodeJS (Js runtime)

// example with koa
import React from 'react';
import Koa from 'koa';
import Router from 'koa-router';
import path from 'path';
import fs from 'fs';

// import spa root component
import App from '../client/App';
// import function for SSR
import { StaticRouter } from 'react-router-dom';
import { renderToString } from 'react-dom/server';

const app = new Koa();

const indexTemplate = fs.readFileSync(path.join(__dirname, '../clientBuild/index.html'), 'utf-8');
app.get('(.*)', (ctx) => {
  const result = renderToString(
    <StaticRouter location={ctx.request.url}>
      <App />
    </StaticRouter>,
  );
  // should use index.html template
  const html = indexTemplate.replace(/#{content}/, result);
  ctx.body = html;
});

app.listen(3000);

A quick look of simple ssr server

<!DOCTYPE html>
<html lang="en">
  <head>
    /* meta */
    <title>SSR Practice</title>
  </head>
  <body>
    <div id="root">
      /* Inject in here */
    </div>
  </body>
</html>
<div>
  <h1>Home</h1>
   <ul>
     <li>Page1</li>
     <li>Page2</li>
   </ul>
</div>
<!DOCTYPE html>
<html lang="en">
  <head>
  	/* meta */
    <title>SSR Practice</title>
  </head>
  <body>
    <div id="root">
      <div>
        <h1>Home</h1>
        <ul>
          <li>Page1</li>
          <li>Page2</li>
        </ul>
      </div>
    </div>
  </body>
</html>

1. spa index.html

2. server render string

3. result html

How it works

  • Render it as an HTML string on the server
  • Send the rendered HTML string to your users as source code (Static)
  • Send your React or other code as JavaScript to your users
  • And then finally “hydrate” your HTML using your React code (become interactive)

Hydrate

<!DOCTYPE html>
<html lang="en">
  <head>
  	/* meta */
    <title>SSR Practice</title>
  </head>
  <body>
    <div id="root">
      <div>
        <h1>Home</h1>
        <ul>
          <li>Page1</li>
          <li>Page2</li>
        </ul>
      </div>
    </div>
  </body>
</html>
ReactDOM.hydrate(<App />, document.getElementById('root'));
ReactDOM.render(<App />, document.getElementById('root'));

More things need to be Handled

  • Css
  • Route
  • Redux
  • Init Page Data
    ...

Render server + SPA

= Universal JavaScript Application

SSG, pre-render

  • Pages are static.
  • Generate at build time

A Quick Look (NextJS)

使用 pages 這個頁面來定義

routing

在 page-level 檔案寫 React Component + SSR 邏輯

/post/test/first-post

Initial Page Data

Trade-off

You have fast First paint, but...

Source: https://addyosmani.com/assets/images/hydrate@2x.png

Web Performance

  • JS Bundle size
  • Code Splitting
  • CDN
  • Encoding (Br, Gzip...)
  • PWA, service worker cache
  • Different Hydration strategies

Streaming server

http.createServer((request, response) => {
  const html = ReactDOMServer.renderToNodeStream(<App />);
  
  response.pipe(html);
}).listen(3000)

Different

Hydrate Strategies

Partial Hydration

example:

pool-attendant-preact

https://medium.com/@luke_schmuke/how-we-achieved-the-best-web-performance-with-partial-hydration-20fab9c808d5

Progressive Hydration

Pieces of the site are "booted up" in order of priority

  • Only hydrate those are interactive
  • Reduce JS bundle
  • Improve hydration cost

Rethinking of SSR

SEO

only for crawlers that not support JavaScript

CSR negatively affect SEO

Improve SEO without full SSR

  • title tag, meta tag
  • Dynamic rendering 

Spectrum

Server-side

rendering

Server-side

rendering

Client-side

rendering

Site                                                                             App

Server-side

rendering

Client-side

rendering

SSR and CSR

Server-side

rendering

Client-side

rendering

pre-rendering

SSR w/

hydration

Server-side

rendering

Client-side

rendering

pre-rendering

SSR w/

hydration

  • partial/progressive hydration
  • streaming server

End

SSR

By Timothy Lee

SSR

  • 509