
Show HN: Sinuous – Small, fast, reactive UI library - luwes
https://github.com/luwes/sinuous
======
evmar
I work in this space so I am curious how your library is different from its
similar competitors. I read the docs, but I didn't find anything about the
actual model for how it works, like whether the whole UI rerenders on any
observable change or not. Maybe consider this paragraph a request for
documentation.

PS: A minor suggestion: the word "blazing" is so overused in the JS world at
this point, when I see it I always at first suspect the app is a parody. If
it's fast, then the word "fast" suffices.

~~~
jazoom
I've started learning Rust after many years of NodeJS. In the past 3 weeks
I've seen more "blazing" in Rust library marketing than in all my years of
NodeJS combined.

~~~
evmar
I've noticed it too. It drives me mad.

------
Pmop
Kind off-topic but related: sometimes I wonder how web development would be if
Lisp had somehow won as standard, since we can use to do everything the stack
HTML+CSS+JS+Backend-language does, in addition to standardized syntax and
standard everything.

Oh, standards. Standards.

~~~
TeMPOraL
We were so close. Twice, JavaScript had a chance to be Scheme; both times
marketing reasons prevailed (first, to capitalize on the marketing spending of
Java; later, to compete against Microsoft's JScript).

If Scheme was the language of the web, then HTML and CSS being represented as
s-expressions would be the most obvious next steps, and we'd be like 15 years
ahead in terms of progress.

~~~
seanmcdirmid
Marketing and popularity aren’t unrelated.

~~~
Razengan
Popularity can be faked through marketing.

~~~
seanmcdirmid
Popularity can only be faked via shills and poll rigging. Perhaps you mean
something else?

~~~
buckminster
You say that like marketing and shilling are two wholly distinct activities.
Have you heard of Instagram?

~~~
seanmcdirmid
One is people pretending to like something or wrongly saying people like
something. The other is people liking something for the wrong reasons. These
are completely two different concepts.

------
_hardwaregeek
I kinda don't get the whole "put html in template literals". Wouldn't there be
no syntax highlighting? And the framework is either putting the string into
the DOM with some regex manipulations, which would lead to some very confusing
error messages, or it's parsing the string into a tree, which means it needs
to implement what's essentially XML parsing, which would come with an
overhead. And for what? Avoiding JSX? If you don't like JSX, just desugar it
to nested function calls. Or just use a templating language.

~~~
dmitriid
My personal opinion is that tagged template literals are the worst addition to
Javascript [1]

As HN user stevebmark said [2]:

\--- start quote ---

…we’ve learned not to write code in strings. You’d think this would be a
fundamental law of software engineering

…

Writing code, not strings, means you can do everything to it that you can do
to code. You can type check code. You can lint it. You can optimize it,
compile it, validate it, syntax highlight it, format it with tools like
Prettier, tree shake it…

\--- end quote ---

[1] [https://dmitriid.com/blog/2019/03/tagged-template-
literals/](https://dmitriid.com/blog/2019/03/tagged-template-literals/)

[2]
[https://news.ycombinator.com/item?id=18511943](https://news.ycombinator.com/item?id=18511943)

~~~
tobr
I think your blog post misses an important aspect of tagged template literals,
which is that the first argument is an immutable object that is unique to the
_source location_ of the template. That doesn’t necessarily invalidate the
rest of your argument, but it is a very powerful feature that is not really
equivalent to anything else in JavaScript.

~~~
rounce
What do you mean by 'source location'? Why does this matter? I'm intrigued
(and also suffering from conjunctivitis so excuse me if I'm being a bit dense
and totally missed your point).

~~~
tobr
If you put a tagged template literal on line 42 in foo.js, every time the
tagging function is called from there, the array of strings passed as the
first argument is _the same object_. It’s unique for the source location of
the template literal, so even if you paste the exact same code into bar.js, it
will have a different object. So, the function can recognize that it is being
called from the same location in the source. This has some interesting
implications for meta programming and debugging.

I’m not sure that it matters so much to the discussion, but it is a completely
unique feature, and really has to be mentioned when discussing what tagged
template literals offer.

EDIT: Looked for a good reference - best detailed description I could find was
here: [https://exploringjs.com/es6/ch_template-
literals.html#sec_im...](https://exploringjs.com/es6/ch_template-
literals.html#sec_implementing-tag-functions)

~~~
dmitriid
Never knew about this, and completely missed it when reading about them on
exploringjs.

Thank you for the explanation!

------
localvoid
All "top ranked" libraries that use fine-grained observables graph in this
benchmark are actually "broken"[1].

1\.
[https://github.com/ryansolid/solid/issues/46](https://github.com/ryansolid/solid/issues/46)

~~~
luwes
@localvoid thanks for the investigation, Sinuous can get around this with the
template module I believe.

Also Sinuous doesn't use the same library as Solid or S.js for tracking
dependencies. I'll do some investigating if it has the same issue that you
posted.

~~~
localvoid
Your library has the same issue. Also, you are using linear search[1] when
removing edges.

1\.
[https://github.com/luwes/sinuous/blob/e33c5e8bcdb461be61f7d0...](https://github.com/luwes/sinuous/blob/e33c5e8bcdb461be61f7d078ac5e606b4745382a/packages/sinuous/observable/src/observable.js#L161)

------
codegladiator
> import { o, h } from 'sinuous';

really recommend you to use proper names instead of single letter variables.

~~~
ezekg
I second this. Also, this example on GitHub doesn't work since html is not
defined.

------
ezekg
I took it for a super simple test run and behavior seems very… weird and
incorrect: [https://codesandbox.io/s/7o92r](https://codesandbox.io/s/7o92r).
Perhaps I'm just using it wrong, but it's not very clear why this example's
state fails to update as you would expect. And I found a few examples of
rendering that don't behave as expected.

~~~
luwes
This is fixed in v0.12.3, [https://codesandbox.io/s/sinuous-counter-
hmp8x](https://codesandbox.io/s/sinuous-counter-hmp8x)

The issue below is still to be fixed. It currently returns an array when it
should be a DocumentFragment. It's related to the popular `htm` package that
Sinuous uses.

html`${seq.map(i => html`<li>Counter #${i} ${counter}</li>`)}`

~~~
luwes
also fixed [https://codesandbox.io/s/sinuous-array-bug-
fixed-4s2nr](https://codesandbox.io/s/sinuous-array-bug-fixed-4s2nr)

------
theprotocol
I've toyed around with the template-strings-to-markup approach before, but
couldn't quite figure out how using `map` to generate dynamic lists avoided
doing a full O(n) loop upon each update without some kind of diffing engine
(other than the browser's own markup diffing).

~~~
luwes
it's indeed not possible, that's why there is a `map` module for rendering
lists.

------
azangru
Is anyone else bothered by the two different meanings of the word "observable"
(data streams vs getter/setter/proxy), when you are never sure which one was
meant until you read the code?

Introduction of D3 observable notebooks didn't help :-(

------
aitchnyu
This brings Svelte to my mind with mere kbs of code free of a virtual-dom
runtime. What should I know more?

~~~
luwes
@aitchnyu it is similar to Svelte, a lot simpler, early stages, less features
though.

I think one of the upsides of Sinuous is that stays much closer to plain JS
and to the web standards.

