Next.js Dynamic Routing with Cloudflare Pages
Created 2021-8-3
Related to 0 projects.
Maybe you want to meme around with the new JAMStack "innovation" or whatever. Anyways, for some reason, you decided to use Next.js in Cloudflare Pages.
Now then, Next.js has dynamic routing... This means that /whatever/[id].js
will get requests from both /whatever/blah
and /whatever/foo
. Obviously,
this is not great for something like Cloudflare Pages, which statically serves
your pages.
However, upon reading the documentation, you find out that Pages supports
Single Page Applications! All you have to do is uh, not have a 404.html
page
in the output, and any 404-ing requests will be redirected to your index page!
Okay, so this seems simple............. WHAT DO YOU MEAN NEXT.JS DOESN'T SUPPORT A SINGLE PAGE APPLICATION OUTPUT???!? I'm switching to Nuxt.
...
...
...
Still with me? Let's figure this out of pure stubbornness, and because my self-hypnosis to like Next.js worked. So, what's the game plan?
Well, Cloudflare Pages supports Cloudflare Workers, and I know that actually
the dynamic url can be accessed at /whatever/[id]
even in Pages. So, maybe I
can redirect /whatever/:id
to /whatever/[id]
, and it will just work?
Okay then, let's do this!
Once you've made a Page and set it up a custom domain (I'll be using
pages-test.helvetica.moe
as mine), install wrangler as in the Cloudflare
documentation.
Now, you can get started with your worker with wrangler generate <folder name to create>
, or wrangler init
in an already made folder. Here's what I've
personally configured the worker as: (wrangler.toml
)
name = "next-dynamic-worker"
type = "webpack"
workers_dev = false
route = "pages-test.helvetica.moe/some/dynamic/route/*"
zone_id = "your zone id"
Make sure to wrangler auth
, and then the actual worker code can be written.
The main library to note is itty-router
, which you can install with npm i itty-router
.
Essentially, at this point, the boilerplate index.js
should be:
import { Router } from 'itty-router'
const router = Router();
router.all('/some/dynamic/route/:param', async (request) => {
// this part is coming soon:tm:
return new Response('responding from the worker!');
})
addEventListener('fetch', event => {
event.respondWith(router.handle(event.request));
});
Now, make sure to deploy your worker with wrangler publish
, and then
redeploy the pages application (for some reason new workers changes only pop
up after a deploy???). Then, visiting
https://your-page.whatever/some/dynamic/route/blah
should respond with
responding from the worker!
. If it doesn't, well, you're on your own here :-)
Now, the rest is easy. All that needs to be done is editing the url that is used, and returning the response from that. Here's what I did:
const url = new URL(request.url);
// (replace "param" with whatever your parameter is called)
url.pathname = '/some/dynamic/route/[param]';
const newRequest = new Request(url, request);
return await fetch(newRequest);
Cool! Now, just wrangler publish
again, redeploy the pages application (
:( ), and it should just work!
Mentions around the web
Mentioned 0 times!