Orientation Arc
Routing Algorithms
Rendering and JSX
Runtime Adapters
Middleware Ecosystem
Developer Helpers
System Utilities
The following files were used as context for generating this wiki page:
The SmartRouter is a high-level orchestration component in the Hono framework designed to bridge the gap between multiple underlying routing strategies. Rather than forcing a singular routing algorithm (like a Trie or Regular Expression) onto all developers, it acts as a dynamic, "smart" proxy that enables Hono to optimize its routing performance based on the actual usage patterns of an application.
The core problem addressed by SmartRouter is the selection of the most efficient routing mechanism. Different routers perform optimally under different conditions (e.g., Trie-based routers often excel at static lookups, while RegExp-based routers offer flexibility for complex patterns). SmartRouter achieves this by maintaining an internal list of candidate routers and deferring the definitive choice until the first request is matched.
Upon the first request, the component iterates through its configured router implementations, attempting to register all previously queued routes sequentially into each candidate. The first router to successfully process the full routing table for the given request context is selected as the "active" router. Subsequent requests bypass the initialization logic entirely, essentially hot-swapping the SmartRouter instance with the performance-proven candidate.
SmartRouter functions as a wrapper that implements the standard Router interface, yet hides a sophisticated "activation" phase. Its design follows a "fail-safe and promote" pattern: it maintains a list of candidate routers provided via configuration and, on the first call to match, attempts to populate them until one succeeds.
The mechanism uses a deferred routing strategy:
add calls (for registering routes) are buffered in a local private #routes array.match method, when called for the first time, performs a "build" operation.routers list, calling add for every buffered route on each candidate.Important
The SmartRouter guarantees that the router chosen is capable of handling the entire existing route set, not just the single request that triggered the selection. This ensures that the state consistency of the routing table is preserved across the transition from buffer to execution.
Sources: src/router/smart-router/router.ts:4-32
SmartRouter is typically instantiated within the Hono constructor. By default, it is configured with a prioritized list (e.g., RegExpRouter followed by TrieRouter). This allows the system to attempt the most performant or generic router first.
Sources: src/hono.ts:28-32
The most complex logic within SmartRouter is the first-match orchestration. The control flow is explicitly designed to handle potential failures in individual router builders (like UnsupportedPathError).
add(): Buffers the route into this.#routes.match() (First invocation):
this.#routes is non-null (indicating build phase).this.#routers.router.add(...) for every entry in the buffered routes array.router.match(method, path).UnsupportedPathError occurs, the loop continues to the next router.this.match to the active router's match function, effectively becoming a pass-through for subsequent requests.Sources: src/router/smart-router/router.ts:13-50
Once an active router is identified, SmartRouter modifies itself to minimize overhead for future requests. By re-binding the match function, it bypasses its own logic loop entirely.
// The line that shifts responsibility from SmartRouter to the chosen implementation
this.match = router.match.bind(router);This specific assignment prevents unnecessary conditional checks during the high-frequency path of route lookup, effectively turning the SmartRouter into a thin wrapper around the chosen router.
Sources: src/router/smart-router/router.ts:46
SmartRouter relies on several critical invariants to maintain the integrity of the routing table:
Caution
Once match is called, the state of the router is frozen. The check if (!this.#routes) throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT) inside the add method prevents any further modifications to the route set after the selection of an active router has occurred.
Sources: src/router/smart-router/router.ts:14-16
The following code illustrates how SmartRouter is initialized within the standard Hono framework instantiation.
import { Hono } from 'hono';
import { SmartRouter } from 'hono/router/smart-router';
import { RegExpRouter } from 'hono/router/reg-exp-router';
import { TrieRouter } from 'hono/router/trie-router';
// Manual instantiation (normally handled by the Hono class)
const myRouter = new SmartRouter({
routers: [new RegExpRouter(), new TrieRouter()]
});
const app = new Hono({ router: myRouter });
app.get('/api/users', (c) => c.json({ status: 'ok' }));Sources: src/hono.ts:26-32