Related
I've done some web-based projects, and most of the difficulties I've met with (questions, confusions) could be figured out with help. But I still have an important question, even after asking some experienced developers: When functionality can be implemented with both server-side code and client-side scripting (JavaScript), which one should be preferred?
A simple example:
To render a dynamic html page, I can format the page in server-side code (PHP, python) and use Ajax to fetch the formatted page and render it directly (more logic on server-side, less on client-side).
I can also use Ajax to fetch the data (not formatted, JSON) and use client-side scripting to format the page and render it with more processing (the server gets the data from a DB or other source, and returns it to the client with JSON or XML. More logic on client-side and less on server).
So how can I decide which one is better? Which one offers better performance? Why? Which one is more user-friendly?
With browsers' JS engines evolving, JS can be interpreted in less time, so should I prefer client-side scripting?
On the other hand, with hardware evolving, server performance is growing and the cost of sever-side logic will decrease, so should I prefer server-side scripting?
EDIT:
With the answers, I want to give a brief summary.
Pros of client-side logic:
Better user experience (faster).
Less network bandwidth (lower cost).
Increased scalability (reduced server load).
Pros of server-side logic:
Security issues.
Better availability and accessibility (mobile devices and old browsers).
Better SEO.
Easily expandable (can add more servers, but can't make the browser faster).
It seems that we need to balance these two approaches when facing a specific scenario. But how? What's the best practice?
I will use client-side logic except in the following conditions:
Security critical.
Special groups (JavaScript disabled, mobile devices, and others).
In many cases, I'm afraid the best answer is both.
As Ricebowl stated, never trust the client. However, I feel that it's almost always a problem if you do trust the client. If your application is worth writing, it's worth properly securing. If anyone can break it by writing their own client and passing data you don't expect, that's a bad thing. For that reason, you need to validate on the server.
Unfortunately if you validate everything on the server, that often leaves the user with a poor user experience. They may fill out a form only to find that a number of things they entered are incorrect. This may have worked for "Internet 1.0", but people's expectations are higher on today's Internet.
This potentially leaves you writing quite a bit of redundant code, and maintaining it in two or more places (some of the definitions such as maximum lengths also need to be maintained in the data tier). For reasonably large applications, I tend to solve this issue using code generation. Personally I use a UML modeling tool (Sparx System's Enterprise Architect) to model the "input rules" of the system, then make use of partial classes (I'm usually working in .NET) to code generate the validation logic. You can achieve a similar thing by coding your rules in a format such as XML and deriving a number of checks from that XML file (input length, input mask, etc.) on both the client and server tier.
Probably not what you wanted to hear, but if you want to do it right, you need to enforce rules on both tiers.
I tend to prefer server-side logic. My reasons are fairly simple:
I don't trust the client; this may or not be a true problem, but it's habitual
Server-side reduces the volume per transaction (though it does increase the number of transactions)
Server-side means that I can be fairly sure about what logic is taking place (I don't have to worry about the Javascript engine available to the client's browser)
There are probably more -and better- reasons, but these are the ones at the top of my mind right now. If I think of more I'll add them, or up-vote those that come up with them before I do.
Edited, valya comments that using client-side logic (using Ajax/JSON) allows for the (easier) creation of an API. This may well be true, but I can only half-agree (which is why I've not up-voted that answer yet).
My notion of server-side logic is to that which retrieves the data, and organises it; if I've got this right the logic is the 'controller' (C in MVC). And this is then passed to the 'view.' I tend to use the controller to get the data, and then the 'view' deals with presenting it to the user/client. So I don't see that client/server distinctions are necessarily relevant to the argument of creating an API, basically: horses for courses. :)
...also, as a hobbyist, I recognise that I may have a slightly twisted usage of MVC, so I'm willing to stand corrected on that point. But I still keep the presentation separate from the logic. And that separation is the plus point so far as APIs go.
I generally implement as much as reasonable client-side. The only exceptions that would make me go server-side would be to resolve the following:
Trust issues
Anyone is capable of debugging JavaScript and reading password's, etc. No-brainer here.
Performance issues
JavaScript engines are evolving fast so this is becoming less of an issue, but we're still in an IE-dominated world, so things will slow down when you deal with large sets of data.
Language issues
JavaScript is weakly-typed language and it makes a lot of assumptions of your code. This can cause you to employ spooky workarounds in order to get things working the way they should on certain browsers. I avoid this type of thing like the plague.
From your question, it sounds like you're simply trying to load values into a form. Barring any of the issues above, you have 3 options:
Pure client-side
The disadvantage is that your users' loading time would double (one load for the blank form, another load for the data). However, subsequent updates to the form would not require a refresh of the page. Users will like this if there will be a lot of data fetching from the server loading into the same form.
Pure server-side
The advantage is that your page would load with the data. However, subsequent updates to the data would require refreshes to all/significant portions of the page.
Server-client hybrid
You would have the best of both worlds, however you would need to create two data extraction points, causing your code to bloat slightly.
There are trade-offs with each option so you will have to weigh them and decide which one offers you the most benefit.
One consideration I have not heard mentioned was network bandwidth. To give a specific example, an app I was involved with was all done server-side and resulted in 200Mb web page being sent to the client (it was impossible to do less without major major re-design of a bunch of apps); resulting in 2-5 minute page load time.
When we re-implemented this by sending the JSON-encoded data from the server and have local JS generate the page, the main benefit was that the data sent shrunk to 20Mb, resulting in:
HTTP response size: 200Mb+ => 20Mb+ (with corresponding bandwidth savings!)
Time to load the page: 2-5mins => 20 secs (10-15 of which are taken up by DB query that was optimized to hell an further).
IE process size: 200MB+ => 80MB+
Mind you, the last 2 points were mainly due to the fact that server side had to use crappy tables-within-tables tree implementation, whereas going to client side allowed us to redesign the view layer to use much more lightweight page. But my main point was network bandwidth savings.
I'd like to give my two cents on this subject.
I'm generally in favor of the server-side approach, and here is why.
More SEO friendly. Google cannot execute Javascript, therefor all that content will be invisible to search engines
Performance is more controllable. User experience is always variable with SOA due to the fact that you're relying almost entirely on the users browser and machine to render things. Even though your server might be performing well, a user with a slow machine will think your site is the culprit.
Arguably, the server-side approach is more easily maintained and readable.
I've written several systems using both approaches, and in my experience, server-side is the way. However, that's not to say I don't use AJAX. All of the modern systems I've built incorporate both components.
Hope this helps.
I built a RESTful web application where all CRUD functionalities are available in the absence of JavaScript, in other words, all AJAX effects are strictly progressive enhancements.
I believe with enough dedication, most web applications can be designed this way, thus eroding many of the server logic vs client logic "differences", such as security, expandability, raised in your question because in both cases, the request is routed to the same controller, of which the business logic is all the same until the last mile, where JSON/XML, instead of the full page HTML, is returned for those XHR.
Only in few cases where the AJAXified application is so vastly more advanced than its static counterpart, GMail being the best example coming to my mind, then one needs to create two versions and separate them completely (Kudos to Google!).
I know this post is old, but I wanted to comment.
In my experience, the best approach is using a combination of client-side and server-side. Yes, Angular JS and similar frameworks are popular now and they've made it easier to develop web applications that are light weight, have improved performance, and work on most web servers. BUT, the major requirement in enterprise applications is displaying report data which can encompass 500+ records on one page. With pages that return large lists of data, Users often want functionality that will make this huge list easy to filter, search, and perform other interactive features. Because IE 11 and earlier IE browsers are are the "browser of choice"at most companies, you have to be aware that these browsers still have compatibility issues using modern JavaScript, HTML5, and CSS3. Often, the requirement is to make a site or application compatible on all browsers. This requires adding shivs or using prototypes which, with the code included to create a client-side application, adds to page load on the browser.
All of this will reduce performance and can cause the dreaded IE error "A script on this page is causing Internet Explorer to run slowly" forcing the User to choose if they want to continue running the script or not...creating bad User experiences.
Determine the complexity of the application and what the user wants now and could want in the future based on their preferences in their existing applications. If this is a simple site or app with little-to-medium data, use JavaScript Framework. But, if they want to incorporate accessibility; SEO; or need to display large amounts of data, use server-side code to render data and client-side code sparingly. In both cases, use a tool like Fiddler or Chrome Developer tools to check page load and response times and use best practices to optimize code.
Checkout MVC apps developed with ASP.NET Core.
At this stage the client side technology is leading the way, with the advent of many client side libraries like Backbone, Knockout, Spine and then with addition of client side templates like JSrender , mustache etc, client side development has become much easy.
so, If my requirement is to go for interactive app, I will surely go for client side.
In case you have more static html content then yes go for server side.
I did some experiments using both, I must say Server side is comparatively easier to implement then client side.
As far as performance is concerned. Read this you will understand server side performance scores.
http://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html
I think the second variant is better. For example, If you implement something like 'skins' later, you will thank yourself for not formatting html on server :)
It also keeps a difference between view and controller. Ajax data is often produced by controller, so let it just return data, not html.
If you're going to create an API later, you'll need to make a very few changes in your code
Also, 'Naked' data is more cachable than HTML, i think. For example, if you add some style to links, you'll need to reformat all html.. or add one line to your js. And it isn't as big as html (in bytes).
But If many heavy scripts are needed to format data, It isn't to cool ask users' browsers to format it.
As long as you don't need to send a lot of data to the client to allow it to do the work, client side will give you a more scalable system, as you are distrubuting the load to the clients rather than hammering your server to do everything.
On the flip side, if you need to process a lot of data to produce a tiny amount of html to send to the client, or if optimisations can be made to use the server's work to support many clients at once (e.g. process the data once and send the resulting html to all the clients), then it may be more efficient use of resources to do the work on ther server.
If you do it in Ajax :
You'll have to consider accessibility issues (search about web accessibility in google) for disabled people, but also for old browsers, those who doesn't have JavaScript, bots (like google bot), etc.
You'll have to flirt with "progressive enhancement" wich is not simple to do if you never worked a lot with JavaScript. In short, you'll have to make your app work with old browsers and those that doesn't have JavaScript (some mobile for example) or if it's disable.
But if time and money is not an issue, I'd go with progressive enhancement.
But also consider the "Back button". I hate it when I'm browsing a 100% AJAX website that renders your back button useless.
Good luck!
2018 answer, with the existence of Node.js
Since Node.js allows you to deploy Javascript logic on the server, you can now re-use the validation on both server and client side.
Make sure you setup or restructure the data so that you can re-use the validation without changing any code.
I've been reading some very interesting articles about the whole client vs. server rendering lately.
http://www.onebigfluke.com/2015/01/experimentally-verified-why-client-side.html
http://www.quirksmode.org/blog/archives/2015/01/angular_and_tem.html
http://tomdale.net/2015/02/youre-missing-the-point-of-server-side-rendered-javascript-apps/
Now I've been a bit of a fan boy when it comes to client side but after I read these articles some points started to show up in favor of the server side rendering, to my surprise... The main points were:
1) You can upgrade your server, but not your users device - This means, well, yes... you are in control of the server, so if it's under performing you may opt to upgrade/scale. You can't force users to upgrade their devices.
2) First paint vs. last paint - Now on the experimentally verified... link above it shows when the users first see the page (first paint) and when the users may use the page 100% (last paint). Now from what I can think of when the user sees the page, it takes their brain some time to process the signals from the visual cortex to the frontal cortex and then to the premoter cortex where the user actually starts clicking his/her finger, that is of course if the html is rendered first so the brain has something to process while loading is happening in the background (js files, binding etc.).
What really got me was the bit were twitter reported people of having up to 10 seconds of loading time for client side rendering, no one should ever experience that! It's kind of saying, "Well if you don't have a good enough device, sorry, you'll just have to wait.".
I've been thinking, isn't there a good way of using both client-side and server-side templating engines and which both client and server use the same template engine and code. In that case it's only to figure out if it's benefactor to supply the client with the rendered page or let the client render it themselves.
In any case, share your thoughts on my sayings and the articles if you want. I'm all ears!
UPD: do it only if you really need it
(4 years and 2 isomorphic enterprise apps later)
If you're required to do SSR, fine. If you can go with a simple SPA - go with it.
Why so? SPAs are easier to develop, easier to debug and cheaper and easier to run.
The development and debugging complications are evident. What do I mean by "cheaper and easier to run", though? Well, guess what, if 10K users try to open your app at the same time your static HTML website (i.e. a built SPA) you won't even feel it. If you're running an isomorphic webapp though, the TTFB will go up, RAM usage will go up and eventually you'll have to run a cluster of those.
So, unless you are required to show some super-low TTFB times (which will likely come through aggressive caching), don't overcomplicate your life.
Original answer from 2015:
Basically you're looking for an isomorphic web app that shares the same code for frontend and backend.
Isomorphic JavaScript
JavaScript applications which run both client-side and server-side. Isomorphic JavaScript frameworks are the next step in the evolution of JavaScript frameworks. These new libraries and frameworks are solving the problems associated with traditional JavaScript frameworks.
I bet this guy explains that much better that me.
So, when a user comes to the page, the server renders the full page with contents. So it loads faster and requires no extra ajax requests to load data, etc. Then, when a user navigates to another page, the usual techniques for single page applications are used.
So, WHY WOULD I CARE?
Old browsers / Weak devices / Disabled Javascript
SEO
Some page load improvements
Old browsers / Weak devices / Disabled Javascript
For example, IE9 does not support History API. So, for old browsers (and if user disables javascript too), they would just navigate through pages just like they did it it in good old days.
SEO
Google says it supports SPA's but SPA's aren't likely to appear in the top results of google search, are they?
Page speed
As it was stated, the first page loads with one HTTP request, and that's all.
OK, so
There are lots of articles on that:
http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/
http://www.sitepoint.com/isomorphic-javascript-applications/
https://www.lullabot.com/articles/what-is-an-isomorphic-application
But SHOULD I CARE?
It's up to you, of course.
Yeah, that's cool, but it takes much work to rewrite/adapt the existing app. And if your backend is in PHP/Ruby/Python/Java/Whatever, I've got bad news for you (it's not necessarily impossible, but close to that).
It depends on the website, you can try to collect some stats and if the percentage of users with old devices is small, it's not worth the trouble, so why not...
LET THEM SUFFER
If you care only about users with old devices, then c'mon, it 2015, and it's your user's problem if he's using IE8 of browsing websites with a iPod Touch 2. For example, Angular dropped IE8 support in 1.3 approximately a year ago, so why wouldn't you just alert the users that they need to upgrade ;)
Cheers!
All of the conversations on this topic miss one point. Bytes sent to the client. Pages rendered as HTML on the server are a lot smaller. Less bytes transmitted is better for everyone, both server and client. I've seen the bandwidth costs on cloud sites and even a 10% reduction can be a huge saving. Client side JS pages are always fat.
So I'm afraid I might be missing something pretty fundamental here, but I really can't get my head around this - Why? Why would we want to use those JS MVC frameworks, instead of sticking with Rails, Django, PHP and so on?
What do these JS frameworks give us that can't be achieved by the old web frameworks? I read about SPA, and there's nothing I couldn't do there with ASP.NET MVC, right?
I'm really baffled by hearing all the people at work wanting to leave our current framework for these new ones, and it's much more than just for the sake of learning something new.
I am totally up for that, and I've always tried playing around with other frameworks to see what I'm missing, but perhaps these new technologies have something really big to offer that I simply cannot see?
Single page applications provide a better experience by having all page transitions be seamless. This means you never see the "page flash" between user actions, in addition to a few other user experience improvements.
Front-end frameworks also generally provide a common way to interface with APIs. So instead of writing an AJAX wrapper for every page in your site, you just say 'This page has this route (path), hooks data with this schema from that API endpoint and presents it with these templates and helpers.' There are many proponents of APIs, because there are many good reason to write you applications from a service standpoint. This talk sums up a lot of the points in favor of APIs. To summarize:
Orchestrating your web offerings as services makes them inherently decoupled. This means they are easily changed out. All the reasons behind strong Object Oriented design principles apply equally to the larger parts of an application. Treat each piece as an independent part, like a car, and the whole platform is more robust and healthy. That way, a defect in the headlights doesn't cause the motor to blow up.
This is very similar to how a SOAP WSDL works, except you have the auto creation tools right out of the box.
Having well defined touch points for each part of your application makes it easier for others to interface with. This may not ever factor into your specific business, but a number of very successful web companies (Google/Yahoo, Amazon AWS) have created very lucrative markets on this principle. In this way, you can have multiple products supported by the same touch points, which cuts a lot of the work out of product development.
As other point out, the front end framework is not a replacement for the backend, server technologies. How could it be? While this may seem like a hindrance ("Great, now we have two products to support!"), it is actually a great boon. Now your front and back ends can be changed and version with much less concern over inadvertently breaking one or the other. As long as you stick to the contract, things will "Just WorkTM".
To answer your additional question in the comment, that is exactly correct. You use a front end framework for handling all the customer interaction and a completely separate back-end technology stack to support it.
I'm forgetting a few good ones...
Angular, Ember, and Backbone are client-side JavaScript frameworks. They could be used interchangeably with a Rails, Django, or PHP backend. These JavaScript MVCs are only responsible for organizing JavaScript code in the browser and don't really care how their data is handled or persisted server-side.
Django/Rails etc are server-side MVC frameworks. Angular/Backbone etc are client-side Javascript MVC frameworks. Django/Rails and Angular/Backbone work together - in a single-page app, usually the server-side MVC will serve the initial HTML/JS/static assets once, and then once that is done, the client-side router will take over and handle all subsequent navigations/interactions with your app.
The difference here lies in the concept of what a "single-page application" is. Think about how a "regular" web Django/Rails website works. A user enters your app, the backend fetches data and serves a page. A user clicks on a link, which triggers the server to serve a new page, which causes the entire page to reload. These traditional types of websites are basically stateless, except for things like cookies/sessions etc.
In contrast, a single-page application is a stateful Javascript application that runs in the browser and appears to act like a traditional webapp in that you can click on things and navigate around as usual, but the page never reloads, instead, specific DOM nodes have their contents refreshed according to the logic of your application. To achieve a pure Javascript client-side experience like this in a maintainable fashion really requires that you start organizing your Javascript code for the same reasons you do on the server - you have a router which takes a URL path and interacts with a controller that often contains the logic for showing/hiding views for a particular URL, you have a model which encapsulates your data (think of a model as roughly one "row" of a database result) which your views consume. And because it's Javascript there are events going on, so you can have your view listen for changes in it's associated model and automatically re-render itself when the data is updated.
Also keep in mind that you don't just have one view on the client side, there are usually many separate views that make up a page and these views are often nested, not only for organizational purposes but because we want the ability to only refresh the parts of the UI that need to be refreshed.
The intro to Backbone is probably a good starter on the topic: http://backbonejs.org/#introduction
Check this article, there is well explained how a modern web application should looks like in the client side, server side and the communication between them.
By the way:
Client side -> Ember, Angular, Backbone, Knockout.
Server side -> Django, Node, Rails
I'd like to create something similar to a family tree online app (like geni.com). I'm unsure what languages I should use to build it with. My IT strong points aren't in programming and this project is going to require me to sit down and learn some languages. My problem right now is that I don't know what languages I should use.
So with the idea of a family tree online app in mind here are some of the specifications.
- I do not want to use flash.
- The app needs to be zoomable and scrollable (sort of like google maps)
- The app needs to be able to add content without reloading the page. Perhaps there's a little "+" sign and when I click it, I can add a tag/title/description/picture
- The app needs to be able to save your work for that user to retrieve later on.
- The layout that a user is able to create in is sort of widget based where the user can add a new bubble and then in that bubble they are able to add text or content.
I started programming this with HTML5 canvas and Javascript, but I'm stuck on creating a connection to the database that isn't directly from Javascript (because that seems very insecure to me). But I'm not just stumped on how to interact securely with the database (I don't even have a database picked out), but also I'm concerned that I won't be able to build out the app with just javascript and may need something else like ajax or something but I'm unfamiliar with what each language does nowadays.
If you are starting from scratch, then the best language to use is the one you are most comfortable with. Alternately, if you don't plan to be developing the whole thing yourself and you already have some other interested parties on board then the best language to use is the one that the majority of you are comfortable with. If it's just you and you do not yet have any favorites, then look around and play with a few - it's the only way to find out if you will actually like / be effective with them.
That being said, a few of the more likely candidates these days are:
JavaScript: Long gone are the days when this language was simply a way to put the D in DHTML. These days JavaScript is a viable client and server-side language. (Others here have already recommended Node.js -- I'd also recommend NPM (node package manager) to handle your dependencies). With a little bit of planning you can reuse most of your application code on both the client and the server side. On the downside, most of the server side technology is very new (only a few years old at most) and so you may find yourself implementing tools for use in your application rather than your application itself. Finding servers that support it will also be harder, again on account of it's age.
Perl: At the opposite end of the spectrum of age, we find Perl - the first commonly deployed language used to make web applications it still powers a great variety of useful websites out there (include new ones such as Pinboard.) The tools that are popular on CPAN have been vetted under fire. The good news is that it is not going anywhere anytime soon. The bad news is, you might have to search a little harder to find a module that supports [that newest, baddest thing that just came out yesterday].
PHP: The BASIC (or Perl, depending on who you ask) of the modern web, PHP was designed from the ground up to do one thing - make building dynamic web pages easier. Its popularity means that there is quite a lot of server support (PHP + Apache + MySQL is the Model T Ford of web servers -- everyone can afford one) and an enormous amount of pre-built code available for perusal. However, like BASIC, PHP's strength is also its greatest weakness. Almost anyone can write something that works in PHP ... how well it works depends on who wrote it. The caveat emptor that applies to all code snippets found on the web applies in spades to snippets of code written in PHP.
Python: The language that made programing fun again (at least for those who can see past the significant whitespace and lack of blocks / anonymous functions and overlook < 3.x's issues with non-ASCII out of the box.) It's a general-purpose, flexible and multi-paradigm language with quite a substantial standard library (but without .NET or Java's incredible bloat). In addition, quite a large amount of work has been done in it, so there is a good chance that what you need has been already developed by somebody else. Plus, it can make you fly.
Ruby (with or without Rails): The language that made the web fun, coupled, if you so desire, with the framework that made MVC cool. There is lots of documentation out there, and a great community, with many prebuilt tools (called gems) from which to pick and choose - free and cheap servers are not as common as their PHP counterparts, but they are likely to be of higher quality (when chosen at random).
All that being said, they are all great languages for web development. What matters is not what we think you should use ... but what you are most likely to be effective with. All of the languages listed above are mainstream (or will be in the next two years), easy-to-learn and easy-to-write languages. You cannot go wrong, no matter what you choose to start off with.
Alternately, if you want something a little more difficult, or less mainstream ... I am working with .NET applications at work, and with Lisp (SBCL)-based services in my spare time. I have heard great things about Lua and Java too ... there are at least two C++ web frameworks out there ... and I'm sure that there is somebody is having fun building a web service in COBOL with a FORTRAN backend. ;-)
As someone has already pointed out, you will need to work with a server side language as well. (Ruby, Python, PHP) You are exactly right there you should not be attempting a database connection via javascript in the browser.
You'll need to build out a server side application to handle the basic operations of your application.
I'd strongly recommend reading up on the MVC design pattern, and possibly looking into Ruby on Rails as your backend framework, it plays very nicely with ajax like features, and has a somewhat shorter learning curve, I believe, than some other frameworks / languages.
You will need server side scripts in a language like PHP or Ruby on Rails to interact with a database.
If you're already familiar with HTML5 and JavaScript, may I recommend using Node.JS? It's about the closest you'll get to what you already know with browser development. It can also hook in with database systems which are closer to the HTML5-suggested IndexedDB.
with that in mind...
If you're inexperienced with programming and programming languages, then the app you describe will involve a pretty big learning curve. While Flash and Flex have really nice interfaces to build apps with click-and-drag, the tools for HTML5 are much less mature.
That's not saying it's not possible with HTML5. Just that there's still some time to wait before people create tools to bring the app building process closer to what Adobe provides.
I want to design a web application whose only interface is json i.e. all the http requests receive responses only in json format and dont render any html on the server side. All the form posts convert the form data into a json object and then post it as a string. All the rendering is done by client side javascript.
The one downside of this approach I know is that browsers without javascript wont be able to do much with this architecture but the interaction on the site is rich enough to be useless to non-javascript browsers anyway.
Are there any other downsides of this approach of designing a web application?
It's an increasingly-common pattern, with tools such as GWT and ext-js. Complex web apps such as GMail have been over 90% JS-created DOM for some time. If you are developing a traditional 'journal' type website with mainly written content to be read this approach will be overkill. But for a complex app that wishes to avoid page refreshes it may well be appropriate.
One downside is that not only does it require a browser that supports JavaScript, it is also easy for the computing resources required by the app to creep up to the point where it needs quite a powerful browser. If you develop in Chrome on a top-end PC you might come to run the app on a less powerful machine such as a netbook or mobile device and find it has become quite sluggish.
Another downside is you lose the opportunity to use HTML tools when working on your pages, and that viewing your application's pages' DOM trees under Firebug or Chrome Developer Tools may be hard work because the relationship between the elements and your code may not be clear.
Edit: another thing to consider is that it is more work to make pages more accessible, as keyboard shortcuts may have to be added (you may not be able to use the browser built in behavior here) and users with special needs may find it more difficult to vary the appearance of the app, for instance by increasing font size.
Another edit: it's unlikely now text content on your website will be successfully crawled by search engines. For this reason you sometimes see server created text-only pages representing the same content, that refer browsers to the JS-enabled version of the page.
Other than the issue you point out, there's another: Speed. But it's not necessarily a big issue, and in fact using JSON rather than HTML may (over slower connections) improve rather than hamper speed.
Web browsers are highly optimised to render HTML, both whole pages (e.g., normally) and fragments (e.g., innerHTML and the various wrappers for it, like jQuery's html or Prototype's update). There's a lot you can do to minimize the speed impact of working through your returned data and rendering the result, but nothing is going to be quite as fast as grabbing some HTML markup from the server and dumping it into the browser for display.
Now, that said, it's not necessarily going to be a big problem at all. If you use efficient techniques (some notes in this article), and if you primarily render the results by building up HTML strings you're then going to hand to the brower (again, via innerHTML or wrappers for it), or if you're rending only a few elements at a time, it's unlikely that there will be any perceptible speed difference.
If, instead, you build up substantial trees by creating and appending individual elements via the DOM API or wrappers for it, you're very likely to notice a performance impact. That seems like the right thing to do, but it involves lots of trips across the DOM/JavaScript boundary and means the browser has to present the DOM version of things to your code at all intermediate steps; in contrast, when you hand it an HTML string, it can do its thing and romp through it full-speed-ahead. You can see the difference in this performance test. It's substantial.
Over slower connections, the speed impact may be made up for or even overcome if the JSON data is more compact than the HTML would have been, because of the smaller size on the wire.
You've got to be more mindful of high-latency, low-bandwidth connections when you're building something like this. The likelihood is, you're going to be making a lot of Ajax calls to sync data and grab new data from the server, and the lag can be noticeable if there's a lot of latency. You need a strategy in place to keep the user informed about the progress of any communication between client and server.
In development, it's something that can be overlooked, especially if you're working with a local web server, but it can be killer in production. It means looking into prefetching and caching strategies.
You also need an effective way to manage HTML fragments/templates. Obviously, there are some good modules out there for rendering templates - Mustache.js, Underscore template, etc. - but keeping on top of the HTML fragments can cause some maintenance headaches. I tend to store the HTML templates in separate files, and load them dynamically via Ajax calls (plus caching to minimise HTTP requests).
Edit - another con:
Data syncing - if you use a server database as your data "authority" then it's important to keep data in sync between the server and client. This is even more relevant if changes to data on one client affects multiple clients. You then get into the realms of dealing with realtime, asynchronous updates, which can cause some interesting conceptual challenges. (Fortunately, using frameworks and libraries such as Socket.IO and Backbone.js can really make things easier).
Edit - pros:
There are some huge advantages to this type of application - it's far more responsive, and can really enhance the user experience. Trivial actions that would normally require a round-trip to the server and incur network overhead can now be performed quickly and seamlessly.
Also, it allows you to more effectively couple data to your views. Chances are, if you're handling the data on the client-side, you will have a framework in place that allows you to organise the data and make use of an ORM - whether its Backbone.js, Knockout.js or something similar. You no longer have to worry about storing data in html attributes or in temporary variables. Everything becomes a lot more manageable, and it opens the door for some really sophisticated UI development.
Also also, JavaScript opens up the possibility for event-driven interaction, which is the perfect paradigm for highly interactive applications. By making use of the event loop, you can hook your data directly to user-initiated and custom events, which opens up great possibilities. By hooking your data models directly to user-driven events, you can robustly handle updates and changes to data and render the appropriate output with minimal fuss. And it all happens at high speed.
I think the most important thing is what is your requirement, if you want to build a interactive application, giving desktop like feel then go for client side development. Using Javascript framework like backbone.js or knockout.js will really help in organizing and maintaining the code. The advantages are already detailed out in previous answers. As respect to the performance in rendering with respect to server side rendering is concerned here is a nice blog post which made thinking.
http://openmymind.net/2012/5/30/Client-Side-vs-Server-Side-Rendering/