Single-page applications like ReactJS are pretty popular, and you can get them to work with static sites too. But because the JAMstack is serverless, you'll need to do a few URL rewrites to keep your SPA routes working and avoid the dreaded "404 - Page Not Found" error.
Here's how I set things up on Cloudflare Pages.
If your whole static site is a SPA
If your entire Cloudflare Pages static site is a SPA, you are good to go out of the box. Seriously, you are done - there's no need to go any further!
Here's why...
If you've put a ReactJS app or another SPA on Netlify before, you will probably have done something like this in your _redirects
file:
/* /index.html 200
This is a documented rewrite rule for handling single-page apps in Netlify.
But you don't need this rule in Cloudflare Pages.
That's pretty cool if your whole website is a SPA. Nothing to do, just deploy your site as-is. But what if it's not?
The beauty of the rewrite rule in Netlify is that your entire site doesn't need to be a SPA for it to work. And that's not the case for Cloudflare Pages (yet).
If part of your static site is a SPA
Let's imagine you have a website with a bunch of static pages, and a ReactJS app running from app.html.
├── css/ 📁
├── js/ 📁
├── about.html 📄
├── app.html 📄 <--- SPA
├── contact.html 📄
├── index.html 📄
└── pricing.html 📄
If you visit /app
and start navigating around your ReactJS application, you might be fooled into thinking everything is working.
🚨 News flash - it isn't.
If you hit refresh in your browser on a client-side route, like /app/dashboard
, you'll get a "404 - Page Not Found" error.
So what's happening?
Well when you go to /app
, your ReactJS (or other SPA) loads up and takes care of the routing. But when you hit refresh, the static site tries to find /app/dashboard.html
- and that doesn't exist as a static page.
You need to pass that URL request back to app.html
(your SPA) to handle it.
Remember that rewrite rule we created earlier in _redirects
? We need another version of that!
You can create a rewrite proxy so that any routes starting with /app
(e.g. /app/dashboard
, /app/login
, /app/register
etc) get shown app.html
so that React Router (or your other front-end router of choice) can handle the routing.
/app/* /app.html 200
And this works... in Netlify.
But we're not talking about Netlify today, we are supposed to be talking about Cloudflare Pages.
And this should work in Cloudflare too. And it will do soon - according to the docs. So if you're reading this blog a few weeks/month in the future, by all means, give it a go!
For a while, Cloudflare Pages _redirects
didn’t support proxying. And while it does now (according to the docs), at the time of writing this post - it wasn't working in production yet. At least, not with dynamic routes. So I couldn't handle a partial SPA static site in Cloudflare Pages _redirects
.
That doesn't mean you can't get a partial SPA to work in Cloudflare, you absolutely can. And here's how...
SPA routing with transform rules
Until the rewrites start working in Cloudflare Pages (which should be soon), you can use transform rules to handle the rewrite instead.
Cloudflare has some pretty flexible route handling, and URL rewrite is exactly what we need.
Don't worry if you are on the free plan, you get 10 transform rules included, and you are only going to need to use one to get this to work!
Here's what you need to do:
- In Cloudflare, head to Rules > Transform Rules
- Click Create rule
- Create the transform rule
☑️ Custom filter expression
Hostname
equals
www.yoursite.com
And
URI Path
starts with
/app/
Then
☑️ Rewrite to... Static
/
app
This would be if your ReactJS/SPA is at the route /app
in your static site. If it's somewhere else, like /user
replace app
with user
in the settings above.
Click Save
Ta-da! Now your SPA works on Cloudflare Pages.