All Projects → bryhoyt → emerj

bryhoyt / emerj

Licence: MIT license
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.

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to emerj

affiliate
Add affiliation tags to links automatically in the browser
Stars: ✭ 77 (+37.5%)
Mutual labels:  dom
front-end-interview-questions
No description or website provided.
Stars: ✭ 27 (-51.79%)
Mutual labels:  dom
xpath2.js
xpath.js - Open source XPath 2.0 implementation in JavaScript (DOM agnostic)
Stars: ✭ 74 (+32.14%)
Mutual labels:  dom
m4q
Small library for DOM manipulation and animation. This library similar to jQuery, but written more simply.
Stars: ✭ 30 (-46.43%)
Mutual labels:  dom
moon
🌎 🌔 A hobby web browser developed from scratch
Stars: ✭ 253 (+351.79%)
Mutual labels:  dom
PopUpOFF
Chrome extension, providing better web experience.
Stars: ✭ 65 (+16.07%)
Mutual labels:  dom
dom
Package for access and manipulate DOM element in HTML file
Stars: ✭ 29 (-48.21%)
Mutual labels:  dom
picoCSS
picoCSS - really small JavaScript Framework
Stars: ✭ 62 (+10.71%)
Mutual labels:  dom
respo.cljs
A virtual DOM library built with ClojureScript, inspired by React and Reagent.
Stars: ✭ 232 (+314.29%)
Mutual labels:  dom
Mei.js
a minimal, simple and helpful library for you
Stars: ✭ 15 (-73.21%)
Mutual labels:  dom
CalDOM
An agnostic, reactive & minimalist (3kb) JavaScript UI library with direct access to native DOM.
Stars: ✭ 176 (+214.29%)
Mutual labels:  dom
smart-custom-element
Smart a lightweight web component library that provides capabilities for web components, such as data binding, using es6 native class inheritance. This library is focused for providing the developer the ability to write robust and native web components without the need of dependencies and an overhead of a framework.
Stars: ✭ 17 (-69.64%)
Mutual labels:  dom
js-symbol-tree
Turn any collection of objects into its own efficient tree or linked list using Symbol
Stars: ✭ 86 (+53.57%)
Mutual labels:  dom
ready
Detect element availability on the initial page load and those dynamically appended to the DOM
Stars: ✭ 77 (+37.5%)
Mutual labels:  dom
tsdom
Fast, lightweight TypeScript DOM manipulation utility
Stars: ✭ 16 (-71.43%)
Mutual labels:  dom
vanilla-caret-js
Set and get Caret position (contenteditable or TextArea) using Vanilla JavaScript
Stars: ✭ 31 (-44.64%)
Mutual labels:  dom
vue-drag-select
基于Vue的仿原生操作系统鼠标拖拽选择
Stars: ✭ 63 (+12.5%)
Mutual labels:  dom
crab
JavaScript library for building user interfaces with Custom Elements, Shadow DOM and React like API
Stars: ✭ 22 (-60.71%)
Mutual labels:  dom
javascript-html5-apis
🏆 Starter project for JavaScript HTML5 APIs
Stars: ✭ 19 (-66.07%)
Mutual labels:  dom
dom-to-image-more
Generates an image from a DOM node using HTML5 canvas
Stars: ✭ 231 (+312.5%)
Mutual labels:  dom

Emerj.js: efficient HTML DOM UI in 60 lines

Build Status NPM Version

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.

For an extended explanation of the thinking behind Emerj, and the design decisions I made along the way, see the introductory blog post.

Installation

$ npm install emerj

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

const emerj = require('emerj');

// or

import emerj from 'emerj';

Alternatively, a CDN can be used e.g.:

<script type='text/javascript' src='https://unpkg.com/[email protected]'>

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 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:

<!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>
  </script>

  <script type=text/javascript>
    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'));
  </script>
</body>
</html>

Why and how

If you need to create dynamic HTML on-the-fly in the browser, based on some data, and you want something lightweight but powerful and adaptable, and/or Preact/React isn't your cup of tea, then (particularly if you like generating HTML from moustachioed templates, but can't accept the brokenness of overwriting your entire document every render), Emerj might be your answer.

For more, see the introductory blog post. But here's the short version:

After becoming frustrated with the horribleness of ad-hoc DOM manipulation, and the problems with plain template rendering, I grew attracted to React's clever idea of comparing two virtual DOMs and just updating the differences in the live document. But I couldn't abide JSX, and any solution I adopt needs to retrofit into sizeable existing applications, without requiring a complete overhaul of the UI templates.

A comment on Hacker News made me realise how useful it would be to have the virtual-DOM concept of React, but without being locked into JSX. A few things fell nicely into place, and Emerj was the result.

Emerj is based on three primary concepts:

  1. Be unopinionated about how the HTML or DOM is generated. Just use any plain HTML or DOM that is passed in, and let the user create it however they like.
  2. Realise that every browser has a perfectly functional virtual DOM built in. Any out-of-document element will do. The browser also provides a functional API to parse an HTML string into a virtual DOM: element.innerHTML = html. So use it.
  3. Using this virtual DOM, merge it with the live DOM in the approximate manner described in React's reconciliation algorithm.

There's not really much more to say. It's that simple. The code is simple enough to refer you to it for any more details.

Isn't the DOM super slow?

No. See the blog post.

Parsing HTML is more slow. But not nearly enough to justify the slow sad shake of your head you're doing right now. Don't forget your real bottleneck is probably the server round-trip for your API calls.

Ok, so basically Emerj does nothing, and Nunjucks does all the real work?

Yep. The best code is no code.

But, in case you completely missed the whole point, Nunjucks on its own (or whatever template language you use) will blow away and rerender your DOM on every update, losing all document state (scroll position, input state, etc) and sucking your CPU.

Performance

See the performance section in the introductory blog post. In short, Emerj+Nunjucks is within cooee of React for a typical modern web app (what's that?!). But test it out for your own needs, and if it's not performant enough for you, either build a component system on top of it, or use something else.

Version

1.0.0

Copyright and License

Copyright © 2017-2018 by Bryan Hoyt.

This is free software; you can redistribute it and/or modify it under the terms of the MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].