hyper-value — living data in your application

March 19, 2018 0 Comments

hyper-value — living data in your application

 

 

hyper-value — is a JavaScript (and Typescript) library created to manage data flows. Bundled with hv-jsx and hv-dom it allows developing web-applications similarly to react.js.

The core idea is minimalism and simplicity.

When I encounter a library or a tool the first thing I’m always looking for is the example of the code.

And here it is:

I believe that the choice of the framework or library depends on the project and preferable patterns of a developer. There are a lot of front-end tools dedicated to help a JavaScript-programmer.

So why do you need one more?

You probably don’t.

If you really like the react-redux way — I guess you won’t find hyper-value a superior.

But I personally see some problems, with complexity being the biggest one.

The main goal of hyper-value is to provide a simple tool. It’s created to be:

  1. easy to learn;
  2. easy to use;

It also does not require you to change a paradigm. The number of new concepts to learn is also reduced to a minimum.

Some people like to fully understand how their tools work. Others prefer to delegate some logic to a framework to be done magically.

I believe that having the magic in a library increases its capability to simplify your work.

There is some of it in hyper-value, but it is localized and easy to understand.

I suggest you trying hyper-value if:

  • you want a really simple tool;
  • you want to minimize the amount of abstractions and entities;
  • you don’t like the existing libraries for some reasons and want to try something new;

Understanding the hyper-value ecosystem consist of getting two basic concept JSX and hyper-value itself. Also there is some information about hv-jsx, which is basically the glue between these two.

Note: There is a lot of documentation about JSX technology. You can probably skip this part if you have worked with it before. Nevertheless I’m going to cover this topic to provide a consistent guide.

Let’s say you start a new web-app using only vanilla JavaScript and DOM API. At some point of development you need to create a small set of HTML elements with children and attributes. You can do it either with generating HTML code and making a browser to parse it (via innerHTML etc.), or via DOM API such as createElement, appendChild, etc.

I omit the first way and concentrate on the second. Working on your app you can end with something like this:

That’s a lot of code which is also hard to read. It will produce the following markup:

Thinking of improvement you can write a function like this:

using that function the code above could be refactored in this way:

which is much easier to read and maintain.

So… where is JSX?

JSX is a specific syntax that could be compiled to very similar form. Given an XML tag a compiler will produce a function call with 2 + n arguments, where:

  • the 1st will be tag name as string;
  • the 2nd will be an object containing attributes and corresponding values;
  • the N-th will be N-th child between the tags;

For example:

will produce:

Note: by default jsx is compiled to React.createElement, but you can customize it via pragma or especial comment like /** @jsx h */for babel (https://babeljs.io/docs/plugins/transform-react-jsx/#options). For typescript it can be accomplished tweaking jsxFactory in compiler options.

It’s also possible to pass variables or expressions to attributes (or inside text) via curly brackets:

I strongly recommend to visit babel repl: https://babeljs.io/repl/ to see how it works.

If you use tag name in pascal case (e.g. <Foo/>) it will be compiled in similar way, but instead of string literal it will be identifier (usually a class):

h(Foo, null)

h function (or React.createElement or any else) is supposed to be able to handle a class as first argument.

You can read more about JSX here: https://reactjs.org/docs/jsx-in-depth.htmlhttps://babeljs.io/docs/plugins/transform-react-jsx/ https://www.typescriptlang.org/docs/handbook/jsx.html

The main idea behind hyper-value library is observable mutations. It’s not a new idea — it’s rather similar to ES5 getter / setter, but it also works for single values (not only to object properties).

To explain how it works I give an example. Let’s say we are writing some web-app where user can input his name and see it in "Hello ${name}" form.

This code will work for the first time. But will not react to changes of the input. However, it represents exactly what we want to do. Changing input value changes the name. No more, no less.

We can rewrite the code in this way:

it will work, but there is another problem. If we output a value in a few places it becomes harder. But if we also change it in more than one place it becomes a complete mess:

Basically one of the solutions is to provide some kind of a bus, through which all data will flow. It can be done via getter / setter approach + EventEmitter, or Observable… or via hyper-value.

hyper-value is a simple wrapper around any variable. It can be created by the following construction:

Now you can read and update name value like that:

of course hyper-value can do some other tricks. It can be watched:

Note: hs — is an instance of HyperScope class which will be available in some environment, or you can create it manually. The latter requires deeper understanding of hyper-value architecture.

and it can be derived from others hyper-values:

In this example fullName.$ will be always equal to the first and last names joined with a space character, even after changing one of them.

There are some more features you will be able to find in the documentation soon.

Since we learned the basics of hyper-value and get familiar with JSX it should not take a lot of time to understand how to combine these two together.

Using hv-jsx library you can create components and use JSX with hyper-values integrated into it.

For example:

The content of the span will always be relevant. So you can write anywhere something like this name.$ = 'Mike'and the app will update respectively.

There is no centralized store in hyper-value itself. The idea is that instead of one big place that reacts to changes in data and stores multiple primitive values, you can create such kind of primitive values anywhere and react to their changes directly.

If needed, you can gather these values together into some kind of a store.

Speaking of components they can be either state-full or stateless (almost) depending on your implementation: if all used hyper-value are passed through the props, it makes more or less stateless component.

Some examples are written in typescript — it’s not a requirement but there are some reasons for that:

  1. I love Typescript, and I encourage you to try it if you haven’t;
  2. Since variables and props can contain both raw values and hyper-values it might be not trivial to tell them apart. That’s where typescript helps a lot. One another solution is to add some prefix or suffix to your identifiers (like suffix $ in rxjs: https://medium.com/@benlesh/observables-and-finnish-notation-df8356ed1c9b).

Before starting, some preparation is needed. Of course you have to have node.js installed on your system. Also you’ll need webpack and typescript for that example project. They are not required, but recommended. There should be no problem to use any other tools like babel, browserify, etc.

To install these ones you can use a snippet:

# install base tools typescript and webpack
npm install -g typescript webpack-cli webpack

The next step is to prepare your project folder. Any of these libraries do not require a specific structure of directories, I’ll show just one of the options.

file structure of the project:
/
|--- dist/
|--- src/
| |--- app.tsx
|--- index.html
|--- package.json
|--- webpack.config.js
|--- tsconfig.json
  • index.html should import the project bundle from ./dist folder;
  • package.json — is not necessary at all;
  • webpack.config.js — is any valid webpack config for a typescript project;
  • tsconfig.json — must contain these options:
...
"jsx": "react",
"jsxFactory": "jsx"
...

It tells typescript to compile JSX syntax in a specific way, which by the way very decoupled from react. For more information you can visit: https://www.typescriptlang.org/docs/handbook/jsx.html

I’m not going to provide full content of these files for the sake of keeping the article readable. But you can find the example configs on the project page on GitHub: https://github.com/int0h/hv-counter-app. It can be a template for your project.

Basically it’s just a regular minimal environment for a typescript application except for JSX-settings.

Let’s install webpack loaders:

# install loaders
npm install --save typescript awesome-typescript-loader source-map-loader

And finally let’s install hyper-value itself and relative libraries:

npm install --save hyper-value hv-jsx hv-dom

At this point we are finally ready to write some code!

I suggest starting with the simplest thing. It’s not going to be impressive but it is supposed to prove that everything is working at all.

Let’s create the click counter app.

Build your project with:

# it will be rebuilding your app
# in a developement mode on every change now
webpack -dw

And open ./index.html in your browser. You should be able to see the message.

Not very impressive, right? (and also indistinguishable from react so far).

So let’s add some dynamics to the app. To do that we’ll create a HyperValue instance:

…and now we are rebuilding the project (or it’s been done already by watch mode). And that’s it! Let’s check how our app works! (I hope it does :D)

I’m going to change the task slightly and we’ll see how to adapt to new conditions. Now our app should output the timestamp and log time of a few last clicks:

Let’s check if everything works as expected and go on!

Now we need to add some kind of an event log to the app:

And the final feature… Let’s make the number of visible items configurable:

That’s it. You can also find a demo for this demo-app here: https://int0h.github.io/hv-counter-app/

All written above surely can remind you of the react ecosystem. And it indeed has some similar parts.

Here I’ll show the comparsion between these technologies:

If you liked the idea of hyper-value itself you would probably wish to be able to use it with the real react instead of hv-jsx. I understand that and I’m thinking about possible ways to integrate them into each other.

As it was mentioned before react can be compared to hv-jsx, and hyper-value should be compared to redux / MobX / RxJs etc.

hyper-value offers an approach different from others, because of that it seems impossible to compare the features.

hv-jsx compared to react looks much less mature. And it has some similarities such as:

  • JSX;
  • component classes;
  • render method supposed to return JSX or something similar;

But all of the rest is different:

  • hv-jsx has no explicit component state. There is no way to call this.setState(...) or anything similar;
  • hv-jsx has some differences in JSX usage, for example you can use class attribute for css-classes, there is no key attribute etc. Also JSX can be extended significantly;
  • at this moment there is almost no component life-cycle hooks. Although there is one init method where you can run any initialization code. But this likely will be changed in the future;

In my benchmarks hv-jsx performs close to react in speed. But these measurements were not enough to make any conclusions, it was rather proof-of-concept checks. And there is a lot of work to be made to improve performance further and further.

Speaking of bundle size: at this point the minified and gzip-ed size of a bundle of the whole demo-application (including hyper-value itself, hv-jsx, hv-dom and application logic) is about 15 KB. But these values are going to change in the future because:

  • there are some features to be done and added to total size;
  • there are some bundle size optimizations, which will reduce the size;

At this point I want to show my project to the community and get some feedback in return.

It’s not stable yet. There are going to be some changes in public API and some internal refactoring.

Also documentation will be improved a lot.

Here is a list of libraries somehow connected to hyper-value:

and some others mostly internal libraries.

There are also some plans, e.g. to make it work with mobile native UI (like react-native).

In the end I want to show a few interesting ideas that can be easily implemented with hyper-value:

By using hs.auto you can create a new hyper-value which will be updated each time its dependent change. It tracks all hyper-values used to calculate its value and subscribe to them.

It’s very similar to hs.auto but supports asynchronous updates. Let’s say you need to make a search field and output some results corresponding to it. It can be expressed like this:

You can find full example here: https://github.com/int0h/hv-async-app

If you have an array of todo’s and want to indicate whether every of them is completed you can write:

https://github.com/int0h/hv-counter-app — counter application described above

https://github.com/int0h/hv-todo-list — todo application

https://github.com/int0h/hv-async-app — async demo

hyper-value is a minimalistic library created to be simple and make application development easier.

I hope you liked the idea. I appreciate any feedback.


Tag cloud