From fbbd195f9f121aa8c2946d4a2ea30e546068d601 Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Thu, 8 Oct 2015 07:13:07 -0700 Subject: [PATCH] [WIP] Use latest visit API --- app/initializers/fastboot.js | 65 ------------------ app/initializers/{ => server}/ajax.js | 14 +--- app/initializers/server/dom-helper-patches.js | 17 +++++ .../{ => browser}/clear-double-boot.js | 5 +- index.js | 67 +++++++++++++++++-- package.json | 4 +- 6 files changed, 85 insertions(+), 87 deletions(-) delete mode 100644 app/initializers/fastboot.js rename app/initializers/{ => server}/ajax.js (66%) create mode 100644 app/initializers/server/dom-helper-patches.js rename app/instance-initializers/{ => browser}/clear-double-boot.js (89%) diff --git a/app/initializers/fastboot.js b/app/initializers/fastboot.js deleted file mode 100644 index 2ab82fbdf..000000000 --- a/app/initializers/fastboot.js +++ /dev/null @@ -1,65 +0,0 @@ -/*globals SimpleDOM, Ember, FastBoot, URL*/ - -export default { - name: "fast-boot", - - initialize: function(App) { - // Detect if we're running in Node. If not, there's nothing to do. - if (typeof document === 'undefined') { - var doc = new SimpleDOM.Document(); - var domHelper = new Ember.HTMLBars.DOMHelper(doc); - - domHelper.protocolForURL = function(url) { - var protocol = URL.parse(url).protocol; - return (protocol == null) ? ':' : protocol; - }; - - domHelper.setMorphHTML = function(morph, html) { - var section = this.document.createRawHTMLSection(html); - morph.setNode(section); - }; - - // Disable autobooting of the app. This will disable automatic routing, - // and routing will only occur via our calls to visit(). - App.autoboot = false; - - // This needs to be setting up renderer:main, and ideally would have a less hacked - // up interface. In particular, the only ACTUAL swap-in here is the fake document, - // so it would be nice if we could register just that. - App.register('renderer:-dom', { - create: function() { - var Renderer = Ember._Renderer || Ember.View._Renderer; - return new Renderer(domHelper, false); - } - }); - - FastBoot.debug("resolving FastBoot promise"); - - FastBoot.resolve(function(url) { - FastBoot.debug("routing; url=%s", url); - - var promise; - Ember.run(function() { - promise = App.visit(url); - }); - - return promise.then(function(instance) { - var view = instance.view; - var title = view.renderer._dom.document.title; - var element; - - Ember.run(function() { - element = view.renderToElement(); - }); - - var serializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap); - - return { - body: serializer.serialize(element), - title: title - }; - }); - }); - } - } -}; diff --git a/app/initializers/ajax.js b/app/initializers/server/ajax.js similarity index 66% rename from app/initializers/ajax.js rename to app/initializers/server/ajax.js index fce421df2..aba6ecda6 100644 --- a/app/initializers/ajax.js +++ b/app/initializers/server/ajax.js @@ -1,4 +1,4 @@ -/*globals najax, FastBoot, Ember*/ +/*globals najax, Ember*/ var nodeAjax = function(url, type, options) { var adapter = this; @@ -22,15 +22,7 @@ export default { name: 'ajax-service', initialize: function(application) { - // Detect if we're running in Node. If not, there's nothing to do. - if (typeof document === 'undefined') { - application.register('ajax:node', { - create: function() { - return nodeAjax; - } - }); - - application.inject('adapter', 'ajax', 'ajax:node'); - } + application.register('ajax:node', nodeAjax, { instantiate: false }); + application.inject('adapter', 'ajax', 'ajax:node'); } }; diff --git a/app/initializers/server/dom-helper-patches.js b/app/initializers/server/dom-helper-patches.js new file mode 100644 index 000000000..04b7a8ab5 --- /dev/null +++ b/app/initializers/server/dom-helper-patches.js @@ -0,0 +1,17 @@ +/*globals Ember, URL*/ +export default { + name: "dom-helper-patches", + + initialize: function(App) { + // TODO: remove me + Ember.HTMLBars.DOMHelper.prototype.protocolForURL = function(url) { + var protocol = URL.parse(url).protocol; + return (protocol == null) ? ':' : protocol; + }; + + // TODO: remove me https://github.com/tildeio/htmlbars/pull/425 + Ember.HTMLBars.DOMHelper.prototype.parseHTML = function(html) { + return this.document.createRawHTMLSection(html); + }; + } +}; diff --git a/app/instance-initializers/clear-double-boot.js b/app/instance-initializers/browser/clear-double-boot.js similarity index 89% rename from app/instance-initializers/clear-double-boot.js rename to app/instance-initializers/browser/clear-double-boot.js index 2508b07d1..7a32a255e 100644 --- a/app/instance-initializers/clear-double-boot.js +++ b/app/instance-initializers/browser/clear-double-boot.js @@ -1,3 +1,5 @@ +/*globals Ember*/ + // When using `ember fastboot --serve-assets` the application output will // already be rendered to the DOM when the actual JavaScript loads. Ember // does not automatically clear its `rootElement` so this leads to the @@ -12,8 +14,7 @@ export default { var originalDidCreateRootView = instance.didCreateRootView; instance.didCreateRootView = function() { - Ember.$(instance.rootElement + ' .ember-view').remove(); - + Ember.$('.ember-view', instance.rootElement).remove(); originalDidCreateRootView.apply(instance, arguments); }; } diff --git a/index.js b/index.js index 9d26d9540..d58ce16e0 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,32 @@ /* jshint node: true */ 'use strict'; +var Funnel = require('broccoli-funnel'); + +// Expose the an factory for the creating the `Application` object +// with the proper config at a known path, so that the server does +// not have to disover the app's module prefix ("my-app"). +// +// The module defined here is prefixed with a `~` to make it less +// likely to collide with user code, since it is not possible to +// define a module with a name like this in the file system. +function fastbootAppModule(prefix) { + return [ + "", + "define('~fastboot/app-factory', ['{{MODULE_PREFIX}}/app', '{{MODULE_PREFIX}}/config/environment'], function(App, config) {", + " App = App['default'];", + " config = config['default'];", + "", + " return {", + " 'default': function() {", + " return App.create(config);", + " }", + " };", + "});", + "" + ].join("\n").replace(/\{\{MODULE_PREFIX\}\}/g, prefix); +} + module.exports = { name: 'ember-cli-fastboot', @@ -11,6 +37,22 @@ module.exports = { }; }, + config: function(/* environment, appConfig */) { + // do nothing unless running `ember fastboot` command + if (!process.env.EMBER_CLI_FASTBOOT) { return {}; } + + return { + autoRun: false, + storeConfigInMeta: false, + EmberENV: { + FEATURES: { 'ember-application-visit': true } + }, + APP: { + autoBoot: false + } + }; + }, + contentFor: function(type, config) { // do nothing unless running `ember fastboot` command if (!process.env.EMBER_CLI_FASTBOOT) { return; } @@ -23,17 +65,28 @@ module.exports = { return ""; } - if (type === 'vendor-prefix') { - return '// Added from ember-cli-fastboot \n' + - 'EmberENV.FEATURES = EmberENV.FEATURES || {};\n' + - 'EmberENV.FEATURES["ember-application-visit"] = true;\n'; + if (type === 'app-boot') { + return fastbootAppModule(config.modulePrefix); } }, - included: function() { + treeForApp: function(tree) { if (process.env.EMBER_CLI_FASTBOOT) { - this.app.options.storeConfigInMeta = false; - process.env.EMBER_CLI_FASTBOOT_APP_NAME = this.app.name; + return new Funnel(tree, { + annotation: 'Funnel: Remove browser-only initializers', + exclude: [ + 'initializers/browser/*', + 'instance-initializers/browser/*' + ] + }); + } else { + return new Funnel(tree, { + annotation: 'Funnel: Remove server-only initializers', + exclude: [ + 'initializers/server/*', + 'instance-initializers/server/*' + ] + }); } } }; diff --git a/package.json b/package.json index 915cbf9ac..29993987b 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "configPath": "tests/dummy/config" }, "dependencies": { + "broccoli-funnel": "0.2.8", "chalk": "^0.5.1", "contextify": "^0.1.11", "debug": "^2.1.0", @@ -49,7 +50,6 @@ "express": "^4.8.5", "glob": "^4.0.5", "najax": "^0.1.5", - "rsvp": "^3.0.16", - "simple-dom": "^0.2.7" + "rsvp": "^3.0.16" } }