0441 Design

Software Creators

Mithril.js Routing

Mithril.js is a JavaScript SPA framework, very Similar to React, but with less...stuff. One thing it does have is a router, which has one strict requirement: it can only be called once in an application. All of the possible routes are contained in one object, supplied as a parameter to m.route.

This object can get very complicated; in FestiGram, the route object is almost 250 lines long (here it is at GitHub).

In Express, a web application, requests are defined along routes, which makes them very convenient. So to do something similar I decided for my next project, I would create a routes folder, instead of having everything inline.

So instead of a 250 line object definition, I use this as my first component:

// App.jsx
// Components/Layout

import m from 'mithril';
import Launcher from '../launcher/Launcher.jsx'
import importedRoutes from '../../routes/routes'

const defaultRoute = {"/launcher": Launcher}

const routes = Object.assign({}, defaultRoute, importedRoutes.default)
const App = {
    oncreate: (vnode) => {
        const mainStage = vnode.dom.querySelector("#main-stage")
        m.route(mainStage, "/launcher", routes)
    },
    view: ({ children }) =>
        
{children}
} export default App

This creates the app and sets up all the routes specified in the routes.js file. Plus it has one default component (Launcher) and a route for it so that even with no other routes defined, the app still runs without errors.

But routes.js doesn' actually have any routes declared:

// routes.js
// src/routes

import _ from 'lodash'

let routes = {}
function importRoutes (r) {
  r.keys().forEach(key => {
    const found = r(key)
    const def = _.get(found, 'default', undefined)
    Object.assign(routes, def)
  })
}

importRoutes(require.context('./', true, /\.route\.js$/))
// At build-time scenarios will be populated with all required modules.
export default routes

Instead it uses a webpack require.context to scan the routes directory and load every file found that ends in .route.js as a module. Then we use Object.assign to roll up all the individual route files into the one giant object that mithril's router wants.

To add new routes, we just add a file ending in .route.js to the routes folder, and webpack will automatically include it in the routes object.

Scroll to top