16 ms·
Isomorphic JavaScript: The Future of Web Apps
- leeoniya 13y agoi hope the future of web apps isn't also pages like this one that screw up my preferred scroll-wheel speed (FF) :(
- deleted 13y ago[deleted]
- camus2 13y agowhy the use of the word Isomorphic in that context ?
- romanovcode 13y agoTo sound smart.
- jsnk 13y agoI think the word denotes mapping of client side data to the server side data. In frameworks like Meteor, if there some addition or deletion of data on the server side, browser notices the changes and updates the page accordingly. In frameworks like Rails or Django, changes of data on server side doesn't update the client side page (unless you customize the app with ajax)
- thurn 13y agoWe do this sort of thing on the site I work on, Google+. Initial page-loads are rendered on the server, subsequent page-loads are rendered on the client. Really good for performance. It's just the templating system that's common code, though, the server is still Java.
- frontendbeauty 13y ago(author) Cool! What's the JavaScript runtime on the server? Something JVM-based?
- thurn 13y agoThe server code is still Java, but our template language (https://developers.google.com/closure/templates/ https://developers.google.com/closure/templates/) compiles to both JS and Java.
- sitkack 13y agoWhy not render the templates in PhantomJs and have a user account that can push the rendered template back into the server cache. No need to duplicate the work of writing two backends. Or hell, just use Rhino and generate the reified pages on the server. Also, you can't patent this now.
- lennel 13y agoThe soy templates have a java (tofu) backend already (several years old). The phantomjs idea is a shit idea and should go away. Phantom is fine and good for headless testing (hells we use it for quite a bit else) but seriously it is not a solution for a real load.
- sitkack 13y agoIn my scenario an alternative (Rhino or PhantomJs) engine would generate a page once and then push that rendered page to the server. No real load would be sent to it. Single code path for all template rendering. Zero cross implementation bugs and the client still gets a fully reified page on first load. Shit idea, lil harsh.
- peterhunt 13y agoShit idea is a little harsh for sure, but the problem is when your page relies on dynamic data and you can't prerender it. It's just too expensive to boot up a DOM on the server.
- lyricalpolymath 13y agosorry thurn, this is off topic: is there a complaint / improvement suggestion page for G+? there are some serious design bugs in G+ that we'd love to have/solve(d) :)
- avolcano 13y agoMy main concern - how does application state get handed off to the client-side code after the initial render? Sure, it's nice to have some pre-rendered templates, but at some point it needs to "transition" cleanly to the client.
- akbar501 13y agoI just started hacking on Rendr last night, so I don't know if it shares state between Express on the server and the client-side app. My guess would be that Rendr does not have this built in as it's stated design goal is to stay small/modular. However, Yahoo already released a solution for shared Express/client state: https://github.com/yahoo/express-state https://github.com/yahoo/express-state
- fieldforceapp 13y agoHow does one go about debugging such a framework, state synchronization errors seem like they'd be a nightmare?
- frontendbeauty 13y ago(author here) We just bootstrap some JSON onto the page to transfer application state to the client. It's the same approach as the `express-state` (mentioned in a below comment). Same as any client-side app.
- quarterto 13y agoYou keep using that word. I do not think it means what you think it means. Using precisely defined mathematical words in contexts where they only make sense vaguely to a layperson ruins their original usage. Make up a new word. Repurpose a shitty English word. But leave our damn maths words alone. Old man quarterto shakes his fist at you! Get off my smooth, compact lawn!
- siegecraft 13y agoI just assumed it meant the opposite of polymorphic, but no it's not even related to that..
- guerrilla 13y agoAmen! I'm glad someone said something. That really bothered me. It's actually the only reason I clicked on the link. In my head, they'd somehow mapped Javascript onto another language and were able to convert interchangeably between the two or something like that. Needless to say, I was disappointed.
- acjohnson55 13y agoAgreed. I like "Nomadic JavaScript" better! Or "Unbound JavaScript". Or "Bicoastal JavaScript". Or maybe "Freebased JavaScript". Anything else.
- danabramov 13y agoFreewheelin' JavaScript
- 13y ago
- themanr 13y agoA great thing about the web is that a multitude of server side languages can be used. While I don't ever want to have to write the same template twice, having everything converge on nothing but Javascript doesn't seem like a very inspiring future to me.
- danpeddle 13y agoIf you are building a service or API, then you can do that in whatever language you like. The natural language for writing client side apps is JS (ok, the only language, for now).
- CmonDev 13y ago"ok, the only language, for now" - which is deeply unnatural for such an innovative field as IT.
- frontendbeauty 13y agoCorrect. If you're already writing a bunch of JavaScript for the client-side, then just think about this approach as migrating some of that client, UI logic to the server.
- CmonDev 13y agoTo have two problems instead of one?
- frontendbeauty 13y agoThere are already two problems, if you're building a rich client-side web app. Have you done this? If so, you would understand the problem.
- camus2 13y agobut who writes clientside logic before serverside logic ?
- deleted 13y ago[deleted]
- gmjoe 13y agoThis smells like over-engineering to me... In my experience, including rendering code both server-side and client-side is overkill. Just put all the rendering and templating code client-side, period. If you want your page to appear more quickly, then instead of loading content data with AJAX afterwards, just include JSON arrays of content directly within the HTML source itself, and use JavaScript to populate the page instantly, even as it loads. (Obviously SEO is a different case, but there are tools built for that specifically.)
- frontendbeauty 13y agoThe approach you mention is much easier. However, it does make for slower perceived page load times, even when serializing JSON on the page, because the browser has to fetch, parse, and evaluate JS files before rendering the HTML into the document. This can take many hundreds of milliseconds, especially on mobile devices. In my experience, server-side rendering has led to a much better UX.
- sgdesign 13y agoI think the idea is that the same bit of code would be running both on the server and/or the client, depending on what you need. So it wouldn't require any more work on the end developer's part.
- acjohnson55 13y agoI like the basic idea, but my hope is that we can go the other direction and bring more interesting languages to the client side. I know this is done to some extent using JS or Asm.js as a compile target with a whole bunch of existing projects. But it would be great to see this really move forward. It seems like CoffeeScript did this rather successfully, and with source maps, the debugging story is getting better too. Any reasons why this might not be a more compelling future than the "JS everywhere" vision?
- markc 13y agoConsider Clojure - an interesting language indeed, and the browser variant (ClojureScript) is gaining lots of interest.
- CmonDev 13y agoMake it native across major browsers - that would be cool. At the moment it's just another transpiler.
- acjohnson55 13y agoI'm not sure anything's fundamentally wrong with transpilation.
- shire 13y agothis is interesting so Javascript can now be used for server-side which removes the need for Ruby on Rails and Django basically? can someone summaries this article, time is of the essence.
- datboitom 13y agoThis isn't anything new...
- doorhammer 13y agoIf you're not familiar with server side javascript, looking up node.js is a good place to start.
- tonetheman 13y agoone man's isomorphic javascript is another man's text file...
- cromwellian 13y agoFor those interested in GWT, I've got a similar library I'm working on for GWT, but I call it "PoA" for Page-Oriented-Architecture. The idea is to have the best of both worlds from both an SPA (Single-Page-Application) standard point, while preserving the fundamental webby-ness of URLs/pages. Of course, since it is Java, a lot of code is shared between server and client, running full performance in the JVM, plus globally optimized JS on the client. It works by authoring all pages in HTML/CSS/WebComponents with basic MDV-style two-way databinding as separate stand-alone pages. These are then globally optimized together as a monolithic SPA application, and then code-split back into separate pieces. A servlet then processes the template on the server, does the data binding, and sends back a fully rendered bit of HTML + inlined JSON data within a single HTTP request. The JS code starts up and binds to the template and model, and then launches async loads of the rest of the compiled templates. You get URL addressability, crawlability, fast initial page load, plus SPA-style fast switches, global aggressive optimization, offline, sharing of heap objects between pages, etc. Initial hacked up draft of what I'm prototyping http://goo.gl/ZNpxTk http://goo.gl/ZNpxTk
- Breefield 13y agoI'm curious to see how this shared rendering between client/server plays out for non JS based frameworks such as Django, Rails, etc. I've been feeling the burn myself—the desire to fully switch to handlebars templates in my Rails app. The expensive part would be building my API out more than I have, because I rely on associations in Rails view renders. However, gaining 1 template engine to rule front & back.
- frontendbeauty 13y ago(OP here) Probably your best bet is to create a small Node web service that takes a template name and data and returns HTML. Then your (Rails, Python, PHP) app can call out to that in the request cycle. Instagram.com does something similar; it's a Django app.
- icebraining 13y agoSeems to me that the approach with best separation of concerns would be to redirect the initials requests directly to node, which would then call the Python/Ruby/etc API to get the data to render the template. After that, the browser JS could call the API directly, and so the latter would never have to know about templates at all.
- wmf 13y agoThere's a different approach that performs all rendering server-side and sends snippets of HTML to the browser to be woven into the existing page. I suspect that would be more natural for non-JS frameworks.
- michaelwww 13y agoI'm having a brain freeze here. How do you render a DOM on the server and then push it out to the client? Convert in memory DOM to a text/html representation before sending?
- williamcotton 13y agoYou could use something like Phantom JS. To iterate a point in the article, a number of client-heavy sites built on Angular and Ember have been rendering their content on the server-side to be presented to crawlers like the Googlebot for SEO purposes.
- michaelwww 13y agoI understand node.js with V8 and also Phantom JS but how does a client browser view the DOM rendered on the server is what I'm asking. I'm guessing it gets rendered and serialized to JSON for transport, but I could be over-thinking it. Server side rendering is the same as it ever was, just with new tools.
- hackerboos 13y ago>I understand node.js with V8 and also Phantom JS but how does a client browser view the DOM rendered on the server is what I'm asking. It's returned in the request as HTML if the USER_AGENT matches Googlebot just like it would in a normally non-SPA web app.
- michaelwww 13y agoThen I don't understand the problem with SEO because we can feed the crawlers whatever HTML is relevant for search engines
- williamcotton 13y agoThe issue is that frameworks like Angular and Ember generate markup AFTER the HTTP GET response has been returned. If a crawler executes the web page without a full Javascript context it will miss out on the intended content.
- williamcotton 13y agoThere is a confusion between isomorphism and monomorphism when it is related to JavaScript as it runs in the web browser runtime compared to the node runtime. I feel this tension is at the root of the CommonJS vs AMD discussions that have been taking place recently as well as issues related to npm, bower, and browserify. Monomorphic code, while being very easily shared amongst different runtimes, still needs to aware of the mechanisms, strengths, and weaknesses of those runtimes! Projects like browserify-cdn and sites built with on top of it like requirebin.org do a lot to bridge the gap but raise some interesting questions about wrappers like UMD. I feel there is room for a better protocol for sharing code between the different environments. I'm currently doing some research on the subject and plan on writing a spec and implementing some example interfaces. BTW, projects like Bower head in the opposite direction and seem painfully unaware of their actual context... I mean, installing a package manager to then install a package manager should raise some eyebrows, right?
- Randgalt 13y agoWasn't this the idea with GWT so many years ago? In GWT's case, it was Java on both sides. I don't believe that it solves the problem and I don't believe Javascript on both sides will solve the problem. This is a classic "impedance mismatch" like O/R mapping. At the end of the day, there may be no good, i.e. simple, solution. It is inherently difficult and messy.
- esamek 13y agoGWT is not Java on both sides. Its Java on the server, Javascript on the client. The Java client side code compiles to Javascript...the abstraction is way greater than what OP is presenting. (JS & JS) GWT is/was a terrible amount of overhead baggage, but had some brilliant event systems and DOM tricks for its day.
- dragonwriter 13y ago> GWT is not Java on both sides. Its Java on the server, Javascript on the client. The Java client side code compiles to Javascript.. And the Java server code compiles to JVM bytecode. Languages often compile to some other form to run, and the fact that the compilation target is different for different parts doesn't change that the programming language is the same.
- ses 13y ago'For its day'? GWT lives in many forms, most notably Vaadin: http://vaadin.com http://vaadin.com Vaadin is consistently rated one of the best web app frameworks. Why its not more widely known is beyond me.
- larsmak 13y ago> GWT is/was a terrible amount of overhead baggage GWT is very much alive and kicking, but it's primarily used on internal business applications with large and complex code bases. And what overhead baggage are you talking about? GWT is designed to reduce overhead though cross-compiled, browser-spesific builds, dead-code removal, and js-optimizing.
- lucasjans 13y agoConspicuously absent from the author's article was Angular. What is it about Angular that doesn't lend itself to this dual purpose frontend and backend infrastructure?
- spion 13y agoLots of potential hidden state as well as the need to support the entire DOM API server-side. For example, directives may add hidden state to the DOM and assume full availability of DOM API (even jQuery). The server will have to support all that Also, you'll have to re-do the entire rendering on the client, then swap the server-generated DOM with the client-generated DOM. Its probably possible - but is it worth the effort?
- ilaksh 13y agoI did it. Not really super hard. https://github.com/ithkuil/angular-on-server/wiki/Running-AngularJS-on-the-server-with-Node.js-and-jsdom https://github.com/ithkuil/angular-on-server/wiki/Running-An.... But http://prerender.io http://prerender.io is a lot easier and works for everything.
- VaedaStrike 13y agoI'm going to stick with learning me some pedestal.
- natural219 13y agoAt the Meteor meetup last week, David Greenspan outlined an interesting approach to how Meteor UI separates the "template-parsing" logic from the "rendering" logic with an intermediate representation (in Javascript) of the steps you need to take to produce that HTML. Check out the video (relevant slide is at 16:47, but the entire talk is awesome): http://www.meteor.com/blog/2013/11/06/david-greenspan-at-devshop-9-meteors-new-rendering-model http://www.meteor.com/blog/2013/11/06/david-greenspan-at-dev... The cool thing is, other template languages (like Handlebars, Jade, etc.) can compile to this intermediate representation, which then gets rendered on any updates. If the front-end community could agree on a protocol for how to represent these steps in, say, JSON, then we could be on our way to a world where you could use any rendering engine with any template library, on the client or the server. That is, if the community could agree on a representation :)
- hippich 13y agoFunny thing, had related talk today with my co-worker... Anyway, so problem currently is that client devices are slow and HTTP requests are expensive/slow. If these were not issues - I guess rendering on a client would be just fine? If above is correct, I do not see good reason for smallish websites/apps/whateverucallit fallback on server rendering, as it looks like every single year mobile devices getting faster and faster. And we have SPDY on a way to mainstream. Do I want to wait 3 seconds to get HTML or wait 100ms to get bootstrap code and see pieces rendering as data comes in? Probably doesn't matter, since it will take roughly same 3 seconds to render it on client side. Ultimately, perceived responsiveness of webapp depends a lot on particular implementation. If you wait for all data required for page to render - yes, it will be slow. If you render pieces of page as data comes in - user sees that something going on and this is good enough. Why it should matter where data will be converted to presentation, on server or on a client? It is still waiting. And if client is not happy with it? Buy beefier hardware!
- babby 13y ago> 3 second to get HTML No server should take more than 100ms-500ms on a sufficiently cached page to process and to begin transferring, in non-edge cases. The only thing that could take that long is a shitty datacenter/vps, and as such, transfer speed/latency limits will encumber all types of requests. In the end, you still have to transfer data from databases, so ignoring that, client-side template rendering seems like a non-issue to me. Surely it's never the latency issue unless you're serving at ~100+ requests per second, which translates to many millions of requests a day, and I don't believe 99% of websites are doing this.
- knappador 13y ago"She's an iso" http://www.youtube.com/watch?v=y8nXRQQ0bjA http://www.youtube.com/watch?v=y8nXRQQ0bjA Mostly Django user attempting to ask from outside the Node/server-side js community for an explanation of why we're invoking "isomorphic" here: As far as what's going on, are we just saying that the js for rendering the page is equally capable of talking to the API and doing the DOM work while running on the server as it is when downloaded, interpreted, JIT'd etc before fetching the actual request content? Does this mostly eliminate an extra RTT to the API if the js/web application server experience relatively zero RTT due to network/physical proximity to the API server? Does this incidentally make SEO possible while having fat clients and server-side initialization all in one setting and with mostly one code base? Assuming I'm on track, working backwards towards understanding the implementation as it relates to "isomorphic", if a program's output state is a valid input state to initialize the program (we're talking fat, stateful MVC clients after all) state, then all that's needed to re-create the entire execution state of the current program is to copy itself into the output in such a way that it will be run upon receipt (we link js files in the page). I'm going to take a wild guess that the output state of the client doesn't have the necessary template tags etc used when a cold page is rendered, server or client-side, so the server has to serialize some of the state and pump it into the copy of the program to make it as if the client we're sending is the client that rendered the page, keeping the client's internal representation consistent with the state of the page. If this is true, we're taking a program that cannot be initialized from it's own output and modifying it to be a program that achieves the same effect. JS is modifying JS, and is therefore said to be "isomorphic?" It still sounds like a glorified way to describe a serialized execution state, one that happens to involve a program in a language outputting a valid program in the same language, but the purpose is to achieve the effect, as far as the developer is concerned, that the output is a valid input, albeit with an intermediate technique to make the abstraction hold water. If I'm on track, then I have to say it's rather as if we have a fat client, output of one render, serialized client state (because the DOM is not sufficient to re-create the program state or else our client js has to initialize from one format that's programmer friendly and one that's program-friendly), and necessarily a third-leg responsible for injecting the client js and serialized state as js into the output. Standing to see the mauve dusk of my life against the impending rain of spears and arrows, I must ask if we can not simply call the js necessary to achieve the equivalent state of running everything client side a "continuation" and call the entire technique "client continuation programming?" with it implicitly understood that creating the continuation involves a third piece of program? I'm prepared to die. I just want to know.
- mindcrime 13y agoNow, the Web has matured into a fully-featured application platform, and fast JavaScript runtimes and HTML5 standards have enabled developers to create the rich apps that before were only possible on native platforms. Eh, saying "matured into" implies that the current state is somehow better or more desirable than the previous state, and somewhat implies that this was the expected / desired goal state. I reject all of those implications. I posit that it would be more correct to say that "the Web has been mangled, bent, distorted, twisted and hacked into a fully-featured application platform..." A Web browser should be good at browsing, trying to make it into an application runtime is a "separation of concerns" violation of the first magnitude. It might work, but let's not pretend there aren't other choices, or forget to continue researching alternative approaches to delivering applications over the Internet.
- akbar501 13y agoAirBnB's Rendr library is not a JavaScript, and only JavaScript solution. It is however a library that allows you to mostly unite your web rendering layers on the web client and application server. Look at the first diagram in the article and you'll notice that the author shows 3 environments: 1. Client (obviously the browser is JS) 2. Application Server (the server-side rendering environment = what he says can now change to JS thanks to Rendr) 3. API Server (use whatever you want here - JS, Java, Ruby, Python...) And, in production you will no doubt need a "static" server as well (for rendering privacy, tos, etc. pages). Plus all of the other production systems (like a queue, stream processing, and so on) that are not JavaScript environments. If you check out his example code you'll see that he actually sets up example 04 (https://github.com/airbnb/rendr/blob/master/examples/04_entrypath/index.js https://github.com/airbnb/rendr/blob/master/examples/04_entr...) with a subapp for a static page. Also, if you look at the react-moment branch in the isomorphic tutorial repo (https://github.com/spikebrehm/isomorphic-tutorial/blob/react-moment/index.js https://github.com/spikebrehm/isomorphic-tutorial/blob/react...) you'll see that he's proxying a dummy API server to a route on the application server.
- csbartus 13y agoIs this something like Rails's PjAX or Turbolinks or completelly different?
- JDDunn9 13y agoSo then you couldn't use a CDN to load your JS files, which might kill your performance gains. How does this change loading partials? I disagree about the complexity. I've build Angular apps with a RESTful backend that couldn't be simpler. I also haven't noticed any performance issues. It's faster than traditional sites for me. SEO is a problem though.
- frontendbeauty 13y agoWhy couldn't you use a CDN for the JS files? We most certainly do.
- poissonpie 13y agoInteresting read. I really think that the SEO problems faced by SPAs will eventually become a non problem......web crawlers will adapt to the technology that is rendering web pages because indexing is their "product".
- raphinou 13y agoI've started developing some simple apps with Wt (http://www.webtoolkit.eu http://www.webtoolkit.eu) and it's really cool. It lets you develop web apps in a widget oriented way, and completly abstract the client/server communication. It's not javascript on the server but that's fine. I actually used the Jwt (java version) with Jruby and Groovy, which is translated from their C++ codebase.
- etanazir 13y agoI think its obvious Twitter moved to server side rendering for control / profitability reasons. Not performance.
- Kiro 13y agoIf a single-page app is dependent on SEO it shouldn't even be a SPA to begin with.
- BUGHUNTER 13y agoI can not sort by prize on the airbnb listings? Also I do not want to see the map, but can not find a way to disable the map.
- tfb 13y agoI've considered doing exactly this (using Node.js) based on the same paradigm as the Unreal Engine. Epic devised a very effective way to code for both a client and server at once within the same class(es), where server->client, client->server, and other types of replication are as easy and intuitive as anything else. I think it would be perfect for real-time web applications where multiple users interact with each other at the same time. I'd advise anyone interested in these ideas to check out how the Unreal Engine does it. Edit - A couple of unofficial but useful links: http://wiki.beyondunreal.com/Introduction_to_replication http://wiki.beyondunreal.com/Introduction_to_replication http://wiki.beyondunreal.com/Legacy:Replication_De-Obfuscation http://wiki.beyondunreal.com/Legacy:Replication_De-Obfuscati...
- ilaksh 13y agohttp://prerender.io http://prerender.io