-
Notifications
You must be signed in to change notification settings - Fork 0
Routing
This is a simple function that takes in a Request
returns a Response
function handle(request: Request) {
return new Response('Hello world!');
}
Let's serve it with an imaginary function
serve(handle);
And open it in the browser
🌐 Browser |
---|
Hello world! |
💥 We have a server!
When our website starts growing and we need more routes we could use a switch/case
function handle(request: Request) {
const url = new URL(request.url).pathname;
switch (url) {
case '/':
return new Response('Home');
case '/about':
return new Response('About');
}
}
Then there are dynamic routes, maybe its better to use if/else
s, they are more versatile
const urlPattern = new URLPattern({
pathname: '/:postId',
});
function handle(request: Request) {
const url = new URL(request.url).pathname;
if (urlPattern.test({ pathname: url })) {
const { postId } = urlPattern.exec({ pathname: url })!.pathname.groups;
return new Response(`Post #${postId}`);
}
}
This is starting to get very messy!
Let's organize it by moving each route into their own function
function index() {
return new Response('Home');
}
function about() {
return new Response('About');
}
function post(url: string, urlPattern: URLPattern) {
const { postId } =
urlPattern.exec({ pathname: url })!.pathname.groups;
return new Response(`Post #${postId}`);
}
And update handle
function handle(request: Request) {
const url = new URL(request.url).pathname;
switch (url) {
case '/':
return index();
case '/about':
return about();
}
if (urlPattern.test({ pathname: url })) {
return post(url, urlPattern);
}
}
Better, but what if we defined this with an array instead?
const routes = [
{
url: '/',
handler() {
return new Response('Home');
},
},
{
url: '/about',
handler() {
return new Response('About');
},
},
{
url: '/:postId',
handler(url: string, urlPattern: URLPattern) {
const { postId } =
urlPattern.exec({ pathname: url })!.pathname.groups;
return new Response(`Post #${postId}`);
},
},
];
It's ok, but each function is nested more than it needs to, we could use Array.push
to dynamicly add our routes and fix that
routes.push({
url: '/',
handler() {
return new Response('Home');
},
});
🧼 Looking clean! But we can do better!
Let's create a Router
class with a custom push method
class Router {
#routes: string[] = []
push(url: string, handler: () => Response) {
this.#routes.push({ url, handler })
}
}
And use it!
const router = new Router()
router.push('/', () => {
return new Response('Hello world!')
})
Maybe this should only work for get request, let's add a method for that... now we can do this
const router = new Router()
router.get('/', () => {
return new Response('Hello world!')
})
Just need to write a new Router.handle
and we good to go, awesome!
Relax router does this plus much more!