Hacker News new | past | comments | ask | show | jobs | submit login
Server-side view or client-side MVC? (kailuowang.blogspot.com)
71 points by kailuowang on Feb 26, 2013 | hide | past | favorite | 56 comments



I would argue that the greatest benefit that client side MVC frameworks bring is that they enforce a clean RESTful API on the server. At a panel on MV* frameworks at HelsinkiJS last week somebody even said that they had to dramatically improve their API to make it work with Ember.

I myself have been working on https://starthq.com which started life as a single page app using AngularJS where most of the functionality was behind a login. It has now pivoted into a web app directory, where delivering the initial page quickly and in a way that Google can easily index is crucial & there's very little actual input validation or interactivity on the page. The nice thing is that despite this transition, the core API has remained the same regardless of where the view is rendered and the architecture is all the better for it.

Give it a go and see if you can tell which pages are rendered entirely on the server and which entirely on the client.


I agree. You always need a clean api to allow for multiple front-ends and to have a secure boundary layer between trusted and untrusted data. Even if the rendering happens on the server, you should always start with an api.

I work on a 400 kloc app developed with a client-side mvc + web services architecture. The nice thing I've learnt about having a proper services api is that slapping another front-end on top of it is straightforward. We've had a relatively easy time building mobile apps thanks to having the service api ready. And because the core app is built around the same services, they are less likely to break.


I agree and would rephrase it as client side frameworks help to enforce a clean and well defined API on the data, thus help to separate the business logic from representation / interaction, which is kind of the original goal of MVC.


     True this maybe achieved by refreshing the whole
     comments container   but what if he is also in the 
     middle of replying to another comment? What if we want 
     that new reply to show up in some sort of animation? 
You can achieve this pretty easily. You shouldn't be refreshing the entire comments container. If your views are well modularized, the comments container would render many _comment partials. You would simply render a new partial and insert it into the page appropriately. There's no reason to disrupt the rest of the page.

When you do client-side MVC, you end up having to duplicate a lot of your model and controller logic. This happens either explicitly, when you start defining relationships between models and how they should react to changes in associated models (e.g. backbone-relational), or implicitly, when it gets stuffed into view and "routing" logic (and leaving you with spaghetti code that's different but no better than jquery spaghetti). In rails views, you have access to the real model objects and you can still use AJAX to have a "single-page application" without the huge added complexity.

There's obviously a place for client-side MVC and that is RICH APPLICATIONS. Google Docs, Pandora, a photo editor, etc...

I think another factor is what your team looks like. If the person writing the models and controllers is the same guy making the front end, then you should probably stay away from client-side MVC. If you have dedicated frontend/javascript guys, then it might make more sense..


The point is that if you need granular partial refreshment, your javascript needs to be a lot more smart, like what to do when add/update/remove a comment - that is you end-up writing view logic both client-side and server-side. As stated in the article, the view logic needs access to both server-side data and client-side DOM, where it resides depends on which side the view logic requires more communication. The argument is that if you rethink HTML, then most web app should be designed in a way so that UI interaction significantly improves the UX. That's why we need client-side MV* to be an enabler for such re-thinking.


Our main product is at it's heart nothing more than CRUD, except some of the forms are pretty complicated where you have to deal with nested record hell. Initially we just did everything the Rails way (i.e. jQuery and AJAX), but we have been looking to move stuff more MV* client side where possible.

I don't think either solution is really that great at the moment. Doing things MV* client side mean you duplicate views and potentially logic (we use decorators a lot which would need to be duplicated). Doing things via AJAX means you have to wait for the response before the view is updated (things like comments that will succeed - assuming validations are done before the request is made, and the server doesn't break - shouldn't have this delay).

One thing we have done that has helped, is instead of just attaching a load of jQuery events on random elements, is writing our Javascript in a similar style to Backbone views. Instead of writing everything with lots of nested events, we have a 'controller' responsible for each feature. On initialisation it binds to the DOM events it needs, and those call other methods on the controller. It also has it's own (local) state, so if we need to use the same feature multiple times on a page we can do with ease. It has allowed us to separate code better, and more importantly make it more legible. Here is an example:

https://gist.github.com/lucaspiller/5040983


The whole point of node.js/meteor is that you can share the code between client/server, so you dont have to duplicate anything, and have the access to the "real" model.


1. Do not take this statement for granted: "When your page is simple, yes, you don't need that much interactivity. But the market will demand more and more functionality on that page." Simple, fast apps that don't overdose on interactivity seem like a better bet. The vast majority of problems being solved with software do not require the bells and whistles of Facebook & Gmail.

2. A huge aspect of choosing Rails or client-side MVC is productivity. If you're going to build a web app in Ruby, you're going to have to have somebody on your team that is good at Ruby. By layering a client-side MVC on top of that, you're now requiring javascript expertise. Your life is now twice as difficult.

3. It's amazing how powerful DHH's approach is. Just look at the new Basecamp. Does any part of that app feel slow, clumsy, and non-interactive? Absolutely not. I imagine myself being opening up the Basecamp codebase and "getting it" within a day. If you understand your constraints well, you can deliver amazing software with an order of magnitude less complexity.


>The vast majority of problems being solved with software do not require the bells and whistles of Facebook & Gmail.

Even with FB and Gmail, I've gotten the impression that neither of those is fully client or server-side, but rather highly optimized hybrids where component processing tasks are done wherever they can be with highest performance and lowest latency.

Both seem acutely conscious of comparative speeds of server-side rendering + internet latency vs. client-side rendering.

Not sure though, only an impression based on anecdotal evidence, anyone more familiar with their architectures?


Facebooks architecture here is impressive and you can read more about it, they call it Bigpipe. (Of course this is probably, to some extent, out-dated by now).


My perspective on this debate is both client-side and server-side with only a backend API layer is required. The problem with most Js MVC frameworks are they enforce/make it easy to do client side rendering, but make it difficult/impossible to integrate server-side.

I have found that increasing the DOM element count leads to poor performance, hence too much view template loaded initially leads to unnecessary slowness. To mitigate this i started dynamic loading of view templates from the server, which lead to two different calls to the server, one to retrieve the json data and the other to retrieve the view template which makes some sense in certain use cases and sometime merging the data with the template makes it more performant and some case retrieving the template and data in a single call, but without merging is optimum. It all depends on the functionality required.

When you work in Old Android (Browser/WebView) devices, you will observe that using client side rendering and loading too much in the DOM leads to poor performance and it is better to render it on the server side and just use plain JavaScript to inject the rendered view to DOM, which leads to optimum performance.


First, a white-tower point: if you look at the client and server as a whole, doing any kind of dynamic view generation on the server is a complete violation of MVC. You shouldn't tell the view how to view.

That said, server-side rendering is a product of historical inertia. Remember, client-side MVC is the way things were quite successfully done before the internets came along. However, browsers originally sucked at anything "client", so we developed languages and design patterns and libraries that slowly made the concept of a server-generated view tolerable, to the point where many sites (e.g. HN or Wikipedia) are actually better served by doing everything on the server. Now that javascript is powerful enough though (and we can cross-compile from languages better suited to complex application development), client-side MVC is unsurprisingly making a comeback.


The search engines complicate the design choice of client-side vs. server-side MVC. While there are ways to hint search engines to retrieve searchable views of our application data, it adds an additional layer of complexity to your application. From my experiments, Google (or Bing) has yet to make a truly agnostic search engine when it comes to the design choice of client-side vs. server-side rendering. To do so, they would need to routinely emulate the full browser stack and javascript rendering on every page crawl. They do not yet do this. This is especially true when client-side anchor tags are used in URL's to represent client side navigation.


You have to discern between web sites and web applications. For example, it's not useful to make a todo app SEO friendly. Basically, anything beyond a login form is a candidate for client-side rendering.


I wouldn't use a client side MVC framework for pages that need to be crawled. I find them great for webapps that require a user to login.


It's a shame to have to arbitrarily make this tradeoff. There is nothing inherent in saying that apps that desire rich client-side navigation are 100% the apps the DON'T require search engine support.

Google does have a spec for hash-bang URL's to enable both to be present in a single app. Unfortunately, it's clunky and not universally implemented.


The newest frameworks (Derby/Meteor) can execute JS on the server side to generate crawlable pages while serving client-side JS for regular browsers. Also, anchors are obsolete; people should be using real URLs.


I think there is a place for anchor URLS - they make sense as a means of expressing purely client-side navigation. Note that, by design, they will never be transmitted to the server - so there is no need to mirror the client-side navigation implemented in JavaScript within the server implementation. I think this factoring of the server-space navigation and client-side navigation is sometimes useful and keeps the two separated.


I have this argument with people a lot. I'm surprised that nobody talks about serving multiple applications from the same service layer. Sure, you can have a web app and then a separate API for mobile clients, but why not just have a RESTful interface that can be used by all of them?

This doesn't necessarily mean that you can't still do server-side views if you wanted to. But by separating the view rendering from the service layer you provide a bit more flexibility. Designed correctly, the argument becomes moot. Either you're creating a controller, models, and event callbacks on the server, or you're creating them on the client. Client-side javascript frameworks are getting so much better that it really just comes down to finding the best tools for your team.


I don't understand how one is supposed to work with only a JSON back-end and rendering all the view with JavaScript. It's ok if it's only going into a list but what if you want to render the data in a complicated div structure? If you render it server-side it's very easy but with JS it becomes a mess, especially if there are lot of css classes that need to be added as well.


I've been doing this for over a year now, and honestly, it's almost exactly the same on the front-end as it is in the back-end. You have templates (with variables, loop structures, etc)and you pass data into them and render. Same as back-end. With a decent front-end framework (backbone, spine, etc) the process can be simplified even more (like using a back-end framework).

I love this method because you can provide really snappy front-end experiences. It's also nice to focus on having a good solid API along with a consistent front-end, whereas splitting up your front-end between the server and the client can be more complicated than just doing it all in the client. Browsers are now capable to run the entire front-end, so why not let them?


Thanks. What template engine are you using?


A modified version of John Resig's templating engine: http://blog.killtheradio.net/technology/a-small-modification...


Implementing PHP syntax in JS is just ass-backwards, IMHO. Why not use something simple like Mustache? I think it's a nice middle ground because it lacks logic and runs in nearly any language. It's also used by the easiest JS templating library ever, ICanHaz.js.


Objection noted! Aside from the PHP opening/closing tags, the templating system is the same as John Reigs and is fast, simple, and works extremely well...so we haven't had a need to change. We've evaluated other options and realized that switching won't really get us anything we don't already have.

Maybe once our team grows we'll re-evaluate again, since it's just two devs at the moment.


The basic idea is that you have html templates and that you use javascript to "fill in the blanks".

Here's a short primer: http://www.gethifi.com/blog/javascript-templates-and-how-we-...

There are various libraries you can use to make this easier for yourself. Underscore and handlebars are too good options.


eco is also nice if you're using CoffeeScript, although it has a few annoying bugs and hasn't been updated in almost a year.

Edit: JS -> CoffeeScript.


Um, there is a time and place for client side MVC and there is a place for server side.

For example, if you want Google to crawl your stuff, go server side.

I think it's smart to look at it on a per-page or per app basis. Not everything should be client side MVC and not everything should be server side.

Do the right thing for your product.


To add a note: if you have an app that you want Google to index but all of the other points weigh in on the all-JS app side, you can use PhantomJS to crawl/scrape/store your pages before a googlebot ever shows up. Yes, it's a pain in the ass, and yes it complicates your back-end...but it's a good way to have the best of both worlds.


I'd love to see an actual nuts and bolts implementation of the method you describe. I've seen variations of it discussed in other threads but it's all just theory. Deciding how to serve up pages based on user agent, scheduling refreshes, etcetera. It all seems extremely complicated, I'd especially like to know if the implementer viewed the ROI as worth it after the fact.


Well, I've implemented it personally. Generally, here's what happens:

1. A user loads the first page of the app. There is a small script (index.php) that serves all front-end requests. It checks if the page being loaded has already been scraped and if so, injects the content into the main template, otherwise fires off a queued job to scrape that page and loads the app regardless.

2. The queue job forks out to phantomjs with the page URL, which listens on the page for a "page-loaded" event, and upon a) this event being fired or b) the scrape timing out, returns whatever HTML content in the main content area (as well as any <head> tags) to the queue worker, which updates a database table with url -> content mappings.

3. The next time someone directly loads the page, that content is pulled and injected.

4. Scraped content expires after a certain amount of time. If expired content is pulled out, it is put into the HTML for that page, and a queue item is fired to re-scrape.

The obvious problem is that the page must be primed for content to show up, which you can fix by a) either having lots of visitors :) or b) using/building a simple crawler.

Also, when facebook scrapes our page to look for og: tags, we do the scrape synchronously which takes longer, but ensures that the page's content is always available. The same could be done for googlebot, but it's more dangerous since rankings depend on page load speed.

As for our rankings, they are fairly high (it's the same as any app that serves HTML directly would be since we are literally just serving delayed HTML content).

So no, it's not just theory; we do it on Musio.com quite successfully. The only user-agent logic we have is for the facebook scraper, refreshes are scheduled by user action. The RIO is high because

1. We already have a queuing system.

2. Phantom JS is fairly standalone and our scraper is small and write once then forget about it.

3. We've found a good blend between simple and functional, with the deciding factor being the delay.


Thanks for taking the time to do a detailed write up, it's very enlightening.

    >So no, it's not just theory;
No offense was intended, I phrased my statement poorly. The technique is usually discussed in more abstract terms would have been better.


None taken! I understand you probably hadn't encountered anybody who had done more than just toyed with the idea. I also agree, people like to talk about how cool it might be, but I hadn't heard of anyone doing it in production before us.

I think one of the reasons it isn't done a lot is because when people think "one-page JS apps" it's usually account-based, making you log in to use the app (at least the ones I use). So other than a few marketing pages which could easily be handled by a CMS, there'd be no purpose to store generated HTML for your own pages.


Google started to understand javascript, didn't it?


Server-side views are resource hogs. Client-side MVC is not SEO friendly and throws non-JS (or crappy) browsers away.

My bet would be both, but I couldn't find any framework that could render both server and client side templates based on the HTTP headers without enormous amounts of glue code.


I was writing something to do this a while back actually. Just recently AirBnB wrote about it as well: http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-t.... They're using Backbone on both the client and server to accomplish what you're talking about. I haven't seen a complete framework that does this yet though.


I did something similar using Blade (https://github.com/bminer/node-blade) which is a great client and server-side templating engine, but it wasn't as smooth as I would've liked.

I guess we'll have to wait (or do-it-ourselves).


Both.


I'm always curious as to why more people don't go with a hybrid approach. For a lot of my projects, it ends up being the simplest and cleanest solution. Maybe it doesn't really scale well when you have a lot of people working on the codebase that may or may not be familiar with both the backend and frontend, but when it's a one or two person project, I don't see the issue with it. It certainly keeps things simple and prevents duplicated logic.


Great point on the size of the team. It is definitely an important factor for choosing a hybrid approach.


Exactly; for regular apps with little interaction needs, I start with a pure Rails back-end, and mix KnockOut.js only where relevant (for instance), or not at all.

For more UI-dynamic apps like https://www.wisecashhq.com, I go Rails JSON back-end + html rendering for skeleton, and KnockOut.js for the interactivity.

Now that DHH advocates "his way or the highway" isn't really a surprise :-)


That was my immediate thought too. In the example cited the client side todo consumed a json list of all todo items. The server side is still going to be MVC just exsposing json instead of html.

Maybe I'm just splitting hairs, in general I agree with the author's premise.


I'm not sure how we'd go client side efficiently. We have 2500 views!


If you're referring to the cost of switching for an existing project with that many views, completely agree - changing any core component on a large project (regardless of how well de-coupled it is) presents challenges, and simply may not be worth it.

Or are you saying that it isn't possible to efficiently manage 2500 views using a client side framework?


The latter. I'm not sure how you could transfer something of that complexity, with all the UI logic efficiently.


if needs_seo_friendly { use_server_side_view(); } else { use_client_side_mvc(); }

Server-side views are good for content-oriented websites, while client-side MVC's are good for function-oriented webapps that needs clean architecture.

PS, I like AngularJS as the client-side MVC framework, and I'm trying to find a way to better support it in my current project (http://liveditor.com).


Use Yahoo Mojito. Same MVC code on both server and client.


>It's the trend not because it looks new

Yes, it is. 90% of the client side javascript interfaces I've seen provide absolutely no benefit to the user, and often are outright worse than a normal html interface (twitter). Your complaints about RoR's terrible templates do not generalize to all server side template engines, so the whole thing should be framed accurately as a comparison of your preferred javascript mvc framework vs rails templates.


Based on your comment, I'm guessing you've never actually implemented anything with a client-side JS framework.

Yes, strictly speaking, there's nothing inherent to client-side JS MVC frameworks that creates a better experience for end-users (over traditional server-side MVC + client-side Ajax + DOM manipulation, or whatever).

Where they do provide benefit is to developers, for whom it makes creating rich interfaces absurdly easy. Again, to be clear, this does nothing for users. Unless, of course, you consider that reduced barriers to implementing rich interactivity induce developers to use it create better user experiences, and that purpose-specific tools reduce the surface area for experience-disrupting bugs (which, statistically, you'd have more of, since you're operating at a lower level of abstraction and having to constantly repeat yourself [unless, of course, you decided to generalize all your Ajax & DOM manipulation and wrote a framework... oh wait]).

But hey, don't let me keep you from thinking whatever keeps you inside your comfort zone.

(Disclosure: the foregoing is based on ~1 year of experience developing applications with AngularJS).


>Based on your comment, I'm guessing you've never actually implemented anything with a client-side JS framework. Yes, strictly speaking, there's nothing inherent to client-side JS MVC frameworks that creates a better experience for end-users (over traditional server-side MVC + client-side Ajax + DOM manipulation, or whatever).

So basically you attack him only to agree with him? Nice.

>Where they do provide benefit is to developers, for whom it makes creating rich interfaces absurdly easy.

No, it does not.

It makes creating rich interfaces a hodgepodge of immature and fragile client side technologies.


I'm not sure how you would come to such a conclusion, you must have some very serious bias clouding your ability to objectively read what people say.

I've written several client side javascript apps, although obviously I'm not dumb enough to actually write them in javascript when there's so many "tolerable language -> javascript" compilers available.

>Yes, strictly speaking, there's nothing inherent to client-side JS MVC frameworks that creates a better experience for end-users

I didn't say anything like that. I said 90% of people writing client side javascript interfaces are doing so for no user benefit, just following a fad. There's plenty of cases where an interface is better in javascript, unfortunately that's only ~10% of the cases people are using javascript for.

>Where they do provide benefit is to developers, for whom it makes creating rich interfaces absurdly easy.

Compared to using horrible shit like ruby on rails perhaps, but compared to decent tools using a javascript framework is a significant step backwards. That's one of the reasons we only do it when it helps the user, rather than all the time just to make our stuff worse.

>But hey, don't let me keep you from thinking whatever keeps you inside your comfort zone

You really need to make the effort to read what you reply to. If you just want to make up nonsense to respond to, that's what blogs are for.


For the record, I think Twitter is one of the only sites out there that have done JS interfaces the right way. I love the Twitter interface over any Twitter client or the old html interface. I think it's much smoother and works great for their platform. But hey, I'm just one man! Ha


"A single tweet page is 2MB. This is one of the big challenges for Single Page Apps."

https://plus.google.com/app/basic/stream/z123j3wxwrm5jb0tv23...

Source: Comparison of various pages: http://mike.teczno.com/notes/bandwidth.html


I'm like 99% they went back to server-side a few months ago for performance reasons.


I think they just render the initial page on the server, then from there the client takes care of it. It makes sense, since it's common to include the data payload in the HTML to save a request anyway, and it's not much more work to just render the HTML too using the same templates as the client uses.


I actually think that is where the path we should go, Hybrid of both tech. Serving the initial view with HTML and the rest via client side JS.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: