Streams

Exploring Riot.js – Introduction

Riot.js presents itself as « React-like user interface micro-library ». Personally, I would qualify it as a user interface micro-library whose philosophy is « webcomponents ». At first glance, what comes in mind is a lightweight Polymer-like library plus some nice goodies.

Basically, the principal Riot.js equation is:

html code (layout) + js code (behavior) = a custom tag = a « webcomponent »

Optionally, you can add some custom styles to the equation to polish your component…

Show me some code!

Here it is! First, you define the html tag that encloses your custom code, then you define the js code. A custom tag skeleton looks like this:

<hello-world>
  <h3>{message}</h3>

  <script>
    // <script> tag is required if we provide style too
    this.message = 'Hello World!!!';
  </script>

  <style>
   ...
  </style>
</hello-world>

If you don’t want embed style, it is not mandatory to declare a <script> tag to embed the javascript:

<hello-world>
 <h3>{message}</h3>

 this.message = 'Hello World!!!';
</hello-world>

Then, in your index.html, you need to call Riot to transform your tags into proper JavaScript before the browser can execute them:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello World</title>
  </head>
  <body>
    <!-- mount point -->
    <hello-world></hello-world>

    <script src="./hello-world.tag" type="riot/tag"></script>

    <!-- include riot.js and the compiler -->
    <script src="https://cdn.jsdelivr.net/riot/3.0/riot+compiler.min.js"></script>
    
    <!-- mount normally -->
    <script> riot.mount('*') </script> 
  </body>
</html> 

… and you get a nice « Hello Word!!! » displayed in your browser. Awesome! 😉

So, that's all guy?

Nope, it was just a teaser. Riot.js not only provides a custom-tags feature, but it also provides eventing and routing. The three master-pieces to build nice client apps. So, here is another equation:

Riot.js = custom tags + events + router

– Custom tags enable web-componentization of the client apps. It’s the first piece of modularity and re-usability.
– Events enable the different web components to communicate to each other and be loosely-coupled. Eventing is the second pillar of modularity.
– Router enables us to navigate through the application.

In this post, we will focus only on custom tags. Other posts will follow for the events and the router…

 

Ok, let’s talk about custom tags…

Riot.js relies on a compiler that compiles the Riot.js custom tags into javascript. This compiler can be either embedded in the html app (as the above code shows) or executed during a pre-built phase (and in this case, your index.html references the generated javascript files).

As in AngularJS, you can defined directly your components in the index.html. In this case, you embed the Riot.js code between a tag <script type=”riot/tag”>…</script>. Honestly, besides small demos, I don’t think I will use it like that. If you wish to get a sample, just go there. In a project, you will probably use it by defining your custom tags into separate files (as you do with AngularJS), compile them and reference the compilation result into your html page.
So, how do we call the compiler? If you have installed Riot.js with npm (and you probably have), you can do it via a « riot » command line or, if you are a hipster guy, through one of the six-month live fashion tools that does everything and more thanks to a plethora of plugins. Huh? Does it look like a beginning of a troll?

Being tired with tasks managers and other tools that become obsoletes or not trendy after six months, I’ve just used npm to run the Riot.js commands. I’ve started embracing the « philosophy » of using npm as a build tool (the troll continues here and for French readers, a nice troll-agnostic article there) just to see if we really need other tools… But, yes, there are Riot.js command wrappers  Grunt, Gulp, Browserify, Webpack, etc..

Back to Riot.js commands, you can not only compile Riot.js files into js but also watch riot files. In this case, each modification of a file results in its compilation. Neat! Here is a simple command that tells riot to watch files in the « app » directory and compile the result into the « dist » directory:

riot --type es6 -w app dist

Oh! The « –type es6 » is to tell Riot.js that the js code is written in ES6… hum, excuse-me, « written in Javascript 2015 »… Riot.js also supports Coffee, Jade, Typescript and Livescript as preprocessors. You can even configure another preprocessor (but I didn’t try it).

 

What else?

You can inject objects or functions through the riot.mount(.) function (which also loads your custom-tags into your html app).

riot.mount('*', {title: 'Say hello!', myService: anAmazingService});

I would compare this to the injection mechanism of AngularJS: you can pass whatever to your Riot.js component thanks to this instruction…  The object is then accessed by the component with a special variable « opts ».

<!-- in the index.html file -->
<script>
  riot.mount('*', {title: 'Say hello!'});
</script>
<!-- in your tag file -->
<hello-world>
  <h3>{opts.title}</h3>
</hello-world>

You’ve also got data-binding (as you’ve seen in the above sample code with the « mustache » { } syntax), expressions, loops and conditional as you have in AngularJS:

<todo>

  <ul>
    <li each={items} class={completed: done}>
      <input type="checkbox" checked={done}> {title}
    </li>
  </ul>

  <div if={has_items}>
    This div is inserted when 'has_items' is true.
  </div>
  <div show={has_items}>
    This div is shown when 'has_items' is true.
  </div>

  this.items = [
    {title: 'First item', done: true},
    {title: 'Second item'},
    {title: 'Third item'}
  ]

  this.has_items = this.items.length > 0
</todo>

You can also have nested custom-tags and transclusion (as for AngularJS directive but a lot simpler…).

At last, custom-tags have a lifecycle that can be hooked thanks to some events (‘mount’, ‘update’, ‘updated’, ‘unmount’).

 

In summary

Riot.js shares some concepts with React but also has some nice features we can find in AngularJS or Polymer too. Its motto is modularity and its backbone is:
– custom tags
– events (observables)
– router

It is not mandatory to use all these features, but all of these features allow you to build nice client apps. What I like in this library is its simplicity: there are few, but strong concepts. Simplicity makes it easy to learn. The doc is well written. I’ve even took the time to read the full API and it didn’t take me a lot of time since the API is small (and I even recommend to read it!). If you come from an AngularJS or an EmberJS or a React, I believe the learning curve is even lower!

So, small and simple… but it doesn’t mean  incomplete. Give it a try! And if you want to have a look at the code, you can find it on our GitHub (introduction branch).

**Original source: streamdata.io blog