7 ms·
Show HN: Cell.js – A Self-constructing web app framework
- teyc 9y agoInteresting, but I get worried every time I see that code refer to specific DOM id. It's probably ok for simple programs where there is only a handful of elements. When the program gets larger, you will still need architectural pieces to coordinate data. You've put a lot of work into this, and there are a lot of examples that are helpful to anyone who wants to evaluate it. I'm curious what is the motivation behind this design - besides zero framework ? - is this in-use in production any where?
- gliechtenstein 9y agoThanks! Zero framework is just one of the distinct traits that makes Cell special. Here's why I started working on Cell: Aside from Cell, I am working on a project called Jasonette http://jasonette.com/ http://jasonette.com/ which lets you build build cross platform iOS/Android native mobile apps by writing just a JSON markup. I have recently started working on a web version of Jasonette, so that a single JSON markup can run exactly the same on iOS, Android, and the Web. I tried implementing it with most of the existing popular JS frameworks but found that they don't fit the bill. They are too complex to fit Jasonette's philosophy of placing simplicity and ease of use as top priority. Also Jasonette is great for decentralized apps, but the centralized nature of all existing frameworks and approaches wasn't compatible with what I was trying to achieve. Cell doesn't just make things easier, but is designed fundamentally different from traditional MVC frameworks. I think this image does a good job of explaining: https://s3-us-west-2.amazonaws.com/fm.ethan.jason/domtree.jpg https://s3-us-west-2.amazonaws.com/fm.ethan.jason/domtree.jp... Instead of creating a centralized control mechanism, Cell lets you inject M-V-C (or anything else you want to) directly into each HTML element, thereby decentralizing the control. I think this will enable a lot of creative things and design patterns going forward (which I'll demonstrate first with Jasonette-Web). As for using querySelectors, I totally get it, because that was my initial feeling as well. Initially I also felt like accessing elements directly was a step backwards (because we've become accustomed to the "new" approach where we keep a separate data structure that binds with the DOM, and directly accessing the DOM feels like what we used to do with jQuery) But Cell's approach brings its own benefits. First, as I mentioned the control logic can be decentralized. Second, all the complexities of model-view binding goes away because the very concept of binding existed because they were separate. In case of Cell, the element can "contain" its own model/view/controller, and because it contains them there's no need for binding, which is one reason why Cell can stay simple. Another factor is this architecture effectively turns each element into an app execution container of its own, so these components can be extremely modular and portable. You mentioned when the app becomes larger we'll need some architectural pieces to coordinate data, and you are right, except that the same logic applies here too. The "architecture" is the DOM tree itself. So the root element can contain the root model, and the descendants can access it as well as keep their own version of the model, so forth. I tried my best to explain all these concepts on the homepage but I do realize it's a long read, so I hope this explanation makes enough sense. TLDR: it requires a bit of stepping back and reframing what we've been accustomed to but I'm confident this new approach brings a lot of benefits that weren't easy to implement before.
- mnishihan 9y agoHow does it scale? Anti pattern is sometimes useful & obvious, but going with anti patterns for everything is a stupid decision IMO. Frameworks are for greater good. If you don't need it, don't use any of them. But when "No framework" is listed as a key Mantra for yet another js library, I simply find it as dumb & full of madness. :-/
- gliechtenstein 9y agoWhat I meant by "No framework" was that there is no "Framework API" to implement. Cell itself is a framework, so I agree that frameworks are for greater good. As for your question on how it scales, I don't see a reason why it shouldn't scale. In fact I think this approach is more scalable than any existing centralized approaches to building web apps because you can create complexity out of simplicity. p.s. The "No framework" part is just one of the benefits that arise as a side effect of Cell's decentralized architecture. I did my best to explain why I built this on the homepage. I know it's long but I hope you take a look at it once more, it's worth a read even if you don't use the framework because Cell does bring something new to the table. Hope this makes sense!
- shakna 9y agoJS frameworks and SEO have a rough history. Pre-rendering tends to be the workaround, but Cell's lack of hierarchy might make that more difficult than normal. How would you work around it?
- gliechtenstein 9y agoCell itself does not have a structure. But the point is that you can easily create a structure by composing cells. The DOM tree itself is a structure, and Cell is designed to let developers take advantage of that instead of creating a virtual DOM or stuff like that (without side effects). Put it another way, you can create a fully centralized architecture using Cell. One way of doing it is taking advantage of Cell's context inheritance feature https://github.com/intercellular/tutorial#b-context-inheritance-and-polymorphism https://github.com/intercellular/tutorial#b-context-inherita... but there can be many different ways. The whole point of Cell is to exist as a minimal decentralized framework which you can utilize to do things your way. The benefit is you have the ability to create a completely decentralized DOM tree, as well as create a centralized one. As for the SEO issue, I have two answers: 1. Pre-rendering on Cell is just a matter of transforming JSON into HTML (but instead of using something like JSDOM on to create an entire DOM on the server-side, you could just directly map the JSON into HTML. I actually have a piece of code that does that as well but haven't released it yet. 2. Handling pre-render is simpler than other frameworks because Cell can seamlessly plug into an existing DOM tree https://github.com/intercellular/cell#b-plug-into-existing-websites-like-a-widget https://github.com/intercellular/cell#b-plug-into-existing-w... (it's actually one of the selling points of Cell because no other framework makes this easy. If you have a static website and just want to integrate a dynamic widget, there's no simple way to do so using most of the popular frameworks because all of them basically take over the entire frontend and you have to switch to that framework entirely just to add that widget, or you need to use webpack, browserify, etc. to package them up just so you can use it on the frontend as a bundle.js. This is also not the most user-friendly way. Cell makes this super easy because there is no dependency and no code packing process) Hope this answers your question!
- satyrnein 9y agoLet's say you pre-render the DOM nodes on the server. At that point, there's no need to create them again in the browser from the JSON object. How would you augment them to become Cells?
- hannofcart 9y agoAfter having looked through the tutorials, I am unclear about the following: 1) How does one cell send messages to another. I suppose this is left to the application? 2) How do you test code written in Cell.js? It appears to me that this is going to be hard to do? 3) Is it intended that the entire webapp code be a single JS file? I guess one would need a server side build step to "assemble" multiple Cell.js components into a single one?
- gliechtenstein 9y ago1) How does one cell send messages to another. I suppose this is left to the application? There are several ways to do this https://github.com/intercellular/tutorial#3-inter-cellular-communication https://github.com/intercellular/tutorial#3-inter-cellular-c... I'm sure there are other ways of doing this in more creative ways, which was my intention when I was designing this to be as simple and modular as possible. Another thing is, I say Cell has a decentralized architecture, but that doesn't mean it only lets you build apps that way. The point is you can construct these decentralized cells in any way you desire to build apps. So you could build a perfectly centralized architecture with Cell as well. 2) How do you test code written in Cell.js? It appears to me that this is going to be hard to do? What I think is really cool about this approach is you are effectively expressing an entire app as a piece of data https://github.com/intercellular/cell#3-app-as-data https://github.com/intercellular/cell#3-app-as-data I think this concept needs some time to sink it at first, but once you get it, it opens door to a lot of creative ways of structuring your app. For starters, any Javascript object can be composed/manipulated/constructed with a function. And since you can express not just data but also the app logic itself as data, you can do the same with stateless functions. So YES, you can unit test your Cell apps. In fact it's easier than any other existing frameworks since the entire app is built with functional programming (no stateful class objects). You can write a whole bunch of functions to construct/manipulate these "Genotype" objects and unit test those functions to make sure they behave correctly. Hope this makes sense. 3) Is it intended that the entire webapp code be a single JS file? I guess one would need a server side build step to "assemble" multiple Cell.js components into a single one? Nope, the only reason I packaged them as a single file at https://play.celljs.org https://play.celljs.org was just to make it easier to understand as a demo (because splitting out into multiple files makes you jump back and forth and is not ideal when you're just trying to have a quick overview of the app structure). But the beauty of this approach is, at the end of the day, all you need is a JSON-like object that defines the looks and behaviors of your HTML nodes throughout the DOM tree. Which means in real life, you would be splitting these out into as many functions as you want (In fact this is one of the strongest selling points of Cell. you can create as many of these functional components as you want without overhead compared to other class based frameworks) Really at the end of the day all you need is a function that generates the Javascript object structure you need, which means you can map/filter/reduce anything from Model to View to Controller logic. Here's an example I was working on yesterday https://github.com/intercellular/jsonschema https://github.com/intercellular/jsonschema It's a JSON schema validator, still work in progress since I just started it yesterday but you get the point. Hope this was helpful. Please feel free to ask more questions!
- dgreensp 9y agoThis is a thought-provoking new framework, thank you! It's novel and easy to understand. Having worked on sophisticated React apps, I've come to understand the benefits and shortcomings of its architecture. One insight is that properly encapsulating UI components and their behaviors leads directly and naturally to nested state machines. React is cleanest if you have one state machine, or N independent global state machines, that drive your app. Once you start trying to compose state machines to make a sophisticated UI, you end up in setState/callback hell, and then you try the Redux/Elm model, in which states are composed to make bigger states. I think it's fruitful to experiment with ways of composing state machines in which you don't just glue the states together, but you let the machines interact. Of course you still want to keep your program easy to reason about and avoid spaghetti, but I'm sure there are interesting patterns lurking there. Another issue is components in React aren't supposed to address each other. You can easily call methods on your children using refs, though this is discouraged and interacts badly with the update cycle and higher-order components. Components not talking directly to each other is a great feature right up until it's not, such as when you have to deal with focus and selection changes. You're forced to contemplate taking what you thought of as pure UI state -- local to a component and tied to that component's lifecycle -- and moving it outside of React into a store whose structure parallels the component tree (which in turn parallels the DOM), just so that you can traverse it in a reasonable fashion and update it synchronously while DOM updates remain asynchronous. In Cell.js, these three trees become one.
- gliechtenstein 9y agoThank you, I think you pretty much nailed it! This architecture may not be very obvious to many people at this point but I believe it can enable a lot of interesting use cases (as well as being able to deal with even traditional app structures in more efficient and cleaner ways) One example is my own use case, where I'm working on a web version of Jasonette https://www.jasonette.com https://www.jasonette.com I couldn't find any existing framework that can achieve what I was trying to without becoming very complex. Thank you for the encouragement, you made my day :D
- dgreensp 9y ago
- revmoo 9y agoThis is neat. I built something a little more complex for work; it is a bootstrap based dynamic form engine, basically you uee JSON to define any one of about 12 form elements, even things like jsgrids or file upload boxes, and add validation rules / regex, layout rules etc. The app then builds all of the CRUD aspects automatically. It is making my life very very easy, as we have to build a lot of massive order forms at my ch ompany with over a hundred unique fields. Also built a PDF generator that pulls the form elements in as tokens to do mail mergy kind of stuff. It is the best project I have built in my career, really want to try and get it open sourced.
- meekaaku 9y agoThis is interesting. I have had a look at the examples. One question that comes to mind, how do you make a reusable component? Say I have: Part = { $cell: true, $type: "h2", $text: "Part No: ", } Part is to be instantiated multiple times in the same page, but I want different $text. How do I pass this data?
- tmzt 9y agoIt seems to use functions for that purpose, look at the example with map. I really like the linked to Android/iOS implementation of this concept.
- meekaaku 9y agoOk. I found a way using factory: ItemMaker = function(data){ return { $cell: true, $type: "h1", style: "font-size: 100px;", $text: data, } } var i1 = ItemMaker('foo'); var i2 = ItemMaker('bar')
- ezekg 9y agoInteresting. Though not really clear why you continuously say "no API!" when you have an API--it's just in the data itself via your "special keywords" i.e. $cell, $update, etc. That's kind of like saying React components have no API since you never actually call e.g. componentDidMount directly.
- xcopy 9y agoLike