squint

Chris McCormick 2025-10-23T07:15:07.090439Z

BTW I discovered React 19 supports this cool thing: https://react.dev/reference/react-dom/components/common#ref-callback > React 19 added cleanup functions for ref callbacks. If you have a :ref and it returns a function, that callback will be called on unmount instead of the :ref , and it has the original element in scope. I have so much messy code having to track the old element so this is hugely better. It's not supported by Reagent yet (Reagent 2 which I think is not yet released) but I am putting it in Eucalypt since it's backwards compatible and seems so useful. So in this respect Eucalpyt is slightly ahead of Reagent briefly. 😎

😎 2
borkdude 2025-10-23T12:03:53.510889Z

My conclusions so far after experimenting with idiomorph and snabbdom for small reactive apps: • I implemented a snake game on idiomorph + atom + add-watch, feels close to reagent. But it turned out you didn't need a morphing lib for this at all, just use set! innerHTML. • You do need a dom patching lib when dealing with input fields, focus, etc. There idiomorph works well. But: if you want to deal with event listeners on nodes, then it's not convenient. I made a https://squint-cljs.github.io/squint/?src=KHJlcXVpcmUgJ1siaHR0cHM6Ly9lc20uc2gvaWRpb21vcnBoIiA6cmVmZXIgW0lkaW9tb3JwaF0gOnJlbmFtZSB7SWRpb21vcnBoIEl9XSkKCihkZWYgcm9vdCAob3IKICAgICAgICAgICAgKGpzL2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3IgIiNjb250YWluZXIiKQogICAgICAgICAgICAoZG90byAoanMvZG9jdW1lbnQuY3JlYXRlRWxlbWVudCAiZGl2IikKICAgICAgICAgICAgICAoc2V0ISAtaWQgImNvbnRhaW5lciIpCiAgICAgICAgICAgICAgKGpzL2RvY3VtZW50LmJvZHkucHJlcGVuZCkpKSkKCihkZWYgc3RhdGUgKGF0b20gezpjb3VudGVyIDAKICAgICAgICAgICAgICAgICAgOmlucHV0ICJIZWxsbyIKICAgICAgICAgICAgICAgICAgOnNob3cgdHJ1ZX0pKQoKKGRlZiBkYXRhLXJlZ2lzdHJ5IHt9KQoKKGRlZm4gZGF0YS1ieSBbaWQgZGF0YV0KICAoYXNzb2MhIGRhdGEtcmVnaXN0cnkgaWQgZGF0YSkKICBpZCkKCihkZWZuIG15LWNvbXBvbmVudCBbXQogICNodG1sIFs6PD4KICAgICAgICAgWzpkaXYgIkNvdW50OiAiICg6Y291bnRlciBAc3RhdGUpXQogICAgICAgICBbOmRpdiBbOmJ1dHRvbiB7OmRhdGEtY2xpY2sKICAgICAgICAgICAgICAgICAgICAgICAgIChkYXRhLWJ5IDpteS1jb21wb25lbnQvY2xpY2sKICAgICAgICAgICAgICAgICAgICAgICAgICAgIyhzd2FwISBzdGF0ZSB1cGRhdGUgOmNvdW50ZXIgaW5jKSl9CiAgICAgICAgICAgICAgICAiUGxlYXNlIGNsaWNrIG1lIl1dCiAgICAgICAgIFs6aW5wdXQgezpkYXRhLWlucHV0IChkYXRhLWJ5IDpteS1jb21wb25lbnQvaW5wdXQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjKHN3YXAhIHN0YXRlIGFzc29jIDppbnB1dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgtPiAlIDp0YXJnZXQgOnZhbHVlKSkpCiAgICAgICAgICAgICAgICAgIDp0eXBlIDp0ZXh0IDp2YWx1ZSAoOmlucHV0IEBzdGF0ZSl9XQogICAgICAgICBbOnByZSAoOmlucHV0IEBzdGF0ZSldXSkKCihkZWZuIHVpIFtdCiAgI2h0bWwgWzpkaXYKICAgICAgICAgWzpidXR0b24KICAgICAgICAgIHs6ZGF0YS1jbGljayAoZGF0YS1ieSA6c2hvdy1idG4tY2xpY2sKICAgICAgICAgICAgICAgICAgICAgICAgICMoc3dhcCEgc3RhdGUgdXBkYXRlIDpzaG93IG5vdCkpfQogICAgICAgICAgIlNob3c%2FIl0KICAgICAgICAgKHdoZW4gKDpzaG93IEBzdGF0ZSkKICAgICAgICAgICAobXktY29tcG9uZW50KSldKQoKKGRlZiBub2RlLXBvb2wgKGpzL01hcC4pKQoKKGRlZm4gcmVzdG9yZS1ldmVudC1oYW5kbGVycyBbXQogIChkb3NlcSBbZXZlbnQgWzpjbGljayA6aW5wdXRdXQogICAgKGxldCBbbm9kZXMgKC5xdWVyeVNlbGVjdG9yQWxsIHJvb3QgKHN0ciAiW2RhdGEtIiBldmVudCAiXSIpKV0KICAgICAgKGRvc2VxIFtub2RlIG5vZGVzXQogICAgICAgICh3aGVuLW5vdCAoY29udGFpbnM%2FIG5vZGUtcG9vbCBub2RlKQogICAgICAgICAgKGFzc29jISBub2RlLXBvb2wgbm9kZQogICAgICAgICAgICAoLmFkZEV2ZW50TGlzdGVuZXIgbm9kZSBldmVudAogICAgICAgICAgICAgIChnZXQgZGF0YS1yZWdpc3RyeSAoLmdldEF0dHJpYnV0ZSBub2RlIChzdHIgImRhdGEtIiBldmVudCkpKSkpKSkpKSkKCihkZWZuIG1vcnBoIFtdCiAgKEkvbW9ycGggcm9vdCAoc3RyICh1aSkpCiAgICB7Om1vcnBoU3R5bGUgOmlubmVySFRNTAogICAgIDpjYWxsYmFja3MgezphZnRlck5vZGVSZW1vdmVkIChmbiBbbm9kZV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkaXNzb2MhIG5vZGUtcG9vbCBub2RlKSl9fSkKICAocmVzdG9yZS1ldmVudC1oYW5kbGVycykpCgooYWRkLXdhdGNoIHN0YXRlIDpzdGF0ZSAoZm4gW18gXyBfIF9dCiAgICAgICAgICAgICAgICAgICAgICAgICAgKG1vcnBoKSkpCgoobW9ycGgp. Smallest app is around 6kb. It does work well with compile time #html generation. • Snabbdom has good support out of the box for dealing with event listeners. Smallest app around 6kb. You do need a hiccup interpreter for this though which in theory could affect render time compared to the compile time #html support. https://squint-cljs.github.io/squint/?src=KHJlcXVpcmUgJ1siaHR0cHM6Ly9lc20uc2gvc25hYmJkb20iIDpyZWZlciBbaAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTW9kdWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzTW9kdWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0eWxlTW9kdWxlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TGlzdGVuZXJzTW9kdWxlXV0pCgooZGVmIHBhdGNoIChpbml0IFtjbGFzc01vZHVsZSBwcm9wc01vZHVsZSBzdHlsZU1vZHVsZSBldmVudExpc3RlbmVyc01vZHVsZV0pKQoKKGRlZm4gY3JlYXRlLW5vZGUgW2hpY2N1cF0KICAoY29uZAogICAgKG9yCiAgICAgIChudW1iZXI%2FIGhpY2N1cCkKICAgICAgKHN0cmluZz8gaGljY3VwKSkgaGljY3VwCiAgICAodmVjdG9yPyBoaWNjdXApCiAgICAobGV0IFtbdGFnICYgW2F0dHJzICYgY2hpbGRyZW4gOmFzIGFsbC1jaGlsZHJlbl1dIGhpY2N1cAogICAgICAgICAgW2F0dHJzIGNoaWxkcmVuXSAoaWYgKG1hcD8gYXR0cnMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHJzIGNoaWxkcmVuXQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuaWwgYWxsLWNoaWxkcmVuXSkKICAgICAgICAgIGVsIChpZiAoZm4%2FIHRhZykKICAgICAgICAgICAgICAgKGNyZWF0ZS1ub2RlIChhcHBseSB0YWcgYWxsLWNoaWxkcmVuKSkKICAgICAgICAgICAgICAgKGRvCiAgICAgICAgICAgICAgICAgKGggdGFnIGF0dHJzCiAgICAgICAgICAgICAgICAgICAobWFwdiBjcmVhdGUtbm9kZSBjaGlsZHJlbikpKSldCiAgICAgIGVsKQogICAgOmVsc2UKICAgIChkbwogICAgICAodGhyb3cgKGpzL0Vycm9yLiAoc3RyICJJbnZhbGlkIGhpY2N1cDogIiBoaWNjdXApKSkpKSkKCihkZWZuIHNsaWRlciBbdGhlLWF0b20gY2FsYy1mbiBwYXJhbSB2YWx1ZSBtaW4gbWF4IHN0ZXAgaW52YWxpZGF0ZXNdCiAgWzppbnB1dCB7OnByb3BzIHs6dHlwZSAicmFuZ2UiIDp2YWx1ZSB2YWx1ZSA6bWluIG1pbiA6bWF4IG1heCA6c3RlcCBzdGVwfQogICAgICAgICAgIDpzdHlsZSB7OndpZHRoICI1MCUifQogICAgICAgICAgIDpvbiB7OmlucHV0IChmbiBbZV0KICAgICAgICAgICAgICAgICAgICAgICAgIChsZXQgW25ldy12YWx1ZSAoanMvcGFyc2VGbG9hdAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGFnZXQgKGFnZXQgZSAidGFyZ2V0IikgInZhbHVlIikpXQogICAgICAgICAgICAgICAgICAgICAgICAgICAoc3dhcCEgdGhlLWF0b20KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZm4gW2RhdGFdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoLT4gZGF0YQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYXNzb2MgcGFyYW0gbmV3LXZhbHVlKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGlzc29jIGludmFsaWRhdGVzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxjLWZuKSkpKSl9fV0pCgooZGVmbiBjYWxjLW9obXMgW3s6a2V5cyBbdm9sdGFnZSBjdXJyZW50IHJlc2lzdGFuY2VdIDphcyBkYXRhfV0KICAoaWYgKG5pbD8gdm9sdGFnZSkKICAgIChhc3NvYyBkYXRhIDp2b2x0YWdlICgqIGN1cnJlbnQgcmVzaXN0YW5jZSkpCiAgICAoYXNzb2MgZGF0YSA6Y3VycmVudCAoLyB2b2x0YWdlIHJlc2lzdGFuY2UpKSkpCgooZGVmIG9obXMtZGF0YSAoYXRvbSB7OnZvbHRhZ2UgMTIgOmN1cnJlbnQgMC41IDpyZXNpc3RhbmNlIDI0fSkpCgooZGVmbiBvaG1zLWxhdy1wYWdlIFtdCiAgKGxldCBbezprZXlzIFt2b2x0YWdlIGN1cnJlbnQgcmVzaXN0YW5jZV19IEBvaG1zLWRhdGFdCiAgICBbOmRpdgogICAgIFs6aDMgIk9obSdzIExhdyBDYWxjdWxhdG9yIl0KICAgICBbOmRpdgogICAgICAiVm9sdGFnZTogIiAoLnRvRml4ZWQgdm9sdGFnZSAyKSAiViIKICAgICAgW3NsaWRlciBvaG1zLWRhdGEgY2FsYy1vaG1zIDp2b2x0YWdlIHZvbHRhZ2UgMCAzMCAwLjEgOmN1cnJlbnRdXQogICAgIFs6ZGl2CiAgICAgICJDdXJyZW50OiAiICgudG9GaXhlZCBjdXJyZW50IDIpICJBIgogICAgICBbc2xpZGVyIG9obXMtZGF0YSBjYWxjLW9obXMgOmN1cnJlbnQgY3VycmVudCAwIDMgMC4wMSA6dm9sdGFnZV1dCiAgICAgWzpkaXYKICAgICAgIlJlc2lzdGFuY2U6ICIgKC50b0ZpeGVkIHJlc2lzdGFuY2UgMikgIiIKICAgICAgW3NsaWRlciBvaG1zLWRhdGEgY2FsYy1vaG1zIDpyZXNpc3RhbmNlIHJlc2lzdGFuY2UgMCAxMDAgMSA6dm9sdGFnZV1dXSkpCgooZGVmIHJvb3QgKG9yCiAgICAgICAgICAgIChqcy9kb2N1bWVudC5xdWVyeVNlbGVjdG9yICIjY29udGFpbmVyIikKICAgICAgICAgICAgKGRvdG8gKGpzL2RvY3VtZW50LmNyZWF0ZUVsZW1lbnQgImRpdiIpCiAgICAgICAgICAgICAgKHNldCEgLWlkICJjb250YWluZXIiKQogICAgICAgICAgICAgIChqcy9kb2N1bWVudC5ib2R5LnByZXBlbmQpKSkpCgooZGVmIHZkb20gKGF0b20gKHBhdGNoIHJvb3QgKGNyZWF0ZS1ub2RlIFtvaG1zLWxhdy1wYWdlXSkpKSkKCihkZWZuIG1vcnBoIFtdCiAgKGxldCBbbmV3IChjcmVhdGUtbm9kZSBbb2htcy1sYXctcGFnZV0pXQogICAgKHBhdGNoIEB2ZG9tIG5ldykKICAgIChyZXNldCEgdmRvbSBuZXcpKSkKCihhZGQtd2F0Y2ggb2htcy1kYXRhIDpzdGF0ZSAoZm4gW18gXyBfIF9dCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChtb3JwaCkpKQ%3D%3D. • https://squint-cljs.github.io/squint/?src=KHJlcXVpcmUgJ1siaHR0cHM6Ly9lc20uc2gvcHJlYWN0IiA6cmVmZXIgW2ggcmVuZGVyXV0pCgo7OyAtLS0gSGljY3VwIC0%2BIFByZWFjdCBlbGVtZW50IGNvbnZlcnRlciAtLS0KKGRlZm4gaGljY3VwLT5wcmVhY3QgW3hdCiAgKGNvbmQKICAgIChvciAoc3RyaW5nPyB4KSAobnVtYmVyPyB4KSkgeAogICAgKHZlY3Rvcj8geCkKICAgIChsZXQgW1t0YWcgJiBhcmdzXSB4CiAgICAgICAgICBbYXR0cnMgY2hpbGRyZW5dIChpZiAobWFwPyAoZmlyc3QgYXJncykpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhjbGotPmpzIChmaXJzdCBhcmdzKSkgKHJlc3QgYXJncyldCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3t9IGFyZ3NdKV0KICAgICAgKGlmIChmbj8gdGFnKQogICAgICAgIChoaWNjdXAtPnByZWFjdCAoYXBwbHkgdGFnIGFyZ3MpKQogICAgICAgIChoIHRhZyBhdHRycyAobWFwdiBoaWNjdXAtPnByZWFjdCBjaGlsZHJlbikpKSkKCiAgICA6ZWxzZQogICAgKHRocm93IChqcy9FcnJvci4gKHN0ciAiSW52YWxpZCBoaWNjdXA6ICJ4KSkpKSkKCjs7IC0tLSBBcHBsaWNhdGlvbiBzdGF0ZSAtLS0KKGRlZiBvaG1zLWRhdGEgKGF0b20gezp2b2x0YWdlIDEyIDpjdXJyZW50IDAuNSA6cmVzaXN0YW5jZSAyNH0pKQoKCjs7IC0tLSBQdXJlIGNhbGN1bGF0aW9uIGxvZ2ljIC0tLQooZGVmbiBjYWxjLW9obXMgW3s6a2V5cyBbdm9sdGFnZSBjdXJyZW50IHJlc2lzdGFuY2VdIDphcyBkYXRhfV0KICAoaWYgKG5pbD8gdm9sdGFnZSkKICAgIChhc3NvYyBkYXRhIDp2b2x0YWdlICgqIGN1cnJlbnQgcmVzaXN0YW5jZSkpCiAgICAoYXNzb2MgZGF0YSA6Y3VycmVudCAoLyB2b2x0YWdlIHJlc2lzdGFuY2UpKSkpCgoKOzsgLS0tIFNsaWRlciBjb21wb25lbnQgLS0tCihkZWZuIHNsaWRlciBbdGhlLWF0b20gY2FsYy1mbiBwYXJhbSB2YWx1ZSBtaW4gbWF4IHN0ZXAgaW52YWxpZGF0ZXNdCiAgWzppbnB1dCB7OnR5cGUgInJhbmdlIgogICAgICAgICAgIDp2YWx1ZSB2YWx1ZQogICAgICAgICAgIDptaW4gbWluCiAgICAgICAgICAgOm1heCBtYXgKICAgICAgICAgICA6c3RlcCBzdGVwCiAgICAgICAgICAgOnN0eWxlIHs6d2lkdGggIjUwJSJ9CiAgICAgICAgICAgOm9uSW5wdXQgKGZuIFtlXQogICAgICAgICAgICAgICAgICAgICAgKGxldCBbbmV3LXZhbHVlIChqcy9wYXJzZUZsb2F0ICguLiBlIC10YXJnZXQgLXZhbHVlKSldCiAgICAgICAgICAgICAgICAgICAgICAgIChzd2FwISB0aGUtYXRvbQogICAgICAgICAgICAgICAgICAgICAgICAgIChmbiBbZGF0YV0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICgtPiBkYXRhCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChhc3NvYyBwYXJhbSBuZXctdmFsdWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChkaXNzb2MgaW52YWxpZGF0ZXMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGMtZm4pKSkpKX1dKQoKCjs7IC0tLSBQYWdlIGNvbXBvbmVudCAtLS0KKGRlZm4gb2htcy1sYXctcGFnZSBbXQogIChsZXQgW3s6a2V5cyBbdm9sdGFnZSBjdXJyZW50IHJlc2lzdGFuY2VdfSBAb2htcy1kYXRhXQogICAgWzpkaXYKICAgICBbOmgzICJPaG0ncyBMYXcgQ2FsY3VsYXRvciJdCgogICAgIFs6ZGl2CiAgICAgICJWb2x0YWdlOiAiICgudG9GaXhlZCB2b2x0YWdlIDIpICJWIgogICAgICBbc2xpZGVyIG9obXMtZGF0YSBjYWxjLW9obXMgOnZvbHRhZ2Ugdm9sdGFnZSAwIDMwIDAuMSA6Y3VycmVudF1dCgogICAgIFs6ZGl2CiAgICAgICJDdXJyZW50OiAiICgudG9GaXhlZCBjdXJyZW50IDIpICJBIgogICAgICBbc2xpZGVyIG9obXMtZGF0YSBjYWxjLW9obXMgOmN1cnJlbnQgY3VycmVudCAwIDMgMC4wMSA6dm9sdGFnZV1dCgogICAgIFs6ZGl2CiAgICAgICJSZXNpc3RhbmNlOiAiICgudG9GaXhlZCByZXNpc3RhbmNlIDIpCiAgICAgIFtzbGlkZXIgb2htcy1kYXRhIGNhbGMtb2htcyA6cmVzaXN0YW5jZSByZXNpc3RhbmNlIDAgMTAwIDEgOnZvbHRhZ2VdXV0pKQoKCjs7IC0tLSBSb290IG1vdW50aW5nIC0tLQooZGVmIHJvb3QgKG9yIChqcy9kb2N1bWVudC5xdWVyeVNlbGVjdG9yICIjY29udGFpbmVyIikKICAgICAgICAgICAgICAoZG90byAoanMvZG9jdW1lbnQuY3JlYXRlRWxlbWVudCAiZGl2IikKICAgICAgICAgICAgICAgIChzZXQhIC1pZCAiY29udGFpbmVyIikKICAgICAgICAgICAgICAgIChqcy9kb2N1bWVudC5ib2R5LnByZXBlbmQpKSkpCgoKKGRlZm4gcmVuZGVyISBbXQogIChyZW5kZXIgKGhpY2N1cC0%2BcHJlYWN0IFtvaG1zLWxhdy1wYWdlXSkgcm9vdCkpCgoKKGFkZC13YXRjaCBvaG1zLWRhdGEgOnJlbmRlcgogICAgICAgICAgIChmbiBbXyBfIF8gX10gKHJlbmRlciEpKSkKCgoocmVuZGVyISk%3D - Smallest app around 7.26kb • Still most excited by Eucalypt, the reagent clone in squint which comes in around 9kb for the smallest app.

Chris McCormick 2025-10-23T13:10:04.947309Z

Thanks for doing this research - super interesting. I created an issue to investigate Eucalpyt + snabbdom (test replacing the patching or more with it).

borkdude 2025-10-23T13:13:09.394619Z

could be nice

borkdude 2025-10-23T13:13:23.961159Z

but I also find it pretty cool that eucalypt has its own patching

borkdude 2025-10-23T13:17:49.039849Z

I guess when going with snabbdom you still have to write a large bunch of code to make it into reagent which can easily exceed the 3kb? We’ll have to see

👍 1