617 karma · joined November 11, 2015
One of the use cases for ST.js in Jasonette is dynamic client-side rendering, where it takes dynamic data and renders it against the template, after which it becomes native components.
Another use case is implementing actual functional programming. This one is not as straight-forward since it involves maintaining another separate state machine for function call stack. But this is also achieved using ST templates. Here's a blog post that talks about it in detail http://blog.jasonette.com/2017/02/15/functional-programming-... but it's a bit involved.
Also Jasonette has something called mixins, which you probably can guess based on its name. It lets you mix in JSON objects into another, so that you can make the app modular. That's also achieved internally using ST.
Overall, I believe even I'm just scratching the surface of what this can do, which is why I decided to take some time to clean things up and prepare and open it up as its own repo, because I think there's tons of other things that can be done by taking advantage of the fact that all that's happening is:
JSON A + JSON B = JSON C
Hope this makes sense!
Could you elaborate?
In essence ST.js is a finite state machine implemented purely in JSON. So I can imagine it being used for things I haven't thought of, which is why I open sourced it. Would be really cool.
Please feel free to reach out at ethan.gliechtenstein[at]gmail thanks!
I thought I would provide some context on why I wrote this library, and how I'm using this right now. So here it goes:
Other than ST.js, I also work on another open source project called Jasonette (https://www.jasonette.com), which lets you write an entire native iOS/Android app in nothing but JSON markup.
And when you can express the entire app logic--from model to view to controller--in JSON, you can split them up whichever way you want and load them from anywhere (from a file, from cache, from a remote server, or from local memory).
But the biggest benefit of all is: you can load an entire ios/android native app from the server in realtime, just like how web browsers load HTML/JS/CSS in realtime.
When working on Jasonette, implementing model and view was relatively simple. For model it's natural since JSON is all about describing data. For view i just needed to come up with a syntax to describe layouts and all the standard mobile UI components in JSON.
However the biggest challenge was how do i actually describe functions in JSON. Without a function, it's just a mockup and won't really do anything meaningful.
Which brings us to ST.js.
When you think about what a function is, it takes one value and turns it into another. So basically what I needed to do was build something that will take one JSON, and turn it into another JSON, but most importantly I would have to do it using JSON. Basically I needed to implement a finite state machine in purely JSON.
And this is what templates do. So I set out to build a JSON template engine that turns one JSON into another using a template which itself is written in JSON.
What's really cool about this is, since the template is JSON (As far as I know there doesn't exist any prior art that uses JSON as a template, otherwise I would have used it instead), it has all the benefits of the JSON format itself:
1. You can store it anywhere (Most DBMS nowadays support JSON natively)
2. You can send it over the Internet
3. You can compose them easily
4. You can validate them using JSON schema
5. etc.
To use a more specific example, I use ST.js in both Android and iOS versions of Jasonette as the template engine. And a JSON template is absolutely necessary in this case.
For example, if I want to take a piece of device-generated data and render it, I need to be able to somehow parse it client-side (can't send it back to server to re-generate a JSON) http://docs.jasonette.com/templates/#3-device-api-generated-...
This also applies to many cases where the client-side data contains privacy-sensitive data. The only way to dynamically parse something that happens on the client side is by writing the template itself in JSON and sending it over as data.
Anyway, I hope you guys take a look at the examples on the homepage to get a glimpse of what makes ST.js powerful. Each example is almost its own library, except that you don't need a separate library for those purposes since all you're dealing with is JSON.
Basically you can send the JSON template over JSON to the server, and let the server transform the raw data using the template before returning.
The most important benefit here is that, since everything can be expressed in JSON, it can be stored or transmitted over the Internet, which enables interesting cases like this.
For background, I am working on a JS library called cell.js (https://www.celljs.org), which turns a JSON object into a dynamic web app.
Anyway, this particular app (HTML to JSON to DOM) takes any HTML, parses it into JSON, and feeds it to cell.js, which then turns it back to DOM again. I built it because sometimes I just want to take an existing HTML and transform it to JSON, so I can turn any existing website into cell, and it works pretty well for that purpose.
You can try copy and pasting any website HTML into it to see the effect, as shown at https://github.com/gliechtenstein/HTML2JSON2DOM. Hope you find it cool as well!
BTW shameless plug: If you're interested in this type of ideas, please also check out Jasonette (an open source project I'm working on) Just like this project uses "list" to describe an app, Jasonette uses JSON to describe an app. https://www.jasonette.com
And this is by design because the goal was to create complexity out of simplicity.
I believe this bottom up approach can be much more scalable in the long run than some frameworks that dictate every single detail you need to implement, because all organisms are basically built that way (cells make up body) and they seem to be working fine.
Personally the more I use this the more I find creative ways of using it, which is the beauty.
But I also do realize sometimes it's good to have some sort of "best practice" structure and I think people will figure it out eventually.
TLDR: I think you should be able to build all kinds of sophisticated apps with it because I believe emergence is the best way to construct something. if that's not the case, that doesn't mean the framework is a failure but just needs some tuning, which I believe is totally possible just because the library is so minimal. So please feel free to play with it and share if you run into trouble, we can evolve cell just like cells evolve in the real world.
But rest assured, the library itself is 100% es5.
btw could you share the link that's not working on IE11? I will fix it right away. Would appreciate it!
How it has a different architecture: https://github.com/intercellular/cell#so-how-does-it-work-ex...
What these architectural decisions mean and how they make a difference https://github.com/intercellular/cell#how-does-this-make-a-d...
I'm using some in-house library I built myself to run the webpage but hadn't realized it fails on an IE. Will fix it!
And when you come from that direction, Cell is a terrible framework that doesn't follow any best practices and does things in a weird way. But the thing is, Cell is fundamentally different from other approaches. That's why a lot of "best practices" don't apply and don't make sense for Cell.
If you go back in history, people hated angular because it went against the general wisdom of "separate view from logic", and react was shunned because it had some weird way of doing things. But I think they solve problems in unique ways that make peoples lives easier in different ways, and that's what matters at the end of the day.
And I am confident that Cell can make people's lives significantly easier in another different way. So I suggest you actually play around with the examples at https://play.celljs.org
Words don't mean anything really because the problem we're trying to solve is come up with a dead simple easy way to build web apps, which is not really easy to grasp when just thinking about theories. Hope this helps!
The whole point of cell is to build the simplest building block you can compose to build complex structures, and a lot of the problems faced by other traditional approaches can be tackled in a different manner using Cell.
From my experience I can build fairly complex apps without having to worry about all the problems you mentioned, they are just structured differently.
If you have time, I really suggest you try playing around with it, If you still don't like it you don't have to use it, but I'm sure it brings some interesting ideas to the table that cannot be experienced by just reading the homepage.
Hope this helps!
The inspiration was from real life cells. It's amazing how small autonomous cells bind and interact with one another to form a complex organism.
Cells have genotypes which manifest themselves into phenotypes. And a nucleus that self-controls the cell cycle.
I thought by creating a completely autonomous structure that mimics how cells work it will be possible to create complexity from simplicity.
i hear a lot of people saying this will never scale because it doesn't look like react or angular, but I think the point is not about what's missing, but what you can do with these by combining these self aware elements. I believe this approach is much more scalable because it builds on top of simplicity.
Again, thanks for the comment!
Just like you can build spaceships, police station, cars, and all kinds of complex things using lego blocks, you can build complex architecture using the simple building block that is cell.
I myself have been experimenting with different approaches of structuring apps using cell, and there are really a lot of different ways since we become free from having to inherit classes and instantiate objects from them. I don't want to be constraining about how one uses cell so I don't talk much about what a "best practice" is (yet)
But maybe sooner or later people can share some nice approaches for structuring "traditional apps" using cell
Also yes it is component based but it's a different type of component than other frameworks. Since cell has no classes to inherit (to get rid of dependency) you can write the entire app with stateless functions only. This scales better than class based approaches since functions don't have overhead and you can "componentize" anything.
Hope this makes sense! I did my best to explain these on the homepage but if some of them are not clear enough please let me know, I'll correct them!
Btw this is a very new framework so everything is a start. So if you have better ideas about dealing with certain problems please feel free to send pull requests or start a thread on github. Thank you!
Yes, there are LCS deduplication logic, synchronized DOM update, initializers, reactive updates, storing and mutating states, etc. They're all in there. They're just structured differently because it has a different architecture than existing frameworks.
The whole point of Cell is not trying to match feature by feature of existing frameworks like React/Angular/Ember/etc. And I am aware Cell doesn't look like most existing web app frameworks that follow best practices, because that's the point.
I did my best to explain the rationale behind all the design decisions on the homepage, could you take a look at those and let me know if you have questions? Thank you.
As for the "_" variables they are meant to have no side effect on the DOM directly and instead only trigger a function called $update() automatically, which is where you can deal with all the view stuff.
So the only thing you need to remember is to:
1. Declare whaterver "_" or "$" attribute you want to monitor initially on the genotype.
2. Once you have done that, every time you make a change to the underscore or $ variables, they automatically get queued up (via Nucleus) and trigger the $update() function right before the next render frame so they can be drawn all at once in a single frame.
There are different ways of doing this, you could directly touch the DOM attributes (without any prefix) or the $ variables and they will update the view from anywhere.
But personally my pattern when using Cell to write apps is to NOT directly touch the $ variables everywhere because it can be confusing, but instead keep the underscore variables as sort of a "model", and only touch those. And because updating a _ variable triggers an $update(), I can deal with all the view related stuff (changing the DOM attributes and $ attributes) in one place, inside $update(), which is the "reactive" feature. (But it's really up to you how you do it) You can learn more here https://github.com/intercellular/tutorial#2-update
Hope this helps!
p.s.
This document may be helpful in understanding the source https://github.com/intercellular/cell/blob/develop/GENESIS.m...
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!
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 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
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-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-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!
There are several ways to do this 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 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 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 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!
Here's why I started working on Cell: Aside from Cell, I am working on a project called Jasonette 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.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.