Nagibaba / sw-routes

Just playing with some ideas

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

sw-routes

A basic router for service worker fetch events.

npm install sw-routes

This library is designed to be used with an ES6-aware bundler like Webpack or Rollup, but there's also a prebuilt version.

Guide

Creating a router

import Router from 'sw-routes';

const router = new Router();

// Add your routes

router.addFetchListener();

If you don't want sw-routes to write the fetch listener for you, see router.handle.

Adding routes

Routes are created using:

router.get(path, ...handlers);
// or
router.get(...handlers);

.get only handles GET requests. There is also .post, .put, .delete for other HTTP methods, and .all for all methods.

Paths can contain regex & patterns.

In their simplest form, handlers are just functions:

router.get('/whatever/', async fetchData => {
  try {
    const response = await fetch(fetchData.request);
    if (!response.ok) throw Error('Not ok');
    return response;
  }
  catch (err) {
    return caches.match('/error-page');
  }
});

Functions are "request handlers", and are called in sequence until one provides a response, or a promise for a response (as above).

For details on fetchData, see the API docs.

Handlers

sw-routes provides many common handlers. For instance, if you wanted to respond from the cache, falling back to the network:

import { fromCache, fromNetwork } from 'sw-routes/handlers';

router.get(fromCache(), fromNetwork());

If you want to respond from the network, falling back to the cache, just flip the handlers around:

router.get(fromNetwork(), fromCache());

Here are all the handlers sw-routes provides:

  • fromCache – Try to get a response from a cache. It can be a specific item, or one that matches the current request.
  • fromNetwork – Try to get a response from the network.
  • fromPreload – Use any preloaded response.
  • ifMethod – Only run subsequent handlers if the request uses a particular HTTP method. This is what .get etc use internally.
  • ifNavigation – Only run subsequent handlers if the request is a page navigation.
  • ifUrl – Only run subsequent handlers if the request matches a particular URL. If you pass a string as the first argument to .get etc, it's passed to this.
  • race – Race a number of handlers. First one to provide a response wins.
  • sequence – Shortcut for creating a sub-router.
  • toCache – Add the response to a cache (unless it came from the cache).
  • updateCache – Add the response to a cache. If it came from the cache, fetch a fresh copy instead.
  • wait – Add an artificial delay. This is useful for creating timeouts.

Writing your own handler

When creating handlers, bare functions are "request handlers", but there are other types, such as "conditional handlers":

import { conditionalHandler } from 'sw-routers/handler-types';

router.get(conditionalHandler(data => {
  return data.request.mode == 'no-cors';
}), fromNetwork());

Here are all the types:

  • requestHandler – Called if a response hasn't been provided yet. Can return a response.
  • responseHandler – Called if a response has been provided. Can return a different response.
  • anyHandler – Called whether a response has been provided or not. Can return a response.
  • responseWaitUntilHandler – Called if a response has been provided. Runs asynchronously. Useful for doing something with the response such as caching.
  • waitUntilHandler – Called whether a response has been provided or not. Runs asynchronously. Useful for doing bookkeeping & clean-up work.
  • conditionalHandler – Skips subsequent handlers in the sequence if it returns false.
  • errorHandler – Called if a previous handler threw an error or rejected. Can return a response.

API

Router

import Router from 'sw-routes';
const router = new Router();

router.all/get/post/put/delete

Create and add a sub-router with handlers.

router.get(urlPattern, ...items);
router.get(...items);
  • urlPattern: Becomes a conditional handler using ifUrl.
  • items: One or more handlers or sub-routers.

all handles requests of all HTTP methods, whereas get etc handle requests of specific HTTP methods.

router.add

Add items to the current router. This is useful for adding catch-all handlers.

router.add(...items);
  • items: One or more handlers.

router.addFetchListener

Adds a fetch listener which uses the router to handle fetches.

router.addFetchListener();

router.handle

Process a fetch event and return a response.

const response = await router.handle(data);

This is useful if you need to add your own fetch event logic around the router:

addEventListener('fetch', event => {
  // Your code goes here.
  event.respondWith(async function() {
    // Maybe more of your own code?
    const response = await router.handle(event);
    // Some more of your own code, perhaps?
    return response; // or maybe something else!
  }());
});

FetchData

An instance of FetchData is given to each handler.

Its has the following properties from the fetch event.

  • request
  • preloadResponse
  • clientId
  • waitUntil

But also:

  • url: A parsed version of request's URL.
  • error: The error thrown by a previous handler.
  • response: The response provided by a previous handler.
  • params: Params from the URL match.

Prebuilt version

dist/index.js.

Router is exposed on the global. Handlers are exposed as Router.handlers, and handler types are exposed as Router.handlerTypes.

About

Just playing with some ideas


Languages

Language:TypeScript 54.0%Language:JavaScript 45.7%Language:HTML 0.3%