Please check it out: https://github.com/pragmagic/karax

Thanks to Nim's metaprogramming, static typing and JS backend we've been able to produce an SPA framework in a short amount of time, and performance is on par with the big players out there. Why use the best tool for the job when you can use the best tool instead?

2017-04-22 09:03:15

Looks neat, might have to give this a go for some upcoming stuff I was going to write in React.

Can I ask what exactly the "Benchmark" graph is meant to show in the readme? Because this isn't very descriptive

2017-04-22 09:28:28
That's just the "standard" TodoApp benchmark. It measures rendering speed after entry insertions and deletions afaik.
2017-04-22 09:54:45
And of course all the usual caveats about benchmarks apply. You should simply take it as an indication that Karax is fast enough already to give a try for a serious application. 2017-04-22 09:59:08
Looks great! Waiting for 0.16.1 to be released to try it
2017-04-22 15:54:28

Indeed, great idea!

Did you had a look at Vue for inspiration? Many people consider it the next big thing after React, and in terms of performance it has already raised the bar a bit.

But performance is typically not the most important aspect for choosing a JS framework. Probably karax would benefit the most by making it more accessible to JS users. Some random questions (not necessarily to be answered here, just points for documentation).

  • How to interact with third party JS libraries? (A general question that is most likely answered in the JS backend documentation itself; just to point out that it is one of the first questions that come to mind, and linking it from karax would be good.)
  • How does state handling work. In a Vue/React component, I know pretty much were to look for state, in the examples I find it very hard to see.
  • Why aren't components split into template/code(/style)?
  • How do components communicate?
  • What about the tooling, i.e., how does building / bundling / browser test running / debugging (source maps) work? An idea for the documentation would be to map JS artefacts like npm/webpack/mocha/karma/selenium to possible solutions.
  • By the way, my first thought when looking at the code was: All cstring here, I'm scared -- wait, it's not even compiling to C? I think I get now why it has to be like that, but getting rid of that c could definitely reduce the scare factor for newbies .
2017-04-23 07:55:54

Did you had a look at Vue for inspiration? Many people consider it the next big thing after React, and in terms of performance it has already raised the bar a bit.

Yeah, I only used Vue version 1, so I know what to stay away from. I looked at Elm for a major source of inspiration.

How to interact with third party JS libraries?

We're making Karax work with emscripten and strive for good interop with Nim code, not JS code.

Why aren't components split into template/code(/style)?

Because such a split only produces artificial complexity.

How do components communicate?

They don't. Components should be stateless. I think we should use a different name, Karax's components are not what others call "components".

What about the tooling, i.e., how does building / bundling / browser test running / debugging (source maps) work?

Source maps are in the works and "bundling" doesn't need anything, it's generated JS code, move it to where you want.

An idea for the documentation would be to map JS artefacts like npm/webpack/mocha/karma/selenium to possible solutions.

I don't know what that means.

All cstring here, I'm scared -- wait, it's not even compiling to C? I think I get now why it has to be like that, but getting rid of that c could definitely reduce the scare factor for newbies

Would it help to rename it to jsstring?

2017-04-23 08:49:19

Would it help to rename it to jsstring?

I think what scares people about "cstring" are two things:

  • the illusion that it has something to do with C (whereas "c" means "compatible")
  • the fact that you have to use a special type instead of the regular "string"

"jsstring" alias would fix the first point, but not the second one.

2017-04-23 17:41:36

@Araq: Sound very interesting, really looking forward in which direction this will develop. +1 for the Elm inspiration and not following the the one-file-component path. And compared to Elm, the Nim syntax really shines for the templating stuff.

I've been wondering for some time, if it would be possible to achieve a design which is even closer to the Elm architecture? On first glance it would be so nice to write stuff like this:

type:
  Model = object
    # ...
  
  Msg = object
    # typically an object variant

proc init(): Model = ...

proc update(msg: Msg, model: Model): Model = ...

proc view[Msg](model): Html[Msg] = ...

karax.runMain(init, update, view)

Are there any plans to go in that direction or are there technical obstacles which prevent such a design?

2017-05-13 21:37:26

In fact, it is maybe not even too far away:

include karaxprelude
import jstrutils, dom, future

type
  Model = ref object
    toggle: bool
  
  EventHandler = (Event, VNode) -> void
  EventHandlerModel = (Model, Event, VNode) -> void


proc curry(handler: EventHandlerModel, model: Model): EventHandler =
  result = (ev: Event, n: VNode) => handler(model, ev, n)

proc onClick(model: Model, ev: Event, n: VNode) =
  kout(ev)
  kout(model)
  model.toggle = model.toggle xor true

proc view(model: Model): VNode =
  result = buildHtml():
    tdiv:
      button(onclick=curry(onClick, model)):
        text "click me"
      tdiv:
        text "Toggle state:"
      tdiv:
        if model.toggle:
          text "true"
        else:
          text "false"

proc runMain() =
  
  var model = Model(toggle: true)
  
  proc renderer(): VNode =
    # var model = Model(toggle: true)   # init here does not work
    view(model)
  
  setRenderer renderer

runMain()

At first I was initializing the model in the renderer proc. This had the result that the view never updated -- it's not immediately clear to me why it has to be in the outer scope.

Adding an Elm-like message approach should also be possible by constructing some Msg in each event handler and calling an update function. Okay, in contrast to Elm the model is updated in-place, but maybe it is even beneficial to keep the model update close to how it works natively.

The only issue is that every event handler has to be curried. So my question probably becomes: Is it possible to automatize this "injection" of the model into the event handlers, so that an event handler (Model, Event, VNode) -> void can be passed directly to on....

2017-05-14 20:37:08
<<<••12••>>>