nanoweb

What is nanoweb?

nanoweb is a minimal library for building server-centric multi page web applications that behave like SPAs.

nanoweb's ideas can be freely combined with other server-centric frameworks while avoiding a technology lock-in, which makes it a perfect fit for micro-frontends.

Motivation

Frontend development has become increasingly complex over the past few years and the time required to manage this complexity often goes at the expense of the user experience. The amount of JavaScript and related payloads doesn't seem to be tenable in a time where the mobile web traffic eclipses that of desktops. React, Vue.js and Angular are great frameworks, yet they are primarily geared towards highly interactive and long-running web applications. Anything outside of this scope has to live with the diminishing returns of those frameworks.

This sentiment is shared by more and more people while new initiatives pop up: Hotwire, Phoenix LiveView, React Server Components, Livewire. These solutions are usually rooted in pre-existing frameworks that add more abstraction. nanoweb, on the other hand, is just a small set of documented and tested helper functions for the framework-fatigued.

nanoweb consists of two packages which can be used together or separately in combination with other frameworks.

The nanoweb links package makes navigating your web application faster. You get the performance benefits of a single page application without the added complexity of a client-side JavaScript framework. Use HTML to render your views on the server side and link to pages as usual. When you follow a link, @nanoweb/links automatically fetches the page, merges it into the current page, all without incurring the cost of a full page load. Besides performance optimizations and loading animations the page interaction will be indistinguishable from a static page.

The real benefit of this solution kicks in once we need to keep state on the client. It is not required to repeatedly rehydrate the frontend anymore. We can keep the UI state always in memory and avoid flashing content. It shares some resemblance with Turbolinks. But instead of simply swapping body content, we merge it with morphdom to avoid loosing form state.

Templates

Templates are tagged template literals - they look like JavaScript strings but are enclosed in backticks (`) instead of quotes - and tagged with @nanoweb/template's html tag:

html`<h1>Hello ${name}</h1>`

Since templates almost always need to merge in data from JavaScript values, they'll most often be written within functions that take some data and return a template, so that the function can be called multiple times:

const myTemplate = (data) => html`
<h1>${data.title}</h1>
<p>${data.body}</p>
`
;

Template values are not limited to primitive data types, but they can contain Promises as well.

const fetchUsername = async (userId) => { [... fetch from DB ...] };

const myTemplate = (userId) => html`
<div>Username: ${fetchUsername(userId)}</div>
`
;

html returns a Template, which can be transformed into a string by passing it to renderToString.

const result = myTemplate({title: 'Hello', body: 'nanoweb is cool'});
const text = await renderToString(result);

Ready to try it yourself? Head over to Getting Started.