The secrets of Node's success
radar.oreilly.com
radar.oreilly.com
In this article, it's interesting that though "Node solves a problem" is stressed as key to its success, compared with the many other JS server-side projects, they don't explicitly mention the problem, except obliquely at the end! (The problem is efficiently handling massive concurrencies in network connections.)
It's because of this short-sightedness of programmers that there will always be easy pickings available to anyone who actually looks at problem. Be a problem-person, not a solution-person.
I still don't see a compelling reason to use node. I think the jvm is a better choice all around.
Ryan and team are talented people, but they're mostly dependent on the V8 team, which is focused on building a JavaScript interpreter for a browser. Node.js/V8 has come tremendously far in the last 18 months, but still hits some particularly nasty walls when it comes to massive concurrency and managing big pools of memory in non-trivial applications. It will take some serious time for these challenges to be overcome. The JVM, Erlang/OTP, and C are particularly good platforms for this type of software because they're mature and well tested in these environments.
I really hope for the sake of the project that the hype surrounding Node.js blows over and the hipster crowd moves on.
1) Utility libraries. I have a clone method I use a lot, an would work equally well in both environments. I'm sure math libraries would be the same way.
2) Models. Maybe. Personally, my server side models contain get and save methods which make database calls. I don't want or need those on the client side. If for no reason other than wasted bandwidth.
* note: I'm a node user, but I don't share any code between server and browser.
#if client
#if server
#endif
for the pieces that only apply to the client side or the server side, with shared pieces staying outside these "tags". I won't go back. This is especially cool as I have a templating system that can run on the server or on the client. So for JS-enabled browsers, all HTML template rendering is done on the client by building all HTML tags out of very small simple JSON structs. For non-JS clients (spiders, bots, paranoid non-JS enterprise legacy browsers) the "pages" get fully rendered old-school by the server-side -- both sharing the same rather simple custom-made JSON-driven templating functions and producing essentially almost the same HTML output. Of course there are some added complexities going on with things like scripted onclicks, but you get the general idea. (This is mostly done for indexing spiders and human non-JS clients just simply have to put up with a limited, degraded, basic experience.)
- Input Validation
- Asynchronous loop patterns
- Promise pattern implementations
- markup logic & output
- A* pathfinding
More and more use cases will pop up over time, and it's really unique to the node.js environment. This alone would not make me pick node.js over another solution but I feel it is still an advantage.
I spend about 50% of my dev time on writing / working with utility libraries as writing these libraries takes far more effort than writing handlers, models, etc.
Validation on the client is primarily a user experience concern,
where you focus on bringing attention to problems with a form, and
helping the user resolve those problems.
Once the form is submitted, if you’ve done thorough client-side
validation you can also avoid friendly server-side validation. Of
course all your client-side validation could be avoided through a
malicious client, but you don’t need to give a friendly error
message in that case, you can simply bail out with a simple 400 Bad
Request error.
At that point there’s not much in common between these two kinds of
validation — the client is all user experience, and the server is all
data integrity.This is not easy by just using Node, and it's not necessary that the language you use is Javascript. A better approach IMO is that you have a language X that is nicer than Javascript, and compiles both to server side code and client side Javascript.
For the case of validation here is a hypothetical language (ignore the bad regex):
<form action="/foo/bar">
<input type="text" name="email" />
<%= if not email ~ "[a-z]+@[a-z]+.[a-z]+": invalid("Email is not valid") %>
<submit>
</form>
From this code you could generate real time JS validation and server side validation.Another example: validation. You want to validate on the client for responsiveness, but on the server for integrity.
Being able to reuse content generating code can be especially useful when you don't realise that you will need it on both the client and server when you write it, or you have to move it from one to the other.
Otherwise, you really have no excuse for putting logic on the client. Even with something like validation, I think its much more sensible to have your renderers pump out generic validation event handlers than to reconstruct the whole model class on the client.
Obviously then you'd need some way of distinguishing validation that is only important to one of the two ends from that which is meaningful to both, but I can see it being possible.
That said, I'm still not convinced it's worth it. Especially when you look at the state of libraries in node compared to something like Python/Ruby.
These can just as easily be described using RDFa as using TAL or Jade or whatever. The benefit of RDFa is that the templating information stays with the page, so client-side can also utilize it.
The library I made for this is https://github.com/bergie/VIE
Blazingly so.
I've got a PHP project at http://fstr.net and its pageloads take about 4 to 5 seconds under normal load. With my other project pageloads are less than a second most of the time (though there seems to be some variability when dealing with the first connection).
Both projects do essentially the same thing (query database, present list). It's really shocking just how much faster node.js is.
Another nice aspect of NODE with a MongoDB solution is that I can scale it very easily. On AWS I can send all traffic into a load balancer, then as the server's load increases I can just fire up additional (CLONE) instances and add them to the load balancer.
A reserved Amazon micro instance costs ~$5 per month or a 'high CPU' instance comes in at $17. Scaling node is really as easy as turning on another machine (or running multiple instances of the application on a machine with multiple cores).
Yes, the V8 engine is fast. That's what it's designed for. But that's only remarkable because it's a JavaScript engine. You can get the same performance from Go (with better memory utilization to boot) or even Java.
Whatever language you are using, if loading a page takes >1 second, you are doing something very wrong.
I have built web apps out of shell scripts that perform hundreds of forks and open dozens of files per request, and still easily managed <200ms response times while running on a crappy xen server.
With how much concurrency?
I mean if I'm doing something wrong in PHP, then I'll likely make the same mistakes in node.
You are right though, PHP+apache can be just as fast as anything else. I'm told that apache has a lot of overhead because of all the modules that come enabled by default. Apparently by removing all but what you need, you get a system that's a lot faster.
That's a bit more advanced though - while node's quick by default.
Anyways, I'm far from a language zealot in any way. I've loved every language that I've worked in.
I'd love t see some of the stuff you're talking about that's lightning fast with hundreds of forks... sounds like something I could learn from :)
Anyway, I think we all want to know more about those forking web apps you've made. They sound quite impressive.
Now to contrast this with python: I personally have never heard of Twisted before all the talk of Node came about. Mind you, I'm not a python developer and if someone's blog title doesn't grab my attention by having some connection to me, or what I do, I'll probably just skip over it.
I have deployed services using both twisted and node - some off the cuff points:
- Twisted is large, and includes many new concepts and vocabulary, with somewhat patchy documentation. There is a big hump to climb over before being productive. I was pretty much there with node on one 35 minute train ride.
- The twisted async. mantra only flies within the (albeit large) twisted cloud of classes. I often find myself deferring to threads etc. for synchronous file IO etc.
- Writing plugins for node is very approachable (including things that interact with the event loop). I use ctypes + .so for the same work in python land, but it took some experimentation and discovery (albeit not very difficult) to arrive at a good pattern for this.
Once you understand it - twisted is an enormously powerful resource, and I am still writing complex services using it. Node gets used for wrapping up computation services.
I've never heard of twisted - but I feel like I'm getting in on the ground floor with node. Additionally, I was positively salivating to learn a new language when it started 'emerging'.
I think part of it comes down to the fact that I was already very comfortable with Javascript, so I started with node.js knowing that I at least knew some of the basics ... and thank got I did, because programming in node is very different from what I'm used to.
It's sometimes difficult to know which lines of code are blocking and which aren't.
This means that content can flow through a node service with being touched by javascript, and without adding work to the garbage collector.
There isn't a huge performance gap between the two engines these days... But V8 is easier to embed in C++, I think.