I'm Miguel รngel Durรกn ๐Ÿ™‹โ€โ™‚๏ธ

ย 

Enabler Frontend
at Adevinta Spain ๐Ÿ‡ช๐Ÿ‡ธ๐Ÿ‘จโ€๐Ÿ’ป

ย 

โ˜• coffee addict
โš›๏ธ React fanboy
๐Ÿ‘พ fanatic Gamer
๐Ÿš€ and performance freak ๐Ÿคช!

@midudev

youtube.com/c/midudev

Performance focus at Adevinta Spain

Dynamic Rendering

Getting the most out of performance ๐Ÿš€
while keeping bots happy ๐Ÿค–

โšก๏ธ

and friends...

the problem

Understanding

the problem

is...

rendering stuff on the client is expensive

and

quick recap
rendering on the web

let's do a

about

Server Side Rendering (SSR)

๐Ÿ‘ TTI & FCP

๐Ÿ‘ Fully streaming
ย 

๐Ÿ‘Ž Slow TTFB

๐Ÿ‘Ž Inflexible

๐Ÿ‘Ž Infrastructure

๐Ÿ‘Ž Interactive with different language

Great for static content with little or zero client interaction

Static Rendering

Individual HTML files must be generated for every possible URL. Great for blogs, landings and static pages.

๐Ÿ‘ TTI & FCP

๐Ÿ‘ Fully streaming

๐Ÿ‘ Fast TTFB!

๐Ÿ‘ Static files

ย 

๐Ÿ‘Ž Inflexible

๐Ÿ‘€ hydratation could be needed

export

Client Side Rendering

SPA fully rendered on the client. Very easy to set up, fast to develop, plenty of possibilities. No strong SEO requirements.

๐Ÿ‘ Flexible

๐Ÿ‘ TTFB
๐Ÿ‘ Just static files


๐Ÿ‘Žย Slow TTFB

๐Ÿ‘Žย TTI way after FCP

trying to get the best of two worlds

SSR ๐ŸŒ + CSR ๐ŸŒŽ

SSR with (re)hydration

finally

that's (re)hydration
and it looks like this...

SSR with (re)hydration

๐Ÿ‘ Flexible

๐Ÿ‘ Universal code


๐Ÿ‘Žย Slow TTFB

๐Ÿ‘Žย TTI >>>>> FCP

๐Ÿ‘Ž Infrasructure

SPA fully rendered on the server,
fully booted on the client as well
๐Ÿคญ

someone in the audience that usesย  ย  ย  ย  ...
but doesn't want to say it

SSR with (re)hydration

SPA fully rendered on the server,
fully booted on the client as well
๐Ÿคญ

๐Ÿ”ฅ

๐Ÿ‘ Flexible

๐Ÿ‘ Universal code


๐Ÿ‘Žย Slow TTFB

๐Ÿ‘Žย TTI >>>>> FCP

๐Ÿ‘Ž Infrasructure


is getting the best...

or the worst of both?

ย 

ย 

a solution

Finding

solution

and the

is...

render less things

on the client and/or the server

but... how?

๐Ÿค– keep my SEO

โš›๏ธ keep the flexibility of my app

๐Ÿ‘ฉโ€๐Ÿ’ป give the best experience to my users

I still want to...

Dynamic Rendering

ftw!

Dynamic Rendering

wt* is...

if you're a bot ๐Ÿค–, you'll get a SSR or prerendered page

if you're a human being ๐Ÿ‘ซ, you'll get a CSR

๐Ÿค–

๐Ÿ‘ซ

doesย  ย  ย  ย  ย  ย  ย  like it?

I hope it does.

It's their idea! ๐Ÿ’ก

Strategies

Dynamic Rendering

by Route

by Component

Dynamic

Rendering

by route

// ๐Ÿš‡ middleware to activate Dynamic Rendering on Express
const BOTS_USER_AGENTS = [
  'googlebot',
  'google-structured-data-testing-tool',
  'mediapartners-google'
]

const INDEX_HTML_PATH = path.join(__dirname, 'public', 'index.html')
const HTML_TEMPLATE = fs.readFileSync(INDEX_HTML_PATH, 'utf8')

export default function(req, res, next) {
  const rawUserAgent = req.get('user-agent')
  const userAgent = rawUserAgent.toLowerCase()

  // check if the request comes from a bot ๐Ÿค–
  if (BOTS_USER_AGENTS.find(ua => userAgent.includes(ua))) {
    // if not an user, just use the normal behaviour (SSR?)
    return next()
  }

  // return index.html directly if is an user ๐Ÿ‘ฉโ€๐Ÿ’ป
  return res.send(HTML_TEMPLATE)
}
// ๐Ÿš† Using the middleware in Express
const dynamicRendering = require('./dynamic-rendering')

// Use dynamic rendering for a specific path for testing
app.get(
    '/es/:op/:type/barcelona-capital/*',
    dynamicRenderingExperiment
)

// Isomorphic routes handler
app.get('*', SSR)

Dynamic Rendering

at route level

DEMO

Dynamic

Rendering

by route

โ™ป๏ธ TTFB

๐Ÿงน Hydration data is gone


๐Ÿค” Just a CSR for the user

๐Ÿšฉ FP & FCP

๐Ÿงช Useful technique for perf experiments

๐Ÿ†“ Free resources from your server

โณ Help GoogleBot to index your content faster

โ˜๏ธย More about this, later ๐Ÿ‘‰

Dynamic

Rendering

at component level

Dynamic

Rendering

at component level

if you're a bot ๐Ÿค–

the component is SSR

if you're a human being ๐Ÿ‘ซ
the component will be
rendered when visible

ย 

// โš›๏ธ Using <DynamicRendering /> component 
// userAgent must be retrieved universally on server and client

<DynamicRendering userAgent={universalUserAgent}>
    <a href='https://very-interesting-url.com'>
        <VeryComplexToComputeComponent />
        <img src='https://huge-image.com/panda.jpg'/>
    </a>
</DynamicRendering>

@schibstedspain/react-perf-dynamic-rendering
http://bit.ly/sui-dynamic-rendering

<DynamicRendering disabled>
  <img src='https://huge-image.com/panda_02.jpg'/>
</DynamicRendering>

<DynamicRendering height={50}>
  <img src='https://huge-image.com/panda_02.jpg'/>
</DynamicRendering>

<DynamicRendering height={50} forceRender={true}>
  <p>This will be rendered on client & server even
    when is out the viewport
  </p>
  <p>Or in the server even when is a regular user agent</p>
  <img src='https://huge-image.com/panda_02.jpg'/>
</DynamicRendering>

@schibstedspain/react-perf-dynamic-rendering
http://bit.ly/sui-dynamic-rendering

// โš›๏ธ <DynamicRendering /> implementation

export default function DynamicRendering(props) {
  const { children, disabled, forceRender, height, userAgent } = props

  // check if the userAgent is a bot and if we're in the browser
  const isBot = checkUserAgentIsBot({userAgent})
  const isOnBrowser = typeof window !== 'undefined'

  // Force render in server and client
  if (forceRender) return children

  // if isBot or disabled, we return in server and client the content
  if (isBot) return children

  // now, we're sure the user isNotBot
  // so check if we're on the browser side and if is not disabled the component
  if (isOnBrowser && !disabled) {
    return <LazyContent height={height}>{children}</LazyContent>
  } else {
    // so, we're on the server side or the component is disabled
    return <div style={{height: `${height}px`}} />
  }
}

Dynamic Rendering

at component level

@schibstedspain/react-perf-dynamic-rendering

๐Ÿ”— http://bit.ly/sui-dynamic-rendering

Only 1๏ธโƒฃ requirement:

It's open source!

you need to use React โš›๏ธ

Dynamic Rendering

at component level

DEMO

seek 0:52

Dynamic

Rendering

at component level

โœ…ย Improve TTI

๐Ÿ˜ด Lazy Load for the user


๐Ÿšฉ Keep Hydration data

๐Ÿ‹๏ธโ€โ™€๏ธ Perfect for stuff below the foldย 

๐Ÿ†“ Free resources from your server

โณ Help GoogleBot to index your content faster

โ˜๏ธย More about this, later ๐Ÿ‘‰

The new GoogleBot is superb!

๐Ÿงฉ JS Modules

๐Ÿ“ Intersection Observer

๐Ÿงฑ Custom Elements

๐ŸŒš Shadow DOM

๐Ÿซ Classes

๐Ÿท Tagged Template Literals

Why do we need this?

links detected

at a later time

๐Ÿ’ธ expensive!

https://youtu.be/LXF8bM4g-J4

130 trillion web pages to crawl

rendering all those pages, takes time

WRS

Google Bot 101

https://youtu.be/LXF8bM4g-J4

If you want/need your site

to be crawled fast and indexed faster

you better bet on SSR

tl;dl ๐Ÿ‘‚

for now

Static

Rendering

at component level

// โš›๏ธ <StaticContent /> usage
import StaticContent from './StaticContent'

function Footer () {
  return (
    <StaticContent>
      <HugeListOfLinks data={listOfLinks} />
    </StaticContent>
  )
}
// โš›๏ธ <StaticContent /> component
import React from 'react'

export default function StaticContent({children}) {
  // we're in the server, just render the content
  if (typeof window === 'undefined') {
    return <div>{children}</div>
  }

  // avoid re-render on the client
  return (
    <div
      suppressHydrationWarning
      dangerouslySetInnerHTML={{__html: ''}}
    />
  )
}

Static Rendering

DEMO

Static

Rendering

at component level

๐Ÿ‘ Avoid re-hydrate for static components

๐Ÿ‘ Thus could greatly improve TTI


๐Ÿ‘Ž Lose interactivity

๐Ÿ‘Žย Hydration data still there

๐Ÿ‘Ž Element wrapper (ex. <div>)

๐Ÿ“ธ For expensive rendering lists or static content

๐Ÿค–ย GoogleBot is definitely going to detect it

That's all!

Thanks!

gifs borrowed from @eh_cat!

@midudev

youtube.com/c/midudev

Made with Slides.com