Remix is fast by default, but with a few edits to root.tsx, you can make it even faster!

For a refresher on Core Web Vitals, check out the free course from WebPageTest:

https://i.nalu.wiki/X9Y-tlBlt8UzTt_9gE0rB.png

There's no magic here: Remix simply makes it easy to implement good practices that would work on any website.

Unblocking CSS

In Remix, we usually add CSS as stylesheet links:

import styles from "~/styles/dashboard.css";
export const links: LinksFunction = () => {
return [
{ rel: "stylesheet", href: styles }
]
}

However, doing this makes stylesheets a render-blocking resource:

Stylesheets are render-blocking by default

By default, HTML rendering is paused until CSS stylesheets have streamed in!

Fix this behavior by linking the stylesheets as preloaded resources first:

This ensures they are available earlier and are less likely to block the page's render, improving performance.

Your updated links export should look something like this:

import styles from "~/styles/dashboard.css";
export const links: LinksFunction = () => {
return [
{ rel: "preload", href: styles, as: "style" },
{ rel: "stylesheet", href: styles },
]
}

How the links export looks on Nalu's app/root.tsx file:

import tailwindStylesheetUrl from "~/styles/tailwind.css";
import fonts from "~/styles/fonts.css";
import rootStyles from "~/styles/root.css";
import balloonCSS from "~/styles/balloon.min.css";
export const links: LinksFunction = () => {
return [
{ rel: "preload", href: tailwindStylesheetUrl, as: "style" },
{ rel: "preload", href: fonts, as: "style" },
{ rel: "preload", href: rootStyles, as: "style" },
{ rel: "preload", href: balloonCSS, as: "style" },
//Preload CSS to makes it nonblocking
{ rel: "stylesheet", href: tailwindStylesheetUrl },
{ rel: "stylesheet", href: fonts },
{ rel: "stylesheet", href: rootStyles },
{ rel: "stylesheet", href: balloonCSS },
];
};

Preconnecting resources

Everything hosted outside your app's domain requires a separate handshake, but you can speed up that process with preconnect links.

Preconnect 3rd party domains to avoid delay.

WPT Report provides a list of content domains used by your website.

https://i.nalu.wiki/MdClzW8PT78Q66DxvKUNV.png

Based on the report, we can add the following to app/root.tsx:

export const links: LinksFunction = () => {
return [
//Pre-connect CDN to improve first bits
{ rel: "preconnect", href: "https://core-cdn.nalu.wiki"},
{ rel: "preconnect", href: "https://wiki-cdn.nalu.wiki"},
{ rel: "preconnect", href: "https://clerk.nalu.wiki"},
{ rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous"},
]
}

The crossOrigin attribute is necessary when loading third-party fonts, see Michael Crenshaw article for details.

Preconnects are not free.

Don't pre-connect to domains unless it'll be used within 10 seconds of request!

Third-Party Scripts

Third-Party Scripts really slow you down. Delete them if you can!

Try the following if that's not an option:

  • Light Alternatives: On Nalu, we used self-hosted Plausible.js for analytics instead of Google Analytics.
  • Off-load the Work: Move long-running script to a Web Worker with Partytown to unblock your site's main JS thread.
  • Defer: Add defer tag to the <script> to lower its Browser priority.

How analytics look on Nalu:

<script
defer
data-domain="nalu.wiki"
src="https://a.nalu.media/js/plausible.js"
/>

Additionally, we also add third-party domains (see above) to further reduce the impact on our users.

Optimizing Fonts

Optimizing Fonts is an important topic that deserves a follow-up article:

Using Fonts in Remix
By xhomu
Using Fonts in Remix

Further Reading

Web Optimization could easily be a developer's full-time job. Hopefully, these tips will help clear some low-hanging fruits.

Fixing Dependency Errors in Remix
By xhomu
Fixing Dependency Errors in Remix

I'll like to acknowledge Sergio Xalambrí and Tiger Abrodi for their help and support in the development of this post.

Hang out with these cool people on the Remix Discord!

What is Nalu?

Nalu is a wiki engine built on Remix and MDX.

Why create content on Nalu?
By pogseal
Why create content on Nalu?