Skip to content
Andy VanWagoner edited this page Feb 3, 2018 · 8 revisions

API

Router (options)

import Router from 'middle-router'
// or var Router = require('middle-router')

router = Router({ hash: '#!' })
router = new Router()

Router Constructs a new router object. Using the new keyword is optional. The options argument is an optional object with options for how the router will function.

options.hash

Defaults to false, meaning routing will be based on location.pathname. If true, enables routing based on location.hash. If a string value beginning with '#', the string prefix will be ignored when routing.

options.routeLinks

Defaults to true. If true, link clicks will trigger a call to navigate with the link's href once you have called start().

options.confirm

Defaults to window.confirm. A function that takes a confirm message string returns a boolean. The function is called to confirm if a beforeExit handler prevents default, or returns a confirmation message. A true returned from this function means that navigation will continue. A false means the user stays.

It is recommended that you use a custom function that calls window.confirm with a static localized message, and your beforeExit handlers just call event.preventDefault().

routing

await router.routing

The same promise returned by route(), representing the current routing flow. This is null when there is no currently running flow.

start (options)

await router.start({ routeLinks: false })

Start listening for hashchange/popstate events, and optionally link click events. Immediately routes the current url and returns the routing promise. This method will throw an error in an environment without a window object.

stop ()

router.stop()

Stop listening for hashchange/popstate and link click events. Returns the routing promise, if currently routing. If not currently listening for events, this method just returns routing.

navigate (url, state, title)

await router.navigate('/new/path/to/glory')

Update the current location and run the new route. This is similar to window.location.assign() in terms of history. A promise is returned that resolves when the navigation and subsequent routing is complete. This method will throw an error if this router has not had start() called.

url

The new url to navigate to.

state

Optional state object to add to the middleware argument object.

title

Optional title to update document.title with.

replace (url, state, title)

router.replace('/where/you/belong')

Replace the current location. This is similar to window.location.replace() in terms of history. No routing is done. This method will throw an error if this router has not had start() called.

url

The new url to replace the current with.

state

Optional state object to add to the middleware argument object.

title

Optional title to update document.title with.

back ()

await router.back()

Go back one page and run the updated route. This calls window.history.back(). A promise is returned that resolves when the navigation and subsequent routing is complete. This method will throw an error if this router has not had start() called.

forward ()

await router.forward()

Go forward one page and run the updated route. This calls window.history.forward(). A promise is returned that resolves when the navigation and subsequent routing is complete. This method will throw an error if this router has not had start() called.

use (path, ...middleware)

router.use(async ({ path, next }) => {
  let start = Date.now()
  await next()
  let ms = Date.now() - start
  console.log(`${path} took ${ms}ms`)
}, async ({ next, resolve }) => {
  try {
    await next()
  } catch (e) {
    console.error(e)
    resolve(<Error error={ e } />)
  }
})

Add the middleware functions to the list. If path is specified, only execute the middleware when the url matches.

path

The url path to match.

...middleware

The middleware functions to execute when routing. More on the signature of these function is documented below. Router objects can also be passed as middleware.

lazy (path, ...middleware)

router
  .lazy('/esnext', async () =>
    (await import('./esnext/router')).default
  )
  .lazy('/commonjs', () => new Promise((resolve) => require.ensure(
    [], (require) => resolve(require('./commonjs/router')), 'commonjs'
  )))
  .lazy('/amd', () =>
    new Promise((resolve) => require('./amd/router', resolve))
  )

Add functions to the middleware list to load the actual functions or routers asynchronously. If path is specified, only load and execute the middleware when the url matches.

path

The url path to match.

...middleware

The middleware functions to execute when routing. More on the signature of these function is documented below. Router objects can also be passed as middleware.

route (url, state)

let routing = router.route('/route/66')
routing.then(value => { /* route resolved with value */ })

Run through the middleware for the url. This is typically used on the server, and client uses start instead.

The returned promise is resolved with whatever is passed to resolve() in the middleware functions when the whole series is finished running.

url

The new url to go to.

state

Optional state object to add to the middleware argument object.

expressHandler ()

express()
  .use('/api', apiRouter)
  .get('/*', clientRouter.expressHandler())

Get a function to pass to express that mounts the Router.

middleware arguments

router.use(async ({ context, next, resolve }) => {
  let v1 = await next()
  let v2 = await resolve(v1 + 'foo')
})

Each middleware function receives a single object argument containing: router, context, next, resolve, location, path, params, state, and exiting. Any properties you might add to this object will not be passed on to subsequent middleware.

router

The router instance this middleware is running under.

context

By default, the context is an object that is part of the middleware argument. The same object will be passed to each and every middleware that runs.

You can replace the default object with whatever you like by passing a context property to the top-level middleware returned by run.

Any properties added to the root argument object will not be carried to next middleware, so if you need something shared, context is the place to put it.

next ()

Calling next() will immediately start the next middleware, and return a promise that will resolve to the value passed to resolve in a downstream middleware. When the promise resolves, all downstream middleware have completely finished running.

Control will continue upstream when this middleware returns (or resolves if it is an async function or returns a promise), or as soon as resolve is called.

next should only be called once, but if you do call next again in the same middleware function, it will simply return the same promise it did initially.

resolve (value)

Calling resolve() will allow control to flow back to the previous middleware, even if this middleware function hasn't completed. A value can be passed as the first argument, and will set the value to resolve the whole series with. If no value is passed in, the current resolved value remains unchanged.

resolve returns a promise that will resolve to the final value, which may have been changed by upstream middleware.

Calling resolve will prevent any downstream middleware from running if called before this middleware has completed or next is called. If next is called after resolve, it will not trigger the next middleware, but will return a promise that resolves to the current value (last passed to resolve).

location

The location object has most of the same properties as window.location, describing the full url currently being routed. Additionally it has a query property that is an object with the parsed search property.

path

The current path. As routes are nested, path will not have the prefix matched from the parent router removed.

params

Path parameters specified with a : in the use(path) are added to the params object.

state

state is an object intended to mirror the state object given to history.pushState and recieved from history.onpopstate.

beforeExit (callback)

Call beforeExit with a callback function. The function will handle beforeunload events on the window, and beforeexit events on the router. To prompt users to confirm before leaving, either call event.preventDefault(), set event.returnValue to a string, or return a string. See MDN documentation on cross-browser handling of beforeunload.

Note that handlers registered with beforeExit are automatically removed when the user completes navigation. This can be either because no handler prevented the navigation, or the user confirmed the navigation.

exiting

This is a promise that resolves as soon as the next routing begins. This can be very helpful to perform cleanup when the url is no longer matching. If the router is not listening to url changes, such as when running on the server, exiting is undefined. In an async function, you may want to await exiting, but make sure to only do so after calling resolve(), or the middleware won't pass control back upstream until the url is next changed!

To perform cleanup immediately on server, and when the route exits on client, you can wrap it with Promise.resolve(exiting) to consistently have a promise to work with.

Clone this wiki locally