(P.S. One thing I think that's pretty meta-cool about the FastBoot site is that it is, itself, a FastBoot site, running on Heroku.)
Everything is working just like you would set it up with React, except that with Ember declaring data dependencies on route is existing convention. And React gives you maybe a little bit more control around that.
Normally Ember app would render everything within the browser after all JS is downloaded and components etc. are processed. With Fastboot, somehow an additional, non-interfering layer of computation on the server does the same loop (without having to download anything and without significantly slowing down overall client app JS initialization) and sends the output to the client. It does it for every route separately. I'm guessing that somehow the client's processing is disabled on that first "pageview" to avoid double calculation. Is that correct? (if it is, it's very cool :)
With Fastboot, somehow an additional, non-interfering layer of computation on the server does the same loop (without having to download anything and without significantly slowing down overall client app JS initialization)
Right. Typically, the way most client-side JavaScript applications (or "SPAs") work is by having a small, static HTML file that doesn't contain much content (beyond maybe a loading page). It contains <script> tags that point at your JavaScript payload.First the browser downloads the HTML, then the JavaScript, then the JavaScript runs and fetches the data via XHR. Only then does the user see the content they were after in the first place.
This actually works surprisingly well for "workspace" apps where the user is using it throughout the day (Gmail, Google Docs, etc.) On modern devices with good broadband, the difference is negligible.
But the thing this sucks for is content sites, where you aren't using an "app" but you're just clicking a link in Twitter or something. If it doesn't load within a second or so, you aren't that invested that you don't just close the tab. That has been the biggest source of pushback on frameworks like Angular and Ember for sites like this.
FastBoot bends the curve by replacing that static HTML file. Rather than serving an empty document that just points to JavaScript assets, we keep your Ember app running in Node.js on the server. When an HTTP request comes in, we direct it to Ember's router, where it figures out what models to load and components to render. When it finishes, it sends the document back to the browser.
You can think about this is as effectively outsourcing the JavaScript runtime to the server for the first load, but then the browser can take over again on subsequent navigations so it's very fast.
I think FastBoot is a great option for search crawlers, Facebook and Twitter embedding (it supports Open Graph and Twitter Cards), and supporting JavaScript-less clients. Most importantly, it's a way to get content quickly to users with a cold cache.
That said, we are planning to aggressively take advantage of App Cache and Service Worker, so ideally any second-time visitor to your site only has to fetch the raw data to see what they're after.
I'm guessing that somehow the client's processing is disabled on that first "pageview" to avoid double calculation. Is that correct? (if it is, it's very cool :)
Currently it does a full rerender once it loads, but one of the motivating features for writing Glimmer 2 is the ability to quickly "rehydrate", so that rerenders are imperceptible to the user assuming nothing has changed. We'd also love to automatically serialize the backing models of the app so you don't have to double fetch.Btw great job!
That said, it should work just fine once the Ember app finishes loading and running in the browser. I would love it if you could file an issue on the Ember Inspector GitHub page with the error you're getting.
What is this? And why should I use it? I slummed through the quick start but that didn't make me any wiser.
EDIT: I read up on your blog post and you guys should definitely put some of that into the web page.
In addition, Glimmer 2 is near completion, and when ready will provide further speed ups to initial rendering.
One of ember's greatest benefits is that it adapts to change and doesn't miss out on features for very long at all (you can look at fastboot as a reaction to isomorphic react apps, or something that the ember team would have just pursued anyway). However, that benefit can also be a pitfall for newcomers to ember as it's hard to find consistent discussion, help, and resources for a framework that changes so fast.
BTW, while Ember CLI makes things much easier, it does not improve the complexity situation, it just becomes one more thing you have to learn when learning Ember (even as a newbie). What if a newbie isn't familiar with node? what if they're not sure why you're precompiling? what if they're not familiar with task runners like grunt and gulp?
Contrasted with frameworks like Angular 1, Backbone+Marionette, Ember definitely has the most rampup and complexity, not the least.
Oh come on now, lets not be hyperbolic. I'm a massive fan of Ember, but I'm a bigger fan of Redux with React; the reason that Ember can afford to be opinionated is because the team is extremely smart and takes the best winning ideas from the outside "insane" community.
This is probably the thing I hate the most from client-side apps. Can't wait to test this and Angular 2 on production!
Having access to .cljc (clojure files that can be loaded by either CLJS or standard CLJ) helps tremendously here. This means the server-side happens in Clojure on the JVM, so all of the async worries just go away entirely.
* Fully asynchronous rendering, so you don't have to awkwardly architect your app so that it can be rendered synchronously.
* Everything is fully progressively loaded. This means if you go to a particular page in your app, only that page's JavaScript and CSS will be downloaded in the client. Additionally the correct css link elements will be inserted.
* Caching XHR requests so that they are not repeated on the client (data used to render is included in the page).
What makes our solution unique is that you have to think about the server very little, if at all. If you need to make a request to services, just make it in your code. No additional wiring is needed and everything will be server rendered.
Much of this is possible because of Zones, a spec that is being worked on for standardization in TC39. We have a library that implements Zones[2] with SSR in mind. This is what makes XHR caching possible, for example. Check out this simple jQuery example app[3] (using jsdom on the server) to see how easy Zones make things.
I did a talk at Node Interactive this year about SSR and what goes into a good SSR solution: https://www.youtube.com/watch?v=wRYdrfrL6ZQ
[1]https://donejs.com/ [2]https://github.com/canjs/can-zone [3]https://github.com/canjs/can-zone-jquery-example
What is an example of something a dev might have to think about with fastboot that they don't have to think about with DoneJS?
[1]: https://github.com/mhart/react-server-example
[2]: https://angular.io
There is a huge gulf between "synchronously render a component in Node" and "asynchronously boot an app, marshall async data, render an async UI, and do it concurrently."
I touch on this a little bit in this talk[1], but the bulk of the work we've done over the last year is conventionalizing app boot and figuring out how to run multiple instances concurrently, cheaply.
Angular 2 is much more similar to what we're doing with FastBoot, and I'm excited to see where they go with that and crosspollinate ideas. (The work they're doing with Web Worker rendering is also very exciting.)
For what its worth, FastRender was first released in 2013. The just-released Meteor 1.3 now has ES2016 module support which should enable more improvements in this area.
1. https://meteorhacks.com/fast-render-internals-and-how-it-wor...
[0] - http://markojs.com/
Build error
The Broccoli Plugin: [object Object] failed with:
RangeError: Maximum call stack size exceeded
at new Error (native)
at Error (native)
at Object.fs.mkdirSync (fs.js:794:18)
at sync (C:\Users\marke\ember\github-fastboot- example\node_modules\ember- network\node_modules\broccoli- templater\node_modules\broccoli-stew\node_modules\broccoli- funnel\node_modules\mkdirp\index.js:71:13)
at sync (C:\Users\marke\ember\github-fastboot- example\node_modules\ember- network\node_modules\broccoli-templater\node_modules\broccoli-stew\node_modules\broccoli-funnel\node_modules\mkdirp\index.js:77:24)
at sync (C:\Users\marke\ember\github-fastboot-example\node_modules\ember-network\node_modules\broccoli-templater\node_modules\broccoli-stew\node_modules\broccoli-funnel\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\marke\ember\github-fastboot-example\node_modules\ember-network\node_modules\broccoli-templater\node_modules\broccoli-stew\node_modules\broccoli-funnel\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\marke\ember\github-fastboot-example\node_modules\ember-network\node_modules\broccoli-templater\node_modules\broccoli-stew\node_modules\broccoli-funnel\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\marke\ember\github-fastboot-example\node_modules\ember-network\node_modules\broccoli-templater\node_modules\broccoli-stew\node_modules\broccoli-funnel\node_modules\mkdirp\index.js:78:17)
at sync (C:\Users\marke\ember\github-fastboot-example\node_modules\ember-network\node_modules\broccoli-templater\node_modules\broccoli-stew\node_modules\broccoli-funnel\node_modules\mkdirp\index.js:78:17)
The broccoli plugin was instantiated at:
undefined
Any ideas?Looking around on the site I didn't see a link to report something like this, and I didn't immediately think to goto github with it.
Please excuse my ignorance.