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.