Skip to content

Commit

Permalink
Use latest visit API from 2.2 beta
Browse files Browse the repository at this point in the history
This commit has an implicit cross-dependency on ember-fastboot/ember-cli-fastboot#71.

This commit takes advantage of the new visit API in Ember and moves
most of the heavy-lifting (runtime stuff) into the server.
  • Loading branch information
chancancode committed Oct 14, 2015
1 parent 3e1352a commit 6ae5e6e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 39 deletions.
28 changes: 25 additions & 3 deletions bin/ember-fastboot
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,38 @@ var server = new FastBootServer({
ui: ui
});

var app = express();
console.log('Booting Ember app...');

app.get('/*', server.middleware());
// FastFail™: this is not mandatory; the first call to visit would
// also boot the app anyway. This is just to provide useful feedback
// instead of booting a server that keeps serving 500.
//
// Note that Application#boot is still a private API atm, so it might
// go through more churn in the near term.
server.app.boot().then(function() {
console.log('Ember app booted successfully.');

var listener = app.listen(options.port, function() {
var app = express();

app.get('/*', server.middleware());

var listener = app.listen(options.port, function() {
var host = listener.address().address;
var port = listener.address().port;
var family = listener.address().family;

if (family === 'IPv6') { host = '[' + host + ']'; }

console.log('Ember FastBoot running at http://' + host + ":" + port);
}, function(error) {
if (error.stack) {
console.error('An error occured when booting Ember app...');
console.error(error.stack);
} else if (error.message) {
console.error('An error occured when booting Ember app: ' + error.message);
} else {
console.error('An unknown error occured when booting Ember app: ' + JSON.stringify(error));
}

process.exit(1);
});
64 changes: 36 additions & 28 deletions lib/ember-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,59 @@ var najax = require('najax');
var debug = require('debug')('ember-cli-fastboot:ember-app');
var emberDebug = require('debug')('ember-cli-fastboot:ember');

function EmberApp(options) {
this.appFile = options.appFile;
this.vendorFile = options.vendorFile;
var HTMLSerializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap);

debug("app created; app=%s; vendor=%s", this.appFile, this.vendorFile);
function EmberApp(options) {
var appFilePath = options.appFile;
var vendorFilePath = options.vendorFile;

// Promise that represents the completion of app boot.
var appBoot = RSVP.defer();
debug("app created; app=%s; vendor=%s", appFilePath, vendorFilePath);

// Create the sandbox, giving it the resolver to resolve once the app
// has booted.
var sandbox = createSandbox(appBoot.resolve, {
najax: najax
});
var sandbox = createSandbox({ najax: najax });

appFile = fs.readFileSync(this.appFile, 'utf8');
vendorFile = fs.readFileSync(this.vendorFile, 'utf8');
var appFile = fs.readFileSync(appFilePath, 'utf8');
var vendorFile = fs.readFileSync(vendorFilePath, 'utf8');

sandbox.run(vendorFile);
debug("vendor file evaluated");

sandbox.run(appFile);
debug("app file evaluated");

this.waitForBoot = function() {
return appBoot.promise;
};
var AppFactory = sandbox.require('~fastboot/app-factory');

if (!AppFactory || typeof AppFactory['default'] !== 'function') {
throw new Error('Failed to load Ember app from ' + appFilePath + ', make sure it was built for FastBoot with the `ember fastboot:build` command.');
}

this._app = AppFactory['default']();
}

this.waitForBoot().then(function() {
debug("app booted");
EmberApp.prototype.boot = function() {
return this._app.boot();
};

EmberApp.prototype.visit = function(url) {
var doc = new SimpleDOM.Document();
var rootElement = doc.body;
var options = { isBrowser: false, document: doc, rootElement: rootElement };

return this._app.visit(url, options).then(function(instance) {
try {
return {
url: instance.getURL(), // TODO: use this to determine whether to 200 or redirect
title: doc.title,
body: HTMLSerializer.serialize(rootElement) // This matches the current code; but we probably want `serializeChildren` here
};
} finally {
instance.destroy();
}
});
}

function createSandbox(appBootResolver, dependencies) {
function createSandbox(dependencies) {
var wrappedConsole = Object.create(console);
wrappedConsole.error = function() {
console.error.apply(console, Array.prototype.map.call(arguments, function(a) {
Expand All @@ -50,11 +69,6 @@ function createSandbox(appBootResolver, dependencies) {
};

var sandbox = {
// Expose this so that the FastBoot initializer has access to the fake DOM.
// We don't expose this as `document` so that other libraries don't mistakenly
// think they have a full DOM.
SimpleDOM: SimpleDOM,

// Expose the console to the FastBoot environment so we can debug
console: wrappedConsole,

Expand All @@ -64,12 +78,6 @@ function createSandbox(appBootResolver, dependencies) {
// Convince jQuery not to assume it's in a browser
module: { exports: {} },

// Expose a hook for the Ember app to provide its handleURL functionality
FastBoot: {
resolve: appBootResolver,
debug: emberDebug
},

URL: require("url")
};

Expand Down
14 changes: 6 additions & 8 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,13 @@ FastBootServer.prototype.middleware = function() {

var server = this;

this.app.waitForBoot().then(function(handleURL) {
debug("handling url; url=%s", path);
handleURL(path).then(
success, failure
).finally(function() {
debug("handling url; url=%s", path);

this.app.visit(path)
.then(success, failure)
.finally(function() {
debug("finished handling; url=%s", path);
});
})
.catch(failure);
})

function success(result) {
server.handleSuccess(res, path, result);
Expand Down

0 comments on commit 6ae5e6e

Please sign in to comment.