import { Cite } from 'spectacle'
import CodeSlide from 'spectacle-code-slide'
import { LightSlide } from './slides'
import RegularComponent from './regular-component'
import TitleCard from '../src/components/TitleCard'
import PoppingCircle from '../src/components/PoppingCircle'
import Spacer from '../src/components/Spacer'
import SpacedRow from '../src/components/SpacedRow'
import Avatar from '../src/components/Avatar'
import Footnote from '../src/components/Footnote'
import AnimationIntroScreen from '../src/components/AnimationIntroScreen'
import ExternalLink from '../src/components/ExternalLink'
import FlexRow from '../src/components/FlexRow'
import BigNumber from '../src/components/BigNumber'
import './index.css'
# 👋🏻 Good morning!
---
export default LightSlide
import meSrc from '../assets/me.jpg'
#### This is what I look like on the internet ↴
---
export default LightSlide
I like cats, but I'm allergic
---
export default LightSlide
### @joshwcomeau
### Send me your cats
---
export default LightSlide
🛴 💥
---
# Performance
---
### Things we optimize for performance:
- Server-side rendering (or compile-time rendering)
- Code-splitting
- Tree-shaking
- Asset optimization
- Lazy-loading
---
### Things we don't focus on as much:
- Everything after the page is loaded and interactive
---
---
Some context...
---
import amazonArticle from '../assets/amazon-article.png'
---
import slowLoading from '../assets/slow-loading.jpg'
---
import amazonArticle2 from '../assets/amazon-article-pt2.png'
---
import mansplaining from '../assets/mansplaining.png'
---
import acSearchResults from '../assets/ac-search-results.png'
---
### People are not patient
---
We **remain impatient** after the page is loaded and interactive.
---
---
# Interactions
---
import inputDelaySrc from '../assets/input-delay.mp4'
---
---
hillelwayne.com/post/performance-matters
---
import pcrSrc from '../assets/patient-care-report.png'
---
- 30,000,000 PCRs filled out per year, many by hand
- Written in emergency situations, in-ambulance
- Mistakes can be fatal (did they write 100mg or 160mg?)
---
A software version exists, and it's better in every measurable way, but nobody uses it.
---
The machine it runs on is low-powered, and every input comes with a 250ms delay.
---
# Input latency tools
In React, the most common cause for input latency is wasteful renders.
- `React.memo()`
- `shouldComponentUpdate`
---
# Resources
- ["React.memo() for Functional Components", from scotch.io](https://scotch.io/tutorials/react-166-reactmemo-for-functional-components-rendering-control)
- [Official docs](https://reactjs.org/docs/react-api.html#reactmemo)
---
Profiling is your friend.
---
# What about animations?
---
Is this as important?
---
Animations serve many purposes, but a big one is making your app feel tangible / "real".
---
# Standards are higher than ever
---
# 📱 vs 🕸️
---
## Question
Guess how large the Facebook mobile app is?
---
export default LightSlide
import facebookAppSize from '../assets/fb-app-size.jpg'
---
import mario64Src from '../assets/super-mario-64.jpg'
Mario 64 was 32 megabytes.
---
### Think about how much friction app installs are...
- Find the app in the App Store
- Try and remember your App Store password
- Download hundreds of megabytes
- Wait for it to install
- Figure out where the app icon went
- Wait for it to open
---
### Why does anyone use mobile apps?
---
Many reasons, but I think a big one is that they're nice to use.
---
# "User Experience"
---
import mattPerryDevSrc from '../assets/matt-perry-dev.jpg'
import chantasticSrc from '../assets/chantastic.jpg'
---
# Relevance
---
AOL -> web
---
The web is an amazing open platform.
---
import codesandboxNetlifySrc from '../assets/codesandbox-netlify.jpg'
---
The web is _low-friction_ both for consumers and developers.
The web is content-rich because of it.
---
In order to keep the web relevant, we need to match the UX of native apps.
This is where animation performance comes in.
---
---
[Bootstrap Accordion example](https://getbootstrap.com/docs/4.0/components/collapse/#accordion-example)
---
import greenPixelsSrc from '../assets/green-pixels.mp4'
The Pixel Pipeline
---
import pixelPipelineSrc from '../assets/pixel-pipeline.jpg'
export default LightSlide
---
Properties like `background-color` don't trigger layout.
---
export default LightSlide
import cssTriggersSrc from '../assets/csstriggers.png'
[https://csstriggers.com/](https://csstriggers.com/)
---
We should rely primarily on two properties that can skip layout _and_ paint:
`opacity` and `transform`
---
# A better accordion?
---
We can't build _exactly_ that animation, but we can build something close.
---
import AccordionExample from '../src/components/Accordion/Accordion.example.js'
---
export default props => (
)
---
export default props => (
)
---
### `will-change`?
`will-change` is a way to let the browser know to optimize a transition.
It can help a lot, but it's a tradeoff with memory ⚖️
---
# Don't be afraid to break the rules\*
\*As long as you're profiling!
---
import khanMenu from '../assets/khan-menu.gif'
---
---
import Tweet from '../src/components/Tweet/Tweet.managed'
---
import LikeButton from '../src/components/LikeButton/LikeButton.managed'
---
import likeBeforeSrc from '../assets/like-before.png'
---
## It runs on the main thread.
[Perf test](https://codepen.io/joshwcomeau/pen/yrPzWO)
---
# Options
- Less particles
- Use CSS transitions
- Sprites
---
import likeSpriteSrc from '../assets/like-sprite.png'
export default LightSlide
---
import LikeSprite from '../src/components/LikeSprite'
export default LightSlide
---
export default props => (
)
---
export default LightSlide
import spritePerfSrc from '../assets/sprite-perf.png'
---
# Fun fact
This is actually how Twitter does it!
---
# Tools
- [GIPHY Capture](https://giphy.com/apps/giphycapture)
- [EZGif](https://ezgif.com/gif-to-sprite)
- Photoshop (or similar)
---
---
# So I built a thing
[Tinkersynth](https://tinkersynth.com)
---
import tinkersynthYikesSrc from '../assets/tinkersynth-yikes.mp4'
---
# The forgotten hero:
Web Workers
We can do all of the art calculations in a separate thread.
---
"When should you be using Web Workers?", by Surma
---
# The trusty sidekick:
OffscreenCanvas
OffscreenCanvas allows you to _paint to a canvas_ from _within a web worker_.
---
import offscreenCanvasSupportSrc from '../assets/offscreen-canvas-support.png'
:(
---
⏰
---
# Conclusion
---
## People hate pages that take forever to load
---
## People hate pages that don't respond swiftly to interactions
---
## People hate choppy, stuttery animations
---
# Context matters
If you're building an Amazon competitor, it makes sense to prioritize page-load above all else.
For other apps? It depends.
---
Test your product on low-powered devices, and see where the pain points are.
---
Start analyzing the products you use every day.
---
All **resources, links, and code samples** available on Twitter:
{'@JoshWComeau'}
(Don't forget: cats!)
##### Thank you!