Routing with Generator Functions

Library used: yieldparser

Approach A: Components return values

import { parse, mustEnd } from 'yieldparser';

function* Home() {
  yield '/';
  yield mustEnd;
  return { type: 'home' };
}

function* Blog() {
  yield '/blog';
  yield mustEnd;
  return { type: 'blog' };
}

function* BlogPost() {
  yield '/blog/';
  const postID = yield /[-_\w]+/;
  yield mustEnd;
  return { type: 'blogPost', postID };
}

function* Route() {
  return yield [Home, Blog, BlogPost];
}

function handleRequest(request) {
  const url = new URL(request.url);
  const route = parse(url.pathname, Route());
  if (!route.success) {
    return new Response(`Not found: ${url.pathname}`, { status: 404 });
  }

  if (route.value.type === 'home') {
    return renderHomePage();
  } else if (route.value.type === 'blog') {
    return renderBlogList();
  } else if (route.value.type === 'blogPost') {
    return renderBlogPost(route.value.postID);
  }
}

Approach B: Components return fetch functions

import { getHomeContent } from './home';
import { listPosts, findPost } from './blog';
import { renderHTMLPage, renderHTMLList } from './html';

function* Home() {
  yield '/';
  yield mustEnd;

  return () => renderHTMLPage('Home', getHomeContent());
}

function* Blog() {
  yield '/blog';
  yield mustEnd;

  return async () => {
    const posts = await listPosts();
    return renderHTMLPage('Blog', renderHTMLList(posts));
  };
}

function* BlogPost() {
  yield '/blog/';
  const postID = yield /[-_\w]+/;
  yield mustEnd;

  return async () => {
    const post = await findPost(postID);
    return renderHTMLPage(post.title, post.contentHTML);
  };
}

function* Route() {
  return yield [Home, Blog, BlogPost];
}

async function handleRequest(request) {
  const url = new URL(request.url);
  const route = parse(url.pathname, Route());
  if (!route.success) {
    return new Response(`Not found: ${url.pathname}`, { status: 404 });
  }

  const html = await route.value;
  return new Response(html, {
    status: 200,
    headers: new Headers({ 'content-type': 'text/html;charset=UTF-8' })
  });
}