Skip to content
Dashboard

How we made the Vercel Dashboard twice as fast

Techniques and strategies we used to optimize your Dashboard for better UX.

Link to headingOptimize what matters most

Improving page performance leads to better user experience and lifts SEO.Improving page performance leads to better user experience and lifts SEO.
Improving page performance leads to better user experience and lifts SEO.

Link to headingTools to guide you

Vercel Top Paths show the heaviest asset payloads being used in your project.Vercel Top Paths show the heaviest asset payloads being used in your project.
Vercel Top Paths show the heaviest asset payloads being used in your project.

Link to headingYour page–faster

Link to headingJavaScript

// Create a cache using an empty object
const slugifyCache = { }
const cachedSlugify = (text: string) => {
// If this value has already been computed,
// it will be a property on the cache object.
if (slugifyCache[text]) {
return slugifyCache[text]
}
// If this is the first time we are seeing this string,
// we will store it in our cache and return the slug.
return (slugifyCache[text] = slugify(text))
}

const useInViewport = (ref: any) => {
const [isInViewport, setIsInViewport] = useState(false)
const [isLoaded, setIsLoaded] = useState(false)
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsLoaded(true)
}
setIsInViewport(entry.isIntersecting)
}
)
if (ref.current) {
observer.observe(ref.current)
}
}, [ref])
return isInViewport || isLoaded
}

const HeavyChildComponent = () => {
return (
<div>
<p>I am a heavy component!</p>
</div>
)
}
const ParentComponent = () => {
const childRefContainer = useRef(false)
const isRendered = useInViewport(childRefContainer)
return (
<>
<div style={{height: "200vh"}}></div>
<div ref={childRefContainer as any}>
{ isRendered && <HeavyChildComponent /> }
</div>
</>
)
}

// Before
// This line imports the entire Sentry package!
import Sentry from '@sentry/nextjs'
// After
// Only bring in the code that it needs.
import { captureException } from '@sentry/nextjs'

Link to headingHTML + CSS

// Before
const Paragraph = (props) => {
return (
<div>
<p>{ props.children }</p>
</div>
)
}
// After
const Paragraph = (props) => {
return (
// No more wrapper div! The p tag already defaults to display: block;
// so this change won't change the final render.
<p style={{ props.style }}>{ props.children }</p>
)
}

// Before
const ImageWithCaption = (props) => {
return (
<figure>
// Image source is way too large for mobile!
<img src="./images/sample-img.png" alt="This is a sample image!" />
<figcaption>{props.figCaption}</figcaption>
</figure>
)
}
// After
import Image from "next/image"
const ImageWithCaption = (props) => {
return (
<figure>
// Delivers correct size for user
<Image
src="./images/sample-img.png"
alt="This is a sample image!"
layout="responsive"
width={200}
height={100}
/>
<figcaption>{props.figCaption}</figcaption>
</figure>
)
}

@font-face {
font-family:'Inter';
src:url('Inter.woff2')format('woff2')tech('variations'),
url('Inter')format('woff2-variations');
font-weight: 100 1000; // Range for declarations of the property
font-stretch: 25% 150%;
}

// Before
const ReusableSection = ( props ) => {
return (
// Setting 0 for the margin is the browser default.
// This will have no styling effect,
// but it will add bloat to your final HTML.
<div style={{ marginTop: props.marginTop || 0 }}>
<p style={{ paddingBottom: props.paragraphBottomPad || 0 }}>
{props.paragraph}
</p>
</div>
)
}
// After
const ReusableSection = (props) => {
return (
// This style tag will no longer be a part of your final HTML.
<div style={{ marginTop: props.marginTop || undefined }}>
<p style={{ paddingBottom: props.paragraphBottomPad || undefined }}>
{props.paragraph}
</p>
</div>
)
}

Link to headingUse data to improve user experience

Vercel Analytics show how your application is performing over time for real users.Vercel Analytics show how your application is performing over time for real users.
Vercel Analytics show how your application is performing over time for real users.