akkajs-dom
v0.1.0
Published
Akka.Js Dom framework extension
Downloads
182
Maintainers
Readme
Akka.Js DOM
Minimalistic Framework for frontend applications built on top of Akka.js
Featuring:
- Local Mutable State (with VDOM)
- Page / application separation
- Location transparency for application
- Real parallelism (multithread via Workers)
- Fully asynchronous
- Easy inter-workers communication
Install
npm install --save akkajs-dom
Quick start
Ensure you have installed npm
and clone this repository.
Go into one of the examples in the demo directory and run:
npm install
npm run build
npm run serve
and you will get the result from a modern browser at http://localhost:3000
.
The examples are intended to be considered "live" and you are encouraged to play with them!
Overview
We assume you have some understanding of basic Akka.Js concepts. Otherwise take first the Akka.js Quick Start
Akka.Js DOM has 2 core components:
UiManager
DomActor
UiManager
UiManager
is the minimal "in-page" driver, with an extremely small footprint that manage operations with the DOM, it needs to be loaded straight in page.
This hook accept, as for now, 3 possible kind of objects to bind to the page:
- a module that exports a
localPort
, it's purpose is mainly for debug or for few elements that needs to be displayed asap in page - a
Worker
- a
SharedWorker
all you need to do is to instantiate one UiManager
per component you have to visualize in page.
import it as:
const { UiManager } = require("akkajs-dom/page")
and then one of:
new UiManager(
require("./simple.js") // for debugging purposes
)
new UiManager(
new Worker("./js/simple.out.js")
)
new UiManager(
new SharedWorker("./js/simple.out.js")
)
A UiManager
constructor accepts a second optional argument.
{
name: componentName, // default to a random ID
handlers: handlersModule, // module containing functions that have to be run on events, default to undefined
unmatchedFun: defaultUnmatchedFunction // what to do if an unhandled message is received in page, default to log it
}
Functions in handlersModule
should return results in a serializable format (e.g. Json, string, ...) since results will be propagated through a MessageChannel
.
example:
const { UiManager } = require("akkajs-dom/page")
new UiManager(
new Worker("./js/simple.out.js"),
{
name: "simple",
handlers: require("dom-handlers.js")
}
)
DomActor
DomActor
is an enanched Actor
that is ready to interact with the DOM, it has an extended API to enable defining UI components.
example:
const { DomActor } = require("akkajs-dom/work")
class Clock extends DomActor {
constructor () {
super("root")
}
render (value) {
return <h3>Hello world!</h3>
}
receive (msg) {
this.update(msg)
}
}
The default constructor of DomActor
accept a String.
Calling the default constructor with the optional String is mandatory for top-level UI components and the value should be the id
of an element already present in page.
If not specified the binding element is by default appended to the parent
DomActor
.
The DomActor
lifecycle is mapped 1 to 1 with the rendering in page, this does mean that spawning a DomActor
will render something in page while killing it will remove the element from the page.
The full available API is composed on top of the basic akkajs.Actor
one and it adds the following user-overridable functions (already binded to this by default)
Methods
|Method|Description|
|-------|----------|
|this.render(value)
| Will return the content to be visualized |
|this.postMount()
| Is an hook triggered after the element is mounted in page NOTE: preStart
is reserved |
|this.postUnmount()
| Is an hook triggered after the element is unmounted from the page NOTE: postStop
is reserved |
|this.events(map)
| Should return a map of the events to be intercepted on the relative DOM elemnt. The format of each entry is eventName -> eventFunction
please note functions used here should be accessible by both UiManager
and DomActor
|
there are also some methods intended to be used from within the Actor
itself:
Methods
|Method|Description|
|-------|----------|
|this.update(value)
| Used to update the status, will trigger a render
call containing the specified value
|
|this.register(eventName, eventFunction)
| Low level interface to register DOM events, functions should be accessible from UiManager
and DomActor
(prefer the events
notation) |
Logging
Given the fact that you can spawn your DomActor
s in environments where console.log
is not available we provide a simple interface for having a cross compatible logging system.
the mandatory import will looks like:
const { Logger, LogLevel } = require("akkajs-dom/work")
to have a Logger you should have already an ActorSystem spawned
const log = new Logger(actorSystem, LogLevel.<desiredlevel>)
available logging levels are:
{
off,
error,
warning,
info,
debug
}
and finally you can use your logger:
log.debug(text)
log.info(text)
log.warn(text)
log.error(text)
Inter-Communication
[in-development]
Akka.Js DOM provides you a common way to communicate peer-to-peer in between different components.
The preferred way is to open a specular bidirectional communication channel.
In page you spawn to UIManager
and be sure to provide a name
option.
const { UiManager } = require("akkajs-dom/page")
new UiManager(
new SharedWorker("./js/ping.out.js"),
{
name: "ping",
handlers: require("./dom-handlers.js")
}
)
new UiManager(
new Worker("./js/pong.out.js"),
{
name: "pong",
handlers: require("./dom-handlers.js")
}
)
Now in the two workers you can:
// Spawn a proxy actor to make this worker available for external communication
const proxy = system.spawn(new WorkerProxy())
// define a "ConnectedChannel" Actor that will connect to another Worker
class PongChannel extends ConnectedChannel {
postAvailable () {
// triggered when the bounded worker is available
this.channel
}
operative (msg) {
// behavior available for user
}
}
system.spawn(new PongChannel(proxy, "pong")) // the name here is the channel we wanna connect
TODO: describe the full API.
Compile
To compile and build this project simply:
npm install
npm run build
IT tests are based on the demo projects:
npm run buildDemo # needed only once
npm test