Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/bryhoyt/emerj

Emerj is a tiny JavaScript library to render live HTML/DOM updates efficiently and non-destructively, by merging an updated DOM with the live DOM, and only changing those elements that differ.
https://github.com/bryhoyt/emerj

dom html-generation nunjucks virtual-doms

Last synced: 2 months ago
JSON representation

Emerj is a tiny JavaScript library to render live HTML/DOM updates efficiently and non-destructively, by merging an updated DOM with the live DOM, and only changing those elements that differ.

Awesome Lists containing this project

README

        

# Emerj.js: efficient HTML DOM UI in 60 lines

[![Build Status](https://secure.travis-ci.org/bryhoyt/emerj.svg)](https://travis-ci.org/bryhoyt/emerj)
[![NPM Version](https://img.shields.io/npm/v/emerj.svg)](https://www.npmjs.org/package/emerj)

Emerj is a tiny JavaScript library to render live HTML/DOM updates efficiently and non-destructively, by merging an updated DOM tree into the live DOM, element-by-element, and only changing those elements that differ. It's a lightweight, powerful answer to the some of the same problems addressed by Facebook's React.

Specifically, Emerj solves the problem of rendering on-the-fly changes to your HTML/DOM webpage or UI. In most user-facing software, you want to keep the UI-rendering logic quite separate from the business logic, and not clutter your logic with all kinds of extra code to update the UI when the data is modified.

In traditional HTML/JavaScript, this can be tricky to do tidily, which is the main driver for the recentish proliferation of tools like Angular, React, Ractive, etc. However, these tools all require a moderately significant paradigm shift, and your code needs to adopt the framework from the ground up. They also come with a fair amount of hidden (and not-so-hidden) complexity.

Emerj aims to cut through all this complexity by doing just one thing, and using the native browser DOM APIs for all the heavy lifting. You provide an HTML string (or an out-of-document DOM tree) and Emerj compares this to the live DOM and updates just those elements and attributes that differ. To do this, Emerj uses a similar method used by React described in its [reconciliation algorithm](https://facebook.github.io/react/docs/reconciliation.html).

For an extended explanation of the thinking behind Emerj, and the design decisions I made along the way, see [the introductory blog post](http://blog.brush.co.nz/2017/11/emerj-js-efficient-html-ui-in-60-lines/).

## Installation

$ npm install emerj

This exposes CommonJS (`index.js`), UMD (`index.umd.js`), and ESM (`index.mjs`) versions e.g.:

```javascript
const emerj = require('emerj');

// or

import emerj from 'emerj';
```

Alternatively, a [CDN](https://unpkg.com/) can be used e.g.:

```html

```

Feel free to post issues or questions as they come up.

## How to use Emerj

There are four basic steps:
1. Set up your document, include the necessary scripts, and an empty element ready to fill with some content.
2. Create your data model. This could be as simple as `data = {todo: []}`
3. Write some code to generate HTML based on that data. You could try [Nunjucks](https://mozilla.github.io/nunjucks/) or anything you like.
4. Whenever you update your data, regenerate your HTML, and use Emerj to update the live document.

I learn best by example, so here you are:

```jinja2
<!doctype html>
<html>
<head>
<script type=text/javascript src='nunjucks.js'>
<script type=text/javascript src='emerj.umd.js'>
</head>
<body>
<div id=root><!-- The live document will go here --></div>

<script type=text/template name='todo.html'>
<!-- Your favourite template language. I like Nunjucks. -->
<ul class='todo'>
{% for item in todo %}
<li><input type=checkbox {% if item.done %}checked{% endif %}> {{ item.text }}</li>
{% else %}
Add an item below
{% endfor %}
<li><input type=text name=new></li>
</ul>


var data = {todo: []}

var template = nunjucks.compile(document.querySelector('[name="todo.html"]').innerHTML);

addEventListener('data:updated', function () { // Use your preferred event system.
// You could use requestAnimationFrame() here for better performance.
var html = template.render(data);
emerj.merge(document.querySelector('#root'), html);
})

document.querySelector('[name=new]').addEventListener('change', function() {
data.todo.append(this.value);
dispatchEvent(new Event('data:updated'));
})

dispatchEvent(new Event('data:updated'));