{"id":25135062,"url":"https://github.com/elricmann/render","last_synced_at":"2025-04-24T00:42:49.712Z","repository":{"id":258809534,"uuid":"873659187","full_name":"elricmann/render","owner":"elricmann","description":"Experimental JavaScript UI library","archived":false,"fork":false,"pushed_at":"2024-12-29T04:37:11.000Z","size":1035,"stargazers_count":31,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-10T18:56:37.166Z","etag":null,"topics":["javascript","rendering","typescript","ui","virtual-dom","virtual-machine","webassembly"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/librender","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elricmann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["elricmann"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2024-10-16T14:20:43.000Z","updated_at":"2025-03-21T14:05:30.000Z","dependencies_parsed_at":"2024-11-16T22:32:57.181Z","dependency_job_id":"6dee1641-fe5a-43bf-b87f-0f2470d3e2f3","html_url":"https://github.com/elricmann/render","commit_stats":null,"previous_names":["elricmann/render"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elricmann%2Frender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elricmann%2Frender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elricmann%2Frender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elricmann%2Frender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elricmann","download_url":"https://codeload.github.com/elricmann/render/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250540939,"owners_count":21447426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","rendering","typescript","ui","virtual-dom","virtual-machine","webassembly"],"created_at":"2025-02-08T16:18:07.042Z","updated_at":"2025-04-24T00:42:49.693Z","avatar_url":"https://github.com/elricmann.png","language":"TypeScript","funding_links":["https://github.com/sponsors/elricmann"],"categories":[],"sub_categories":[],"readme":"\u003ch3\u003erender\u003c/h3\u003e\n\n\u003cimg align=\"right\" width=\"100\" height=\"100\" src=\"/.github/logo.png\"\u003e\n\nExperimental JavaScript UI rendering library. Render uses a lightweight stack-based VM with minimal opcodes to encode DOM trees and run DOM operations either immediately or in retained mode (by diffing and patching bytecodes). Components are defined as **views** that serialize their attributes and children into `Uint8Array` instances.\n\n### Installation \u0026 usage\n\n```\nnpm install librender\n```\n\nRefer to the [wiki](https://github.com/elricmann/render/wiki) for basic usage and API documentation.\n\n\u003e [!Note]\n\u003e\n\u003e _The documentation starts from the v0.2 release of Render, which will not cover `librender` usage in other languages (until API stability towards 1.0). For a basic introduction to this library, refer to the wiki._\n\n### Features\n\n- [ ] Views\n  - [x] `View` - view instance serializer\n  - [x] `Text` - static text view with title\n  - [x] `Button` - static button with label\n  - [x] `Container` - dynamic view with optional attributes (e.g. tag name)\n  - [x] Tags corresponding to semantic elements (`Container`)\n  - [x] Attributes on views (`attr` method), deprecate opcode for inline styles\n  - [x] Event listeners on views (`Container`)\n  - [x] JSX elements, attributes and expressions\n- [ ] Virtual machine DOM\n  - [x] Create DOM nodes (`OPCODE_CREATE_ELEMENT`)\n  - [x] Decode 8-bit entries with static offsets (UTF-16 character codes)\n  - [x] Set DOM node attribute to least recent node (`OPCODE_SET_ATTRIBUTE`)\n  - [x] Append least recent nodes as parent-child (`OPCODE_APPEND_CHILD`)\n  - [x] Create DOM text node (`OPCODE_TEXT_NODE`)\n  - [ ] Set `innerHTML` with in-memory string source\n  - [x] Append adjacent DOM nodes as siblings (`OPCODE_APPEND_SIBLING`)\n  - [ ] Diffing and patching arbitrary bytecodes (partially complete)\n  - [x] Event listeners on least recent node (`OPCODE_EVENT_LISTENER`, requires `__eventStore`)\n- [x] Consistency in rendering with timed `requestAnimationFrame`\n- [x] Streaming instruction blocks to VM (`createBytecodeStream`, `unsafe_streamBytecodeToVM`)\n- [ ] Non-tracking reactive primitives in views\n- [ ] Precompiled bytecode from views (requires build tools)\n- [ ] Off the main thread view serialization (`ThreadView`)\n\n### Quick overview\n\nRender relies on **views** to return byte arrays with exact alignment of data values and offsets. The VM does not _fix_ program inputs which is why views form safe high-level wrappers representing extendable components. Aside, the default settings are supposed to be configurable.\n\nPortability is the primary goal of this library. I wrote `librender` expecting that there could be a **single optimizing bytecode IR** for various web-based rendering libraries. To this effect, there is an imperative-procedural approach when defining view methods that correspond to raw bytecode.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/.github/graph.png\"\u003e\n\u003c/p\u003e\n\n#### Completeness of the virtual machine\n\nThe VM does not fully take the role of a DOM-based model and opcodes are only limited to DOM operations where inputs are serializable (e.g. event handlers are _not_ serializable). It lacks features like pausability and resumability, async batch streaming, per-batch scheduling, and virtual prioritization, that could essentially improve rendering.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/.github/vm.png\"\u003e\n\u003c/p\u003e\n\nThe structural description of the VM is:\n\n- The **stack** is reserved for holding references to handlers and raw strings\n- The **memory** applies to enabled shared memory (e.g. temporal view states) between VM instances\n- `nodeCount` is a counter that allows managing the `nodeIndexStack` in the DOM operations\n\n#### Portability of the bytecode IR\n\nWebAssembly modules are loaded as view slices into an array buffer representing a linear memory model. Since modules are precompiled, the bytecode could target `librender` with virtually no overhead. This would imply that optimizing the VM itself from the JavaScript source would improve existing programs without introducing layers of indirection.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"/.github/portable.png\"\u003e\n\u003c/p\u003e\n\nWith this enabled, various high-level libraries targeting the bytecode can be used as microfrontends with predictability. Currently, `librender` is barely useable so this will require major effort to put in place. Additionally, certain data structures can be linearly represented for uniformity, e.g. C-like structs with offsets require no deallocation in WebAssembly. Growing memory is as easy as incrementing a pointer.\n\nPortability allows loading `.bin` files through a shared worker, which could be useful for monolithic SPAs that depend on server endpoints to fetch and render data in the main UI thread for client-side rendering.\n\n### Acknowledgements\n\nRender does not provide unique insights into the approach rendering is done or criteria for commiting DOM nodes for painting. Other libraries such as [React](https://react.dev/) (scheduling model) and [GlimmerVM](https://github.com/glimmerjs/glimmer-vm) (opcode-based rendering) are to be considered prior art in this regard.\n\n### License\n\nCopyright © 2024 Elric Neumann. MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felricmann%2Frender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felricmann%2Frender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felricmann%2Frender/lists"}