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.
npm install urlhub
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.
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();
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'}})
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;
})
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.