🗺 Universal router for web applications.

Overview

Rill Logo
API stability TypeScript NPM version Build status Test Coverage Downloads Browser Bundle Size (Gzipped) Gitter Chat Sauce Test Status

Expressive router for nodejs and the browser. Rill brings cascading middleware to the browser and enables a familiar routing solution for web applications.

Rill provides the minimum for abstractions over nodejs and the browser enabling things like routing (with redirecting, refreshes and more), cookies, and middleware with the same api.

It supports many view engines including Marko, React, Svelte and even html only template engines such as Pug.

Installation

npm install rill

Browser support

All modern browsers are supported including IE10 and above. Older browsers will need to polyfill the Promise API, checkout es6-promise for a good polyfill, babel-polyfill also covers this.

Community

Articles

Why Rill?

Rill is the answer to a simple question; Can I run my Express style router in the browser? Turns out you can and it works awesome.

It brings a common interface to many typical app like features in both the browser and nodejs. Many isomorphic frameworks and routers have crazy abstractions and learning curves but with Rill, if you understand Express or Koa, you already know how the routing works! In Rill you get to program much of your application logic using the same api (client or server) including routing, rendering, data fetching and more are easily shared.

Rill also works perfectly as a stand alone router for nodejs or in the browser. This allows for easy progressive enhancement. If all is well the browser can handle much of your application logic and if JavaScript fails for any reason your server knows exactly what to do.

How does this thing work?

If you look at the source for Rill here you will quickly notice there is ZERO browser specific code. This is all thanks to @rill/http which is node's HTTP.createServer ported to the browser.

In the browser it works by listening for internal link clicks, form submissions and browser history changes. It will then create a Rill Context for each of these events and emit it through the router, similar to how receiving a request works in nodejs.

It supports everything you'd expect from a client side nodejs server. This includes redirects, refreshes, cookies, scrolling and url updates using the History API.

Example

Create an app

/**
 * The following code can run 100% in the browser or in nodejs.
 * Examples use es2015/2016 with Babel and JSX but this is optional.
 */

import Rill from 'rill'
const app = new Rill() // You can call Rill without new, but autocomplete will not work.

Setup middleware

// Universal form data parsing middleware.
import bodyParser from '@rill/body'
app.use(bodyParser())

// Universal react rendering middleware.
import reactRenderer from '@rill/react'
app.use(reactRenderer())

// Example Logger
app.use(async ({ req }, next)=> {
  const start = Date.now()

  // Rill uses promises for control flow.
  // ES2016 async functions work great as well!
  await next()

  const ms = Date.now() - start
  console.log(`${req.method} ${req.url} - ${ms}`)
})

Setup a page

// Respond to a GET request.
app.get('/todos', async ({ res })=> {
  // Fetch a todolist from some service.
  const todolist = await MyTodoListService.getAllTodos()

  // Directly set React virtual dom to the body thanks to @rill/react.
  // (Checkout @rill/html for universal html diffing).
  res.body = (
    <html>
      <head>
        <title>My App</title>
        <meta name="description" content="Rill Application">
      </head>
      <body>
        <form action="/add-todo" method="POST">
          <h1>Just a plain old form</h1>
          <input type="text" name="todo"/>
          <button type="submit">Add Todo</button>
        </form>

        {todolist.length
          ? todolist.map(renderTodo)
          : 'No todos to display.'
        }
        <script src="/app.js"/>
      </body>
    </html>
  )
})

Handle a form submission

// Respond to a POST request.
app.post('/add-todo', async ({ req, res })=> {
  // We handle form submissions with Rill the same way one would express or koa.
  // Here we are simply adding the todo via some service.
  await MyTodoListService.addTodo({ text: req.body.todo })
  // And then we redirect back (same as res.redirect('/todos'))
  res.redirect('back')
})

Start app

// Start a regular http server.
// In the browser any form submissions or link clicks will intercepted by @rill/http.
app.listen({ port: 80 })

See Also

  • isbrowser - A browserify transform to remove server-side code.
  • isomorphic-fetch - Universal http requests using WHATWG fetch.
  • isomorphic-form-data - Send multipart form data universally (able to send files and works with fetch).
  • scroll-behavior - @rill/http will automatically try to use the "smooth" scroll-behavior when scrolling to targets on link clicks. This will polyfill that across modern browsers.
  • submit-form - Manually trigger Rill navigation in the browser.

Prior Art

  • koa-client - Koa clone that runs in the browser, inspired this package.
  • monorouter - Another isomorphic router that partially inspired this package.

Contributions

  • Use npm test to build and run tests.

License

MIT

Comments
  • Res.status returns 404 when using promises in routes

    Res.status returns 404 when using promises in routes

    Hello,

    The response object returns a 404 whenever I use promises with the routes. When I remove the promise, the response is resolved normally. The examples on the site are done with async/await, so I think that is likely the issue. Is there any example using regular promises?

    opened by imolorhe 11
  • Grouping routes for similar functions into seperate files

    Grouping routes for similar functions into seperate files

    Hello,

    Is it possible to group routes into seperate files the same way you would do it in express?

    In express, you could just do:

    app.use('/animals', require('./animals'))

    and inside animal.js, you could have:

    var express = require('express')
      , router = express.Router()
    
    // Domestic animals page
    router.get('/domestic', function(req, res) {
      res.send('Cow, Horse, Sheep')
    })
    
    // Wild animals page
    router.get('/wild', function(req, res) {
      res.send('Wolf, Fox, Eagle')
    })
    
    module.exports = router
    

    Such that all the routes are preceded with /animals. Can this be achieved in rill as well?

    opened by imolorhe 4
  • Props

    Props

    Not react props. I just wanted to give you some props for making this. I've been thinking about how great it would be if this existed and attempted once. But got too tricky for me trying to extrapolate express routes for the browser. I'll be following closely!

    Funny story as well, I put something together last week, less of a framework but something that puts together webpack and hmr together for ssr. Not complete but works given the right conditions right now. Need to add in configurability. checkout, http://github.com/uptownhr/kube.

    Right now, i'm trying to see how I can use rill, instead of express and see where that can go.

    opened by uptownhr 4
  • Production logger: rill-pino-logger

    Production logger: rill-pino-logger

    Hey @DylanPiercey

    rill looks really promising!

    I made this http://npm.im/rill-pino-logger - it provides high speed request logging, specifically designed for production servers via http://npm.im/pino

    This is the first production logger for rill :bowtie:

    Would you be up for adding it to the wiki ?

    opened by davidmarkclements 2
  • Pass the request, response and next() arguments to the middlewares

    Pass the request, response and next() arguments to the middlewares

    Hello,

    Is it possible that the re, res, next() arguments can be passed directly to the controllers as arguments? To streamline it with the approach taken by express. Currently the first argument is the context while the second is the next() when available.

    opened by imolorhe 1
  • Documentation: Transpiling JSX / React

    Documentation: Transpiling JSX / React

    The main example on the readme would not work without a step that transpiles JSX / React.

    I'll submit a PR as soon as (and if) I figure out an easy way to do that.

    PS: Thanks, the concept of this framework is quite exciting. I'll be playing with it quite a bit over my weekends. 👍

    opened by srirangan 1
  • Add a Gitter chat badge to README.md

    Add a Gitter chat badge to README.md

    rill-js/rill now has a Chat Room on Gitter

    @DylanPiercey has just created a chat room. You can visit it here: https://gitter.im/rill-js/rill.

    This pull-request adds this badge to your README.md:

    Gitter

    If my aim is a little off, please let me know.

    Happy chatting.

    PS: Click here if you would prefer not to receive automatic pull-requests from Gitter in future.

    opened by gitter-badger 0
  • Cleanup

    Cleanup

    • [x] rename ctx,request to ctx.req and ctx,response to ctx.res.
    • [x] make ctx.req.original and ctx.res.original.
    • [x] Remove cookies from context and add a getter on req and a setter on res.
    • [x] Write compression middleware for non static assets.
    opened by DylanPiercey 0
Owner
Rill
Universal web application framework.
Rill
A proxy web app that serves ABC iView content outside of the iView webplayer, avoiding intrusive data harvesting.

iview-proxy A proxy web app that serves ABC iView content outside of the iView webplayer, avoiding intrusive data harvesting. There's also a cool Andr

The OpenGov Australia Project 11 Jul 16, 2022
DSC-AlarmServer - Creates web interface to DSC/Envisalink with proxy.

DSC-AlarmServer Creates web interface to DSC/Envisalink with proxy. Since the Envisalink module can only have one connection, this phython script can

null 4 Oct 11, 2022
Node.js web server framework for Http/1.1 or Http/2

Node.js web server framework for Http/1.1 or Http/2 Description: This is http framework, you can use it to create Http/1.1 or Http/2 service。 Now let'

Jeremy Yu 10 Mar 24, 2022
Micro client-side router inspired by the Express router

Tiny Express-inspired client-side router. page('/', index) page('/user/:user', show) page('/user/:user/edit', edit) page('/user/:user/album', album) p

Sloth 7.6k Dec 28, 2022
A chainable router designed for Next.js api. inspired and regex based from itty-router

Next.js Api Router A chainable router designed for Next.js api. inspired and regex based from itty-router Features Tiny (~8xx bytes compressed) with z

Aris Riswanto 1 Jan 21, 2022
Router JS 💽 Simple Router building in JavaScript

Router JS ?? Simple Router building in JavaScript

David Montaño Tamayo 1 Feb 12, 2022
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
IDE and toolkit for building scalable web applications with React, Redux and React-router

An all-in-one solution for creating modern React apps Rekit is a toolkit for building scalable web applications with React, Redux and React-router. It

Rekit 4.5k Jan 2, 2023
✨ Create server-rendered universal JavaScript applications with no configuration

Universal JavaScript applications are tough to setup. Either you buy into a framework like Next.js or Nuxt, fork a boilerplate, or set things up yours

Jared Palmer 11k Jan 7, 2023
✨ Create server-rendered universal JavaScript applications with no configuration

Universal JavaScript applications are tough to setup. Either you buy into a framework like Next.js or Nuxt, fork a boilerplate, or set things up yours

Jared Palmer 11k Jan 8, 2023
A Flow-based programming language for universal applications.

Hlang A Flow-based programming language for universal applications. Hlang aims to make programming easier, faster and more comfortable. It avoids codi

HSET 5 Dec 25, 2022
a more intuitive way of defining private, public and common routes for react applications using react-router-dom v6

auth-react-router is a wrapper over react-router-dom v6 that provides a simple API for configuring public, private and common routes (React suspense r

Pasecinic Nichita 12 Dec 3, 2022
Thin Backend is a Blazing Fast, Universal Web App Backend for Making Realtime Single Page Apps

Website | Documentation About Thin Thin Backend is a blazing fast, universal web app backend for making realtime single page apps. Instead of manually

digitally induced GmbH 1.1k Dec 25, 2022
🗂 Universal Media Library as a web component.

Kondonizer Kondonizer is a custom element (a native HTML tag) that can be integrated in any frontend code. It displays a media library based on a Medi

EcoHead 6 Jul 19, 2022
A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router.

A web application to search all the different countries in the world and get details about them which can include languages, currencies, population, domain e.t.c This application is built with CSS, React, Redux-Toolkit and React-Router. It also includes a theme switcher from light to dark mode.

Franklin Okolie 4 Jun 5, 2022
A web interface to edit TP-Link Router Config export files (typically named config.bin).

TP-Link Router Config Editor A web interface to edit TP-Link Router Config export files (typically named config.bin). Visit the website. Tested on an

Jahed 10 Nov 17, 2022
A template repository / quick start to build Azure Static Web Apps with a Node.js function. It uses Vue.js v3, Vue Router, Vuex, and Vite.js.

Azure Static Web App Template with Node.js API This is a template repository for creating Azure Static Web Apps that comes pre-configured with: Vue.js

Marc Duiker 6 Jun 25, 2022
Bun-Bakery is a web framework for Bun. It uses a file based router in style like svelte-kit. No need to define routes during runtime.

Bun Bakery Bun-Bakery is a web framework for Bun. It uses a file based router in style like svelte-kit. No need to define routes during runtime. Quick

Dennis Dudek 44 Dec 6, 2022