Settings

Theme

Show HN: Cami.js – A no build, web component based reactive framework

github.com

113 points by kennyfrc 2 years ago · 35 comments · 1 min read

Reader

Hi Everyone! My main motivation for making this was that I wanted something as powerful as Svelte or React but I wanted no build steps, no JSON API, and I wanted something as close to vanilla js as much as possible. I'm mainly a backend developer, and I wanted to simply return html with some interactive islands when I need to (whose components get 'hydrated' with by backend language's templates).

Some key ideas:

• It's centered around light dom web components • Uses a "reactive element", which uses observables for fine-grained reactivity • Rendering is done through lit-html's tagged templates • A pub/sub store • Easy immutability using immer (it powers the observable updates & also the reducers)

It's my first 'serious' library that I'm using in some work prototypes, and it's also my first 'real' open source project, so comments & feedback would be great!

gitgud 2 years ago

Nice work, love the use of reactivity via observables and pub/sub stores (some of my favourite abstractions)

Some feedback from first glance is “type inference” could be better, which would help prevent a lot of foot-guns. Consider the example code here:

    this.count = this.observable(0);
Does this allow “count” to be inferred as a “number” type in the rest of the code? There might be a way to allow JS to easily infer the types, without requiring a build step…
  • kennyfrcOP 2 years ago

    This is great feedback, thanks! I think there’s something around JSDoc types that can accommodate this. Something I’ll put as a milestone before v1.

apsurd 2 years ago

Looks good! FWIW I always felt the observable pattern much more intuitive than the redux/reducer style. Something like https://mobx.js.org/

Things get hairy in both, but redux pattern feels so ridiculously ceremonial all to effectively manage a huge global state object with a false sense of "purity".

Observables otoh say "fuck it, I'm mutating everything, do what you want with it".

  • kennyfrcOP 2 years ago

    Thanks! Cami is technically a combination of both. I like the intuitiveness of observables so that’s used:

    ```

    // define observable

    this.count = this.observable(0);

    // getting

    this.count.value;

    // setting

    this.count.update(value => value + 1);

    ```

    But it also has a redux-like pattern where you can dispatch actions and register reducers with far less ceremony:

    ```

    // define store

    const todoStore = createStore({ todos: [], });

    // register reducer / producer

    todoStore.register('add', (store, payload) => { store.todos.push(payload); });

    // subscribe component to store

    this.todos = this.subscribe(todoStore, 'todos');

    // dispatch

    this.dispatch("add", newTodo);

    ```

    It looks like it’s mutating, but both the reducers and update() uses immer* under the hood, so we still respect immutability under the hood.

    Cami supports redux devtools so you can use that for time-travel debugging too.

    —-

    * https://github.com/immerjs/immer

    • KRAKRISMOTT 2 years ago

      > this.dispatch("add", newTodo);

      Will the V8 JIT optimize the hash based function table loop into a constant integer array lookup?

socketcluster 2 years ago

Great to see the interest growing around native Web Components. I've been working on a no-code (markup only) platform which is also based on web components.

https://saasufy.com/

I built a whole chat app with authentication, blockchain and GitHub login with just 120 lines of HTML markup no front end or backend code (all the logic is abstracted away via generic, easy-to-use components provided by the platform).

You can also build apps which display filtered views by category or with text search with custom parameters and it does so efficiently with indexing and all updates in real time. Real time updates are delivered efficiently only to relevant components. Components automatically subscribe and unsubscribe to and from realtime changefeeds in an efficient way. Access control can be specified at the object/model level or on individual fields.

spankalee 2 years ago

lit-html author here. I'm glad the template library is useful for you!

Question regarding interop with other web components: I don't see how to create reactive properties on elements. Can they receive data from parents via property bindings? Ie, could a Lit element pass data to a Cami element?

  • kennyfrcOP 2 years ago

    Yes, the lib's great!

    Unfortunately I haven't thought much yet about interoperability with other web components libraries like lit. I imagined folks would choose just one web component library over the other.

    That said, you can initialize reactive properties(1), but property bindings won't work if there's a parent LitElement (as my reactive properties need to be called with either a .value method or an .update method for getting and setting respectively).

    As of the moment, what's possible is interop with other cami elements using a store, and in a future version, i'm considering a richer event system for external javascript code to listen to.

    ---

    (1) Initializing is possible with observerableAttr: https://github.com/kennyfrc/cami.js/blob/master/examples/008...

infamia 2 years ago

Great work! This is such a great concept that slots in nicely between HTMX/Unpoly/AlpineJS and React/Vue/etc.

dxchester 2 years ago

Nice work! I have a no-dependencies project with somewhat similar goals in frameable/el[0], which takes more inspiration from Vue in its interface.

WebComponents give us so much, but just not quite enough to be usable on their own without a little bit more on top. Reactivity with observable store and templating with event binding are the big missing pieces.

[0]: https://github.com/frameable/el

arthropodSeven 2 years ago

This seems like a great candidate for the few instances in my HTMX projects when it'd be a pain in the ass to write endpoints that enumerate every possible client-side state. I would love to see somebody put the two together and report on how they get along.

20after4 2 years ago

I like it a lot! I think I will give this a try on a project I'm working on.

jslakro 2 years ago

I see many points in common with https://www.arrow-js.com/ Probably that focus on components could be the only difference

  • kennyfrcOP 2 years ago

    Interesting! Many points are indeed similar. Apart from components, Cami also has immutability built-in and state management.

oknoorap 2 years ago

I also created a webcomponent-based framework two months ago: https://realm.codes

  • Alifatisk 2 years ago

    The website renders weirdly, there is lots of jumping elements before everything is loaded properly. I guess irs the js rendering?

cbrgr 2 years ago

How does this compare with https://github.com/preactjs/preact?

revskill 2 years ago

Seems like Runes (Svelte 5).

Does this support SSR for custom component ?

  • kennyfrcOP 2 years ago

    Yes, Cami uses fine-grained reactivity, so it’s a cousin of similar solutions like Solid signals, Svelte runes, Knockout / and MobX observables.

    It doesn’t support SSR as it aims to be backend-agnostic (i.e. you can use python/ruby/haskell, and you can copy+paste the Cami module with no build step and you can start using it).

    If you want SSR for the SEO benefits, I think it’s better to render the text-heavy parts as normal HTML for indexing with Google, and then mount the interactive parts with Cami / web components (i.e. “islands architecture”: https://www.patterns.dev/posts/islands-architecture)

  • kreetx 2 years ago

    Not the author, but on a quick read, everything here is straight-up web standards so there is nothing to server-side render.

mock-possum 2 years ago

this seems pretty cool - I love me some `lit-html`. How do you feel about Cami versus straight up Lit?

  • Valord 2 years ago

    I use pure no-build lit for the "interactive islands" the repo describes. Nice to see others have the same idea even if we're not taking the same approach.

  • kennyfrcOP 2 years ago

    You can consider Cami as the light dom sibling of Lit (which uses shadow dom).

    Cami loses out on slots & style encapsulation, but you can style Cami components with normal / global css like it’s part of the normal dom. And since there’s no shadow dom overhead, it’s more performant and there is no FOUC if you load CSS in <head>.

  • jack_the_dev 2 years ago

    Wondering the same thing. What is the value proposition versus using other popular web component libraries like Lit?

pjmlp 2 years ago

This is great, I am a big fan of vanilla.js for personal projects.

Thanks for sharing.

aitchnyu 2 years ago

Umm, how do the templates escape malicious input (XSS)?

golergka 2 years ago

What's the advantage of not having any build steps? For me personally, it's an instant turn-off, as I'll never use an untyped library.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection