Open Source Adventures: Episode 18: Imba 2
Tags: imba, javascript
Published: 2022-03-20 17:43:39

I wanted to do this back for my Electron Adventures series, but [Imba 2 doesn't work well with Electron due to some bundler configuration issues](https://github.com/imba/imba/issues/591).

### History of JavaScript frameworks

So, here's some opinionated history of JavaScript frameworks. There's been 3 generations:

The first generation was the **jQuery generation**. Everything was either based on storing state directly in the DOM like *jQuery* or *D3*, or trying to use Model-View-Controller pattern, with view and controller being very often built on top of jQuery, and model often having some custom half-assed OO system as JavaScript never provided enough functionality out of the box. Some notable frameworks of that generations were *Backbone* and *Angular* 1. Notable languages were pre-ES6 JavaScript, and CoffeeScript.

I think it's fair to say that jQuery was and still is amazing at sprinkling a bit of extra functionality on top of a mostly-static site, with very little code, but neither DOM-state nor MVC approaches work very well for more complex sites. It's still alive and well in many niches, for example testing tools, scrappers etc. are basically all jQuery-style.

Second generation was the **React generation**. It dropped DOM-state and MVC concepts completely, and instead organized code in a tree of Components. Every component handling its rendering, behavior, and sometimes also styling, and communicating only with parent and children. This generation embraced ES6 JavaScript with extensions like JSX, and bundlers like Webpack. Strangely despite ES6 having a reasonable OO sytem, there's a lot of custom OO systems in this generation as well. React Hooks, Redux and so on, are all basically custom OO systems. Notable frameworks of that generation were (various iterations of) *React* and *Vue*.

And currently we're entering third generation, which so far looks like **Svelte generation**. It's still Component based, but unlike previous generation where reactivity was partial (dependencies need to be declared manually), runtime-managed, and required a lot of boilerplate; this generation's reactivity is more complete (dependencies are automatically inferred), compiled, and low-boilerplate. The main frameworks of this generation so far are *Svelte* and *Imba*, but since this is the generation we're currently entering, there could be a lot more.

This generation usually more fully embraces making each component handle its styling, something React generation was divided on, and jQuery generation never did.

### Imba

[Imba framework](https://imba.io/) was created for [Scrimba](https://scrimba.com/), a very futuristic interactive education website.

The biggest problem with Imba is that Imba 1 to Imba 2 transition is a total rewrite, Imba 2 has been in alpha for over two years, and Imba 1 is not getting updates, so there are some issues related to bundlers it uses and latest node version.

Imba is based on a custom variant of CoffeeScript, which is not a very popular choice now, and Imba 1's language, Imba 2's, and original CoffeeScript are not even that close to each other.

### Creating a new App

Let's create a new Imba app with `npx imba create counter`. It asks a bunch of questions, but you can just accept the default.

Let's take a look at initial file:

```
global css html
  ff:sans

tag app
  <self>
    <header>
      <svg[w:200px h:auto] src='./logo.svg'>
      <p> "Edit {<code> "app/client.imba"} and save to reload"
      <a href="https://imba.io"> "Learn Imba"

imba.mount <app>
```

The first and super annoying thing is that it uses tabs, set to 4 space width, instead of 2 spaces like every other web tech. Back in Imba 1 both worked, but now only tabs work. That's terrible for all kinds of reasons, one of them being how bad these look when pasted into blog posts (that's why I convert it all to 2 spaces for the blog). I hope they see the light and add support for standard 2 spaces at some point.

Anyway, there's crazy much going on here:

* it's CoffeeScript variant, so indentation is significant
* `tag app` defines component `app`, which behind the scenes creates a web component `app-tag` - Imda 2 is based on web components
* `imba.mount <app>` mounts component `app` to the DOM, as we didn't specify target, it does it directly inside the `<body>`
* Imba handles CSS too, global, element scoped, or inline
* Imba does a lot of Tailwind-style CSS shortcuts, like `ff:sans` expands to `font-family: var(--font-sans,system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");`
* `w:200px h:auto` expands to much less surprising `width: 200px; height: auto;`
* HTML is builtin sort of like with JSX, but instead of explicitly closing tags it uses indentation
* inside HTML things are code by default, so you need to do `"Learn Imba"` not just plain `Learn Imba` if you want to insert a string
* string interpolation with `"{}"`, because obviously every language has different string interpolation syntax

As you can see, Imba 2 is a big language. It's not a limited framework that just does one thing well like jQuery or React or Tailwind, Imba tries to be complete solution for the frontend.

### Counter App

OK, let's build a simple counter app.

```
global css body
  min-height: 100vh
  d: flex
  justify-content: center
  align-items: center
  text-align: center

tag app
  prop count = 0

  <self>
    <header>
      <button @click=count++> "Click me"
      <p> "Clicked {count} times"

imba.mount <app>
```

![Counter screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p097vvzi0kzqodew86co.png)

What's going on:

* `global css body` is just "how to center in CSS", I don't know all the shortcuts, so I used long ones except for `d`
* `prop count = 0` defines property and its initial value
* `<button @click=count++> "Click me"` is a simple inline clicke handler
* as with all third generation frameworks, we don't need to do any manual dependency tracking, so no `this.setState` or such

### Coming next

So this is the basics of Imba 2. Over the next few episodes we'll try to build a few toy apps in Imba 2, and then we'll try some other techs that slipped through the cracks.

[All the episode code is in this repo](https://github.com/taw/open-source-adventures).