



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
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


Dynamic Rendering: Getting the most out of performance while keeping bots happy
By Miguel Angel Durán García
Dynamic Rendering: Getting the most out of performance while keeping bots happy
Version: Frontend Connect Presentation Wien 2019
- 600