Skip to content
/ urlhub Public

Yet another router library, but the simplest one.

License

Notifications You must be signed in to change notification settings

arqex/urlhub

Repository files navigation

UrlHub: Yet another router library, but the simplest one

Build Status npm version

Is another new routing library needed? Probably not, UrlHub is a router that make the work like any other javascript routing library. The difference is that UrlHub is SIMPLE, it's made to be understood completely just by reading this file.

Installation

npm install urlhub

Translating URLs to other things

Think of UrlHub as a library to translate URLs into something else (that's a nice definition for a router). Let's create a test router.

var urlhub = require('urlhub');
var pushStrategy = require('urlhub/pushStrategy');

var routes = [
  {path: '/home', cb: 'Sweet Home'},
  {path: '/users', cb: 'Users screen', children: [
    {path: '/:userId', cb: 'SingleUser'}
  ]}
];

var router = urlhub.create( {strategy: pushStrategy} );
router.setRoutes( routes );
router.start();

The router has been defined with 3 routes:

  • /home
  • /users
  • /users/:userId (Child of /users)

The cb (named after callback) attribute is what the router returns when a url matches one of the defined routes. With the example above we are translate URLs into strings.

location = router.match('/home');
// location.matches will be ["Sweet Home"]

location = router.match('/users/937264923');
// location matches will be ["Users screen", "SingleUser"]

The matches attribute is the translation of the URL. Since we defined the "/home" route with the string "Sweet home" as its cb, we get that same string back when there is a match on that route. Nested routes will match all the parent routes, that's why the matches attribute is an array.

router.match returns much more useful information from the url:

location = router.match('/users/937264923?foo=bar#my_hash');
/* location value will be:
{
  hash: "#my_hash",
  matches: ["Users screen", "SingleUser"],
  matchIds: ["/users/", "/users/:userId], 
  params: {userId: "937264923"},
  pathname: "/users/937264923",
  query: {foo: 'bar'},
  route: "/users/:userId",
  search: "?foo=bar"
}
*/

As you can see, UrlHub does nothing else than parsing and translating URLs. If we give it a string as cb it will be returned on a URL match, but you'd probably want to pass a function as cb to be executed after the match, or a React component in order to display it after routing.

Detecting URL changes

The second nice feature that any router must have is detecting changes in browser's location to react properly to them. That's why we need a routing strategy: the mechanism to define what is a URL change, and how to navigate without a page refresh.

There are 2 routing strategies shipped with UrlHub, the HTML5's pushState strategy, and the Hash strategy, that updates the URL's hash to navigate. Both strategies are used in the same way by urlhub:

We create our router like this:

var urlhub = require('urlhub');
var hashStrategy = require('urlhub/hashStrategy');

var router = urlhub.create( {strategy: hashStrategy} );
router.setRoutes( routes );
router.onChange( function( location ){
  // The location object is the same returned by the `match` method.
  // This will be triggered by any change in the browser's URL.
  // We can load our content here depending on the route match.
});

// Start listening to URL changes
router.start();

Navigating

UrlHub come with some useful methods to let the developers navigate programmatically without hassle.

// Go to the `/users` path
router.push('/users');

// Replace current location in history by `/users/874922`
router.replace('/users/874922')

// It's possible to use partial location objects to update the route
router.push({query: {foo: 'anotherBar'}})

Intercepting route changes

A nice feature in urlhub is the ability of preventing route changes by using the onBeforeChange hook. Imagine that our app has some route '/restricted' that can only be accessed for users that are logged in, we can add this restriction easily:

// The hook function receives the next route as a location object
router.onBeforeChange( function(location){
  if( location.pathname === '/restricted' && !userIsLoggedIn() ){
    // In this case we go to the login screen
    return '/login';
  }

  // In any other case, don't intercept the route
  return location;
})

What else?

That's basically all the functionality. This is still a work in progress, still need:

  • Document the API and options.
  • There is a Link React component shipped. Document it.
  • How to use in node.js without a browser.
  • Write an article to make clear all the advantages.

License

MIT licensed