live_json
LiveJSON provides LiveView-like updating for JSON objects rather than DOM elements. It works within your existing LiveViews - just use push_patch
as you would assign
or push_event
. Only the changes to the data are sent over the wire, not the whole object every time, so it can end up being quite fast indeed.
This may be useful for front-end frameworks, data visualization, games and anything else where you need dynamically updated data that lives outside of the DOM, like mobile apps.
Example
def handle_info({:new_data_to_visualize, new_data} = _event, socket) do
{:noreply,
socket
|> push_patch("viz_data", new_data)
}
end
Now, check your JS console:
window.viz_data
// {1: ["a"], 2: ["b"] ... 99999: ["zzzzz"]}
The data is automatically updated, but if you check the WebSocket, you'll see that only the data that changed has been sent.
Problem / Solution
Phoenix LiveView is awesome for automatically updating your webpage's DOM. However, it doesn't work as well for data objects, since it only works at the DOM level out of the box, meaning any complex data objects need to be entirely re-sent every time. So, if you load your JS app's data via a templated script
tag, LiveView will rewrite the whole tag, not just the elements that changed, which means sending a lot of data over the wire and other headaches on the client-side.
LiveJSON is a simple alternative - it uses Jsondiff/JSON-Patch (RFC 6902) to only send the delta of the data, which is then patched client side, similar to how morphdom
works on the DOM.
Installation
First, the usual:
def deps do
[
{:live_json, "~> 0.1.0"}
]
end
Next, you'll need to set up the hooks in your app.js
:
// Import the JS..
import { createLiveJsonHooks } from 'live_json';
const liveJsonHooks = createLiveJsonHooks();
// ..then define all your hooks..
const Hooks = {
// your other hooks
// ...
...liveJsonHooks,
};
// ..and use them!
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {
hooks: Hooks,
params: {_csrf_token: csrfToken},
});
If your app uses an assets/package.json
, you'll also need to add:
{
"dependencies": {
"live_json": "file:../deps/live_json"
}
}
and then npm install
.
Finally, you'll need to put a tag for the hook somewhere on the related Heex:
"><div id="lj" phx-hook="LiveJSON">div>