https://github.com/funcool/bide
A simple routing library for ClojureScript
https://github.com/funcool/bide
clojurescript html5 html5-history routing
Last synced: 4 months ago
JSON representation
A simple routing library for ClojureScript
- Host: GitHub
- URL: https://github.com/funcool/bide
- Owner: funcool
- License: bsd-2-clause
- Created: 2016-08-27T07:22:37.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2021-05-02T19:23:41.000Z (over 4 years ago)
- Last Synced: 2025-09-03T22:41:35.461Z (4 months ago)
- Topics: clojurescript, html5, html5-history, routing
- Language: JavaScript
- Size: 124 KB
- Stars: 132
- Watchers: 10
- Forks: 20
- Open Issues: 5
-
Metadata Files:
- Readme: README.adoc
- Changelog: CHANGES.md
- License: LICENSE
Awesome Lists containing this project
README
= bide
:sectlinks:
image:http://clojars.org/funcool/bide/latest-version.svg["Clojars Project", link="http://clojars.org/funcool/bide"]
== Introduction
A simple routing library for ClojureScript that uses Express-like syntax.
[quote, A Basque proverb.]
____
Egiak ez ditu bi bide
____
NOTE: **Looking for a maintainer.**
== Install
Add the following dependency to your `project.clj` file:
[source,clojure]
----
[funcool/bide "1.7.0"]
----
== User Guide
Just import the core namespace and start building the router:
[source, clojure]
----
(ns myapp.core
(:require [bide.core :as r]))
(def router
(r/router [["/api/auth" :myapp/auth]
["/api/users/:id" :myapp/user-by-id]]))
----
Now, you can perform basic operations such as `match` and `resolve`:
[source, clojure]
----
(r/match router "/api/auth")
;; => [:myapp/auth nil nil]
(r/match router "/api/users/1")
;; => [:myapp/user-by-id {:id "1"} nil]
(r/match router "/api/users/1?foobar=1")
;; => [:myapp/user-by-id {:id "1"} {:foobar "1"}]
(r/match router "/api/other")
;; => nil
(r/resolve router :myapp/auth)
;; => "/api/auth"
(r/resolve router :myapp/user-by-id {:id 2})
;; => "/api/users/2"
(r/resolve router :myapp/user-by-id {:id 2} {:foobar 1})
;; => "/api/users/2?foobar=1"
----
In addition, you can integrate it in your ClojureScript web application using
the provided builtin helpers. It uses `goog.History` API under the hood:
[source, clojure]
----
(defn on-navigate
"A function which will be called on each route change."
[name params query]
(println "Route change to: " name params query))
(r/start! router {:default :myapp/auth
:on-navigate on-navigate})
----
Also, you can pass factory function that returns instance of
`goog.history.Html5History` as value of `:html5history` key of second argument
and `bide` would use it to manage history events, and/or pass `true` as value of
`:html5?` key to stop using '#' in URLs.
Note that when `:html5?` is `true`, the built-in instance of `Html5History` uses
a custom `goog.history.Html5History.TokenTransformer` to allow it to handle
query parameters. You can construct a transformer with `token-transformer`.
Finally, you can force the navigation trigger by using the `navigate!` helper
function:
[source, clojure]
----
(r/navigate! router :myapp/user-by-id {:id 10})
----
Or if you don't want to add entry into history use `replace!` helper function
instead.
== How to Contribute?
Just open an issue or PR ;)
== FAQ
=== Why another routing library?
Existing solutions out there are complex and generally bloated wih irrelevant
documentation.
Most libraries work with native Clojure data structures for representing the
routing configuration. It's a great idea, but it does not work very well once
your project scales. Things get out of hand pretty fast.
An example of this with link:https://github.com/juxt/bidi[bidi] routing library:
[source, clojure]
----
(def routes
["/" [["auth/login" :auth/login]
[["auth/recovery/token/" :token] :auth/recovery]
["workspace/" [[[:project-uuid "/" :page-uuid] :workspace/page]]]]])
----
The mental effort required to read and understand the configuration defined like this
is considerable. Now, let's see an example using *bide*:
[source, clojure]
----
(def routes
[["/auth/login" :auth/login]
["/auth/recovery/token/:token" :auth/recovery]
["/workspace/:project-uuid/:page-uuid" :workspace/page]])
----
As you can imagine, a simple library like *bide* does not offer all the features
provided by other solutions. New features will be added on-demand. However, we plan
to stay as *small and simple* as possible.
== How fast is *bide*?
Before talking about real performance comparisons and benchmarks, you
should know that *bide* design is very simple and maybe can be considered
naive. The worst case for the matching algorithm is *O(N)* and *O(1)*
for resolve operation.
Considering that having thousands of entries is very unlikely to happen,
the match algorithm works pretty well. This is a comparison against the
same operations with link:https://github.com/juxt/bidi[bidi]:
[source, text]
----
$ node out/benchmarks.js
op=resolve lib=bidi ops=10000
"Elapsed time: 90.989215 msecs"
op=resolve lib=bide ops=10000
"Elapsed time: 19.447844 msecs"
op=match lib=bidi ops=10000
"Elapsed time: 1070.330668 msecs"
op=match lib=bide ops=10000
"Elapsed time: 98.864120 msecs"
----
I've been a _bidi_ user for quite some time, that's why I choose this library to
run the benchmarks.
== License
_bide_ is licensed under BSD (2-Clause) license.