9 ms·
Missing the Point of Server-side Rendered JavaScript Apps
- Isofarro 12y agoSo they are building a server-side app to deliver a usable first-load experience with HTML and CSS, while the JavaScript loads in and runs, and until the JavaScript runs, all the links work like normal anchors. Sounds like Progressive enhancement [1]. [1] http://tomdale.net/2013/09/progressive-enhancement-is-dead/ http://tomdale.net/2013/09/progressive-enhancement-is-dead/
- tomdale 12y agoTypical "progressive enhancement" calls for creating HTML in templates that have no knowledge of the JavaScript, and then using JavaScript to attach behavior to that HTML. The approach described in this blog post builds a JavaScript app from the get-go, and uses a server-side technique to extract standalone HTML from the JavaScript application. The net effect is the same (you get HTML on the client before you executed the JavaScript), but the developer paradigm is sharply different. Typical progressive enhancement techniques require you to carefully construct a version of your application that works without JavaScript, and then find ways to shim in and bring the page alive. The approach I'm working on provides the HTML as a by-product of running the application normally. Additionally, progressive enhancement techniques almost always involve server-side rendering, which means you lose the benefits of client-side routing I describe in the post. The goals of progressive enhancement are wonderful. My complaint has always been that previous techniques hamper developer productivity far too much to be realistic. With FastBoot, I'm hoping we can offer the benefits with far fewer costs.
- Touche 12y agoTom, it's ok to backtrack here. You (and the rest of us) didn't know at the time that progressive enhancement could be possible without making development much more difficult.
- azakai 12y agoI think this might be semantic quibbling at this point. Yes, progressive enhancement and server-side rendered JS are similar. You can see the latter as a new version of the former. But it is implemented in such a way - a novel way - that it definitely deserves a term of its own.
- Touche 12y agoProgressive enhancement is not a technique, it's a goal. Server-side rendering is a method for achieving the goal.
- ac2u 12y agoIt's not really useful for the conversation to lump it in with the traditional definition of progressive enhancement that's been done for years. Even middle of the road efforts I tried a few years ago (such as sharing a templating language between client and server even when the implmentation language differs) was fraught with friction compared to this technique.
- remysharp 12y agoPlaying devil's advocate: PE techniques aren't documented (so far as I know) so it's up the developer to take the path they're most comfortable with. FastBoot, I suspect, will dictate how I code my application/server side logic. On the surface, it looks like the cost of FastBoot is higher. The benefits are, I suspect, are higher though: single code base, reusable views, etc.
- ericclemmons 12y agoHah! I'm glad others have seen we've come full circle again :) As a developer of isomorphic (there's another term to pick apart!) React apps, I'm thrilled Ember and others are reaching the same conclusions on why server-side rendering is crucial. I'll still call it Progressive Enhancement, since a server-generated response is "enhanced" with client-side functionally that still functions for those with it disabled.
- carsongross 12y agoMy response to this consists of a library: http://intercoolerjs.org/ http://intercoolerjs.org/ Server-side rendered HTML: an idea so crazy... It. Just. Might. Work.
- Scaevolus 12y agoI like the simplicity. How does this handle CSRF tokens?
- carsongross 12y agoIt looks for the standard meta CSRF meta tag, it will include it if the request is within a form with a CSRF hidden input, and you can hook in via the usual jQuery AJAX hooks if you are doing something else.
- Procrastes 12y agoNice! I'll have to try this out in my next side project.
- CGamesPlay 12y agoGood for the simplest of "rich" interactions, but quickly drops off when responsiveness becomes a factor. For example, you cannot implement optimistic responses using this library (click the "save todo" button and the saved item immediately appear in its read-only interface; this interaction requires reimplementing your templating library and validation code on the client and the server).
- carsongross 12y agoI wouldn't dismiss it so blithely. I implemented a remote job runner UI here: http://intercoolerjs.org/examples/jobrunner.html http://intercoolerjs.org/examples/jobrunner.html You can get pretty far with it. It isn't a perfect fit for every app, but most apps have at least a few areas where using it would simplify things considerably. Also, there are a lot of nice things that are extremely easy to use that are a PITA with most other frameworks. For example, AJAX-aware history is an ic-push-url="true" away: http://intercoolerjs.org/examples/history.html http://intercoolerjs.org/examples/history.html I realize that most front end people who see this will immediately dismiss it as "simple", but it's a very rich library and can be used to accomplish an awful lot: you can fire client side events using custom HTTP headers, show and hide request indicators using only a CSS selector, etc.
- supporting 12y agoYou gotta love the Orwellian naming on this one. "Ember FastBoot" meaning Ember-we've-been-selling-you-very-slow-booting-for-years-and-now-we're-hoping-to-mitigate-it-slightly-but-it's-still-vaporware. Meanwhile, the commonsense approach has always been faster and simpler than this model: Use a small JS framework, not a bloated one, and only load the minimal UI and data set that you need to render the initial page at first. Load the rest later. This includes bootstrapping — remembering to put all the data you need to render the page inline as a JSON object in the HTML. This can often result in less data sent over the wire than a large HTML page with tons of repeated DOM elements. It's also far easier to cache appropriately.
- tomdale 12y agoI don't want to get into a big discussion on small libraries vs. big frameworks (your use of the word "bloat" gives away your position here ;). I would ask readers of this discussion to visit any of the web applications they use on a daily basis, open the developer tools, and look at the size of the JavaScript payload. Whatever libraries or frameworks they're using, the payload size is almost always several hundred kilobytes. I'd argue that using small libraries is a noble goal, but in practice, you just need several hundred KB of JavaScript to build modern apps. If we're honest with ourselves about it, we can try to do a good job of managing it from the beginning. Otherwise you just end up with an ad hoc mess. The other point I tried to make here is that, yes, of course, you can do all of this by hand. But in practice, most teams are so under the gun to ship features that they don't do it. If we can make great boot performance as easy as installing an npm package, why not? Lastly, regarding the vaporware claim: we've got a very alpha version up on GitHub already. I invite Ember users to play around with it and give us feedback: https://github.com/tildeio/ember-cli-fastboot https://github.com/tildeio/ember-cli-fastboot.
- mst 12y agoI'd like to stand up and be counted as saying that both 1. Ember absolutely isn't to my taste and I've successfully avoided it so far and intend to continue doing so in future 2. The work you're doing is really cool and I'm looking forward to seeing it completed, both for the benefit of my friends with different tastes who're happily using ember and for the benefit of everybody else in that it provides a worked example of an awesome idea. (and people who dislike it just because they dislike ember might, possibly, need to remember that trailblazing is important for new ideas)
- Touche 12y agoI would take it a step further and say that server-rendered JavaScript apps completely changes the game and will have ripple effects throughout the web industry. Here's MercuryJS's example of server rendered app: https://github.com/Raynos/mercury/tree/master/examples/server-rendering https://github.com/Raynos/mercury/tree/master/examples/serve... As you can see most of the code is the client-code. All the server code does is run a function and stringify the results. What this means is that you no longer need a back-end team and a front-end team. Your front-end team is your team (not counting "API" teams). Sure, some companies have already been doing this but now you can do it with far less code. And you can do it faster. And with fewer developers (there's less work). Which means you can do it cheaper. All of this means is, if you are writing your front-end and back-end in different languages, you are in a real competitive disadvantage. So any language used for web development is going to see its usage slide if they can't find an answer for transpiling to JavaScript. And hopefully having an isomorphic answer the way JavaScript now has.
- deleted 12y ago[deleted]
- bonif 12y agoyes, sure
- ffn 12y agoThank you Tom Dale for continuing to make ember better with Fast Boot. I personally write and live-test a lot of my apps on 4chan's /g/ and /r/programming (which I imagine hosts a large "tinfoil" user base), and the most common feedback I would get from them is "why do you need javascript for this trash?" (well, the actual most common feedback I'd get from them are personal insults regarding my sexual preferences, but they're not constructive and heeding them will not lead to a better product). So thank you so much for working to make ember server-side-enabled. Also, not to put the cart before the horse, but any chance we'll be getting virtual dom any time soon?
- tomdale 12y agoRe: Virtual DOM, keep an eye on https://github.com/tildeio/htmlbars/pull/282 https://github.com/tildeio/htmlbars/pull/282.
- failed_ideas 12y agoI don't think anyone is missing the point at all. I fully understand what you're attempting to do because I tried to implement an Ember project only to have so many negatives pile up that it was actively working against our goals. I really wanted to like Ember, but even with those issues aside, the two most common comments on out team about Ember were "Wait, why is that working?" and "I didn't change anything, why isn't it working now". Neither is something you should be hearing from your dev team. You can do some pretty cool things pretty quickly, but there are more promises that resolves.
- adamnemecek 12y agoHow long ago did you check out Ember?
- failed_ideas 12y agoWe removed the last bits 3-4 weeks ago. We started with a pre-1.0, but all the headaches with that are on me, not Ember. I will probably check it out again at a 2.0 or 3.0 release, I love the potential. But for now, it doesn't work for us.
- deleted 12y ago[deleted]
- azakai 12y ago> I don't think anyone is missing the point at all. Perhaps you are not, but "anyone"? The article quotes 2 tweets that disagree with the point, and I've heard it misunderstood on internet comments. Perhaps it's not a common misunderstanding, or perhaps it is - it's hard to tell with anecdotes. Regardless, it's worth clarifying, as the author of the post did.
- failed_ideas 12y agoAbsolutely, you are 100% correct. I definitely misspoke.
- chrisdotcode 12y agoEDIT: Lots of downvotes for saying that there are other ways to program apps besides doing everything on the client. Render content on the server, enhance content presentation on the client. --- I don't get it. Is this 1996? Why are people just now 'discovering' that you don't need to throw JS at an application to have it completely usable? > All modern websites, even server-rendered ones, need JavaScript. There is just a lot of dynamic stuff you need to do that can only be done in JavaScript. Really? Look at Linode, Amazon, or even Google (including GMail, and probably others). All of which are big names that can and do work ENTIRELY without JavaScript. > Client-side JavaScript applications are damn fast. Another (AJAX) HTTP request + rendering the returned data on a tiny mobile phone is faster than one HTTP request for the entire webpage and having dedicated machinery pre-render the content for you? I don't think so. He does talk about this point later on, but which is it? Client-rendered JS apps are, or aren't fast? --- JS Hipsters offloading rendering everything to the client for absolutely no reason is the 'everything-looks-like-a-nail' or the 'everyone surfs the web like I surf the web and has my specs' problem. Worst of all, in doing so, they completely neglect actual content. You don't know how many million-dollar VC-funded company webpages I've visited that don't even have a damn tagline visible on their landing page without JavaScript enabled. <h1>s with actual content inside of them are too complicated now? The solution is very simple: render all the data on the server, and progressively enhance subsets of your app with JS, by overriding the defaults of the rendered page. It's literally like we're discovering DHTML all over again.
- azakai 12y ago> GMail, and probably others [..] All of which are big names that can and do work ENTIRELY without JavaScript. Gmail uses massive amounts of client-side JavaScript (perhaps compiled from a different language, of course).
- chrisdotcode 12y agoThere's an option for the basic HTML layout available if you have JS disabled. That's the second-best approach. The first is using a JS-redirect to the flashy AJAX page, or just overriding all the default handlers necessary with JavaScript (remember, at this point, your content was already (supposed to be) properly rendered for you by the server).
- deleted 12y ago[deleted]
- bsimpson 12y ago@tomdale, I think you're conceptually correct (server-rendered apps don't replace your API/data server); however, it's just as misleading to say that a server-rendered app replaces your CDN. Instead, server-rendered apps add a new tier (if you were serving your app from S3 before) or replace an existing tier (your old app server). The kinds of people who needed a CDN before will still need one, and your API layer should not be tightly coupled to your app, esp. if you eventually want to support a native app or a developer ecosystem. So you end up with: - Data layer/API server: exposes your data to a client in a RESTful way - Browser: a client (one of potentially many) that presents data from your API in an interactive way - App server: a node/io.js server that renders your app to HTML and sends it to the browser. It optimizes for search and slow devices without duplicating your app logic. This role was previously filled by Flask/Django/Rails/PHP, though sometimes conflated with the data layer. - CDN: makes your media that doesn't change often highly available and lower latency. If you needed on of these before you added an app server, you probably still need one.
- tomdale 12y agoYes, I totally agree. Sorry if that was confusing—I was trying to simplify the diagrams and perhaps oversimplified. You would of course still use a CDN for any static assets. Only the HTML that changes would be served by FastBoot, and of course you probably want to cache certain responses from that as well.
- cyberpanther 12y agoGreat post but taking your Twitter example why not make a full HTML version like GMail does so you don't have to scrap the client side stuff? Also so you don't have to build a framework specific server library like Fastboot. I feel like Fastboot is a more sensible solution than lets say Meteor.js; however, it is still about solving issues for a minority of your users who are on slow internet and older devices. If your really using slow internet and old devices than the experience is still going to be slow no matter what you do unless you really strip things down. So just make multiple experiences that are really good instead of one 'meh' experience. With that said, Twitter made the right decision at the time because their client side implementation sucked on all machines not just the old ones.
- quaunaut 12y agoIt's not just for users on slow internet or older devices- Bustle was a good example, because as a content site, it generally has a lot of assets to load. Fastboot can get you over the hump of the initial load when you're linked to a content-heavy page on the site for the first time, and hide the download/boot of the JS app for the moment it becomes ready.
- gweinberg 12y agoWell, I freely concede I am still missing the point. You use client-side javascript because that's what runs in the client. Whatever your server-side code does, why would you write it in javascript?
- gkelly 12y agoI think the goal is to have FastBoot use your existing client-side javascript app, the idea being that one codebase in one language is simpler and better.
- scribu 12y agoAs the post mentions, the node.js app that servers the initial HTML would be separate from the API server. The code in the API server can, as before, be implemented in whatever language you want.
- smacktoward 12y agoBecause writing an app in one language is easier than writing it in two or more, and since JavaScript is the only language you can do client-side scripting in you're probably going to be writing some JavaScript no matter what. So if you want the ease of writing your whole app in one language, the only language that one language can possibly be is JavaScript.
- sanderjd 12y agoHere is an architecture that fits what the article is talking about: -------------------------- | In-browser EmberJS app |------ -------------------------- | | | HTML (1) | | | ------------------------------- | | Same EmberJS app, running on| | | server, generating HTML | | ------------------------------- | | ---------- JSON (2) JSON (3) | | ------------------------------------ |JSON API server written in, eg. Go| ------------------------------------ You don't write any more javascript than you already would have for the client app, and you can write your API server however you want.
- lhorie 12y ago> If it needs to fetch data from your API server to render, so long as both servers are in the same data center, latency should be very low Maybe I'm just missing something obvious, but wouldn't FastBoot make things slower if it needs to go hit the database to produce the static page, and then the clients hits the server again to fetch the unrendered templates and data as part of Ember's normal bootstrapping? I don't think it's that uncommon for the database to be a bigger bottleneck than the network. Are there any benefits over, say, slapping a screenshot of the page as the background of body? (yes, I know I'm oversimplifying, but for instance, Facebook loads up wireframy graphics as placeholders until ajaxed stuff pops up.)
- Isofarro 12y agoBy having the app running on the server it can take advantage of being primed before the first request arrives. Primed in that the app is already running, and/or the data retrieved is cached and regularly refreshed. Depending on the nature of the application, if it's largely not client personalised (a content site like Bustle, as opposed to a Gmail client), one instance of the app on the server can respond to multiple client requests in it's lifespan. So basically it's an already spun up ready to go instance of the app, or already processed, just needs to squirt the HTML buffer at a response object.
- lhorie 12y agoReally? I'd imagine most Ember projects are more like Gmail than Bustle (in the sense that they probably have at least login). If even a single byte of the payload changes, you're looking at O(n=users) instances and then you're potentially back at the problem of having the db hit happen before the first pixel on screen.
- pr0gramm 12y ago(Throwaway because I don't want my real name associated with the site) So here's another perspective. I'm running a highly dynamic site[1] with 8m sessions and 650m pageviews per month. The site runs on a single moderately sized server (4 cores, 16gb RAM) for MySQL and PHP. I can only do this, because I offload everything I can to the client. The site loads a single 80kb JS file (which also contains all templates) and fires of one AJAX request that gets the requested data. This data is the same for all visitors (for the same resource), so it can be easily cached on the server for a few seconds, before it gets stale. Everything on this site can be voted (tags, comments, images). These votes are stored client side and synced with the server if needed. This means I can load my canned data from the server and augment it with client data when rendering. If I were to render it server side, I'd have to create a custom page for each and every user and load the client's votes from the database for each request. This is simply not feasible with the current hardware. [1] http://pr0gramm.com/ http://pr0gramm.com/
- Twirrim 12y agoIt's worth noting that while that's OK for desktop visitors, shifting the workflow to the client means you're putting a lot more stress on mobile visitors and resulting in a worse experience for them. Network performance and latency is all over the place, leaving AJAX an unpredictable mess. On top of that you're adding the overhead of spinning up the javascript runtime on the phone, running the code etc. etc, all of which eats precious battery time for them, and negatively impacts your time to screen, a very important metric.
- krapp 12y agoI think that load balancing is a perfectly legitimate reason to use javascript, particularly if you're on a shared server with limited resources.
- Animats 12y agoThey're misusing the term "rendered". Rendering is the graphics operation of turning some non-image representation into an image. Server-side rendering would be generating each page as an image and serving that. The article is just talking about fancier template systems for generating HTML. That's what content management systems do - assemble a page out of parts on the server and deliver it to the client.
- adamnemecek 12y agoRender has been hijacked a bit and AFAIK all (most?) web frameworks refer to HTML generation from templates as 'rendering', e.g. https://docs.djangoproject.com/en/1.7/topics/http/shortcuts/#render https://docs.djangoproject.com/en/1.7/topics/http/shortcuts/... http://guides.rubyonrails.org/layouts_and_rendering.html http://guides.rubyonrails.org/layouts_and_rendering.html
- dsrw 12y agoThe term rendering predates computer graphics by quite a long while. Their usage here is extremely common, and seems perfectly acceptable to me.
- sanderjd 12y agoI think if we had to do it over again, a better term would have been "serialize". But this has been a commonly used meaning of "render" for more than a decade now, as it was used by the earliest versions of ruby on rails.
- thekingshorses 12y agoWhatever architecture you use, it all depends on your requirements. Example: If SEO is important, build server side rendering. Period. Just make sure you provide best user experience possible. Author claims Bustle is one of the good JS rendered site. If you scroll down http://www.bustle.com/ http://www.bustle.com/ and click on the item, and if you use back button, you won't be at the same position. This is one of the biggest problem with JS rendered site. Now compare this to reddit.com. It works great without client side rendering, and not have any issues that most client side rendering sites has. I am not oppose to JS only app. Problem is, it is hard to build a good JS only app. I do build client only apps. Hacker news: http://hn.premii.com/ http://hn.premii.com/ Reddit: http://reddit.premii.com/ http://reddit.premii.com/
- quaunaut 12y agoI don't know what you're talking about. The back button works on Bustle everywhere I've tried it. What browser and version are you using?
- subsection1h 12y agoIn Chrome, when I scroll to the bottom of an article at Bustle, click a link to another article, and then go back, I'm directed to the top of the first article, not the bottom where I left off. In my experience, this behavior is the norm at sites that use client-side rendering, and it's the main reason why I hate browsing content sites that use client-side rendering.
- recursive 12y agoI can reproduce with Chrome 40 on Windows 7.