ember-cli-fastboot
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -22,11 +22,8 @@ /*globals najax, FastBoot, Ember*/ | ||
export default { | ||
name: "ajax-service", | ||
name: 'ajax-service', | ||
initialize: function(registry) { | ||
initialize: function(application) { | ||
// Detect if we're running in Node. If not, there's nothing to do. | ||
if (typeof document === 'undefined') { | ||
// 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. | ||
registry.register('ajax:node', { | ||
application.register('ajax:node', { | ||
create: function() { | ||
@@ -37,5 +34,5 @@ return nodeAjax; | ||
registry.injection('adapter', 'ajax', 'ajax:node'); | ||
application.inject('adapter', 'ajax', 'ajax:node'); | ||
} | ||
} | ||
}; |
@@ -10,3 +10,3 @@ /*globals SimpleDOM, Ember, FastBoot, URL*/ | ||
var doc = new SimpleDOM.Document(); | ||
var domHelper = new Ember.View.DOMHelper(doc); | ||
var domHelper = new Ember.HTMLBars.DOMHelper(doc); | ||
@@ -18,2 +18,7 @@ domHelper.protocolForURL = function(url) { | ||
domHelper.setMorphHTML = function(morph, html) { | ||
var section = this.document.createRawHTMLSection(html); | ||
morph.setNode(section); | ||
}; | ||
// Disable autobooting of the app. This will disable automatic routing, | ||
@@ -28,3 +33,4 @@ // and routing will only occur via our calls to visit(). | ||
create: function() { | ||
return new Ember.View._Renderer(domHelper, false); | ||
var Renderer = Ember._Renderer || Ember.View._Renderer; | ||
return new Renderer(domHelper, false); | ||
} | ||
@@ -38,5 +44,10 @@ }); | ||
return App.visit(url).then(function(instance) { | ||
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; | ||
@@ -48,6 +59,8 @@ | ||
element = element.firstChild; | ||
var serializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap); | ||
var serializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap); | ||
return serializer.serialize(element); | ||
return { | ||
body: serializer.serialize(element), | ||
title: title | ||
}; | ||
}); | ||
@@ -54,0 +67,0 @@ }); |
{ | ||
"name": "ember-cli-fastboot", | ||
"dependencies": { | ||
"handlebars": "~1.3.0", | ||
"jquery": "^1.11.1", | ||
"ember": "1.8.1", | ||
"ember-data": "1.0.0-beta.12", | ||
"ember-resolver": "~0.1.11", | ||
"loader.js": "ember-cli/loader.js#1.0.1", | ||
"ember": "canary", | ||
"ember-data": "canary", | ||
"ember-resolver": "~0.1.12", | ||
"loader.js": "ember-cli/loader.js#3.2.0", | ||
"ember-cli-shims": "ember-cli/ember-cli-shims#0.0.3", | ||
"ember-cli-test-loader": "rwjblue/ember-cli-test-loader#0.0.4", | ||
"ember-cli-test-loader": "ember-cli-test-loader#0.1.3", | ||
"ember-load-initializers": "ember-cli/ember-load-initializers#0.0.2", | ||
"ember-qunit": "0.1.8", | ||
"ember-qunit-notifications": "0.0.4", | ||
"qunit": "~1.15.0" | ||
"ember-qunit": "0.2.8", | ||
"ember-qunit-notifications": "0.0.7", | ||
"qunit": "~1.17.1" | ||
}, | ||
"resolutions": { | ||
"ember": "canary" | ||
} | ||
} |
/* global require, module */ | ||
var EmberApp = require('ember-cli/lib/broccoli/ember-app'); | ||
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon'); | ||
var app = new EmberApp(); | ||
var app = new EmberAddon(); | ||
@@ -7,0 +7,0 @@ // Use `app.import` to add additional libraries to the generated |
29
index.js
@@ -9,5 +9,32 @@ /* jshint node: true */ | ||
return { | ||
fastboot: require('./lib/commands/fastboot') | ||
fastboot: require('./lib/commands/fastboot'), | ||
'fastboot:build': require('./lib/commands/fastboot-build') | ||
}; | ||
}, | ||
contentFor: function(type, config) { | ||
// do nothing unless running `ember fastboot` command | ||
if (!process.env.EMBER_CLI_FASTBOOT) { return; } | ||
if (type === 'body') { | ||
return "<!-- EMBER_CLI_FASTBOOT_BODY -->"; | ||
} | ||
if (type === 'head') { | ||
return "<!-- EMBER_CLI_FASTBOOT_TITLE -->"; | ||
} | ||
if (type === 'vendor-prefix') { | ||
return '// Added from ember-cli-fastboot \n' + | ||
'EmberENV.FEATURES = EmberENV.FEATURES || {};\n' + | ||
'EmberENV.FEATURES["ember-application-visit"] = true;\n'; | ||
} | ||
}, | ||
included: function() { | ||
if (process.env.EMBER_CLI_FASTBOOT) { | ||
this.app.options.storeConfigInMeta = false; | ||
process.env.EMBER_CLI_FASTBOOT_APP_NAME = this.app.name; | ||
} | ||
} | ||
}; |
@@ -0,1 +1,3 @@ | ||
var path = require('path'); | ||
module.exports = { | ||
@@ -8,3 +10,5 @@ name: 'fastboot', | ||
{ name: 'environment', type: String, default: 'development', aliases: ['e',{'dev' : 'development'}, {'prod' : 'production'}] }, | ||
{ name: 'port', type: Number, default: 3000 } | ||
{ name: 'serve-assets', type: Boolean, default: false}, | ||
{ name: 'port', type: Number, default: 3000 }, | ||
{ name: 'output-path', type: String, default: 'fastboot-dist' } | ||
], | ||
@@ -16,7 +20,8 @@ | ||
var express = require('express'); | ||
var outputPath = this.commandOptions.outputPath; | ||
var server = new FastBootServer({ | ||
appFile: findAppFile(appName), | ||
vendorFile: findVendorFile(), | ||
htmlFile: findHTMLFile(), | ||
appFile: findAppFile(outputPath, appName), | ||
vendorFile: findVendorFile(outputPath), | ||
htmlFile: findHTMLFile(outputPath), | ||
ui: this.ui | ||
@@ -26,2 +31,8 @@ }); | ||
var app = express(); | ||
if (this.commandOptions.serveAssets) { | ||
app.get('/', server.middleware()); | ||
app.use(express.static(outputPath)); | ||
} | ||
app.get('/*', server.middleware()); | ||
@@ -34,3 +45,6 @@ | ||
var port = listener.address().port; | ||
var family = listener.address().family; | ||
if (family === 'IPv6') { host = '[' + host + ']'; } | ||
ui.writeLine('Ember FastBoot running at http://' + host + ":" + port); | ||
@@ -51,4 +65,2 @@ }); | ||
commandOptions.environment = commandOptions.environment || 'development'; | ||
commandOptions.outputPath = 'dist'; | ||
return buildTask.run(commandOptions); | ||
@@ -58,4 +70,10 @@ }, | ||
run: function(options, args) { | ||
process.env.EMBER_CLI_FASTBOOT = true; | ||
this.commandOptions = options; | ||
var runCommand = function() { | ||
return this.runCommand(this.project.name(), options); | ||
var appName = process.env.EMBER_CLI_FASTBOOT_APP_NAME || this.project.name(); | ||
return this.runCommand(appName, options); | ||
}.bind(this); | ||
@@ -72,19 +90,12 @@ | ||
function findAppFile(appName) { | ||
return findFile("app", "dist/assets/" + appName + "*.js"); | ||
function findAppFile(outputPath, appName) { | ||
return findFile("app", path.join(outputPath, "assets", appName + "*.js")); | ||
} | ||
function findVendorFile() { | ||
return findFile("vendor", "dist/assets/vendor*.js"); | ||
function findVendorFile(outputPath) { | ||
return findFile("vendor", path.join(outputPath, "assets", "vendor*.js")); | ||
} | ||
function findHTMLFile() { | ||
var fs = require('fs'); | ||
if (fs.existsSync('app/fastboot.html')) { | ||
return 'app/fastboot.html'; | ||
} else if (fs.existsSync('app/index.html')) { | ||
return 'app/index.html'; | ||
} | ||
assert("Could not find either app/fastboot.html or app/index.html. Please provide an HTML file to serve FastBoot contents in.", false); | ||
function findHTMLFile(outputPath) { | ||
return findFile('html', path.join(outputPath, 'index*.html')); | ||
} | ||
@@ -91,0 +102,0 @@ |
@@ -26,9 +26,9 @@ var fs = require('fs'); | ||
appFile = fs.readFileSync(this.appFile); | ||
vendorFile = fs.readFileSync(this.vendorFile); | ||
appFile = fs.readFileSync(this.appFile, 'utf8'); | ||
vendorFile = fs.readFileSync(this.vendorFile, 'utf8'); | ||
sandbox.run(vendorFile.toString()); | ||
sandbox.run(vendorFile); | ||
debug("vendor file evaluated"); | ||
sandbox.run(appFile.toString()); | ||
sandbox.run(appFile); | ||
debug("app file evaluated"); | ||
@@ -83,2 +83,3 @@ | ||
sandbox.window = sandbox; | ||
sandbox.window.self = sandbox; | ||
@@ -85,0 +86,0 @@ // The sandbox is now a JavaScript context O_o |
@@ -1,2 +0,1 @@ | ||
var express = require('express'); | ||
var chalk = require('chalk'); | ||
@@ -13,4 +12,3 @@ var fs = require('fs'); | ||
this.html = fs.readFileSync(options.htmlFile); | ||
this.html = this.html.toString(); | ||
this.html = fs.readFileSync(options.htmlFile, 'utf8'); | ||
@@ -26,7 +24,8 @@ this.ui = options.ui; | ||
var contentForRegex = /\{\{content-for ['"](.+)["']\}\}/g; | ||
FastBootServer.prototype.insertIntoIndexHTML = function(title, body) { | ||
var html = this.html.replace("<!-- EMBER_CLI_FASTBOOT_BODY -->", body); | ||
FastBootServer.prototype.insertIntoIndexHTML = function(body) { | ||
var html = this.html.replace("{{content-for 'body'}}", body); | ||
html = html.replace(contentForRegex, ''); | ||
if (title) { | ||
html = html.replace("<!-- EMBER_CLI_FASTBOOT_TITLE -->", "<title>" + title + "</title>"); | ||
} | ||
@@ -36,5 +35,5 @@ return html; | ||
FastBootServer.prototype.handleSuccess = function(res, path, body) { | ||
FastBootServer.prototype.handleSuccess = function(res, path, result) { | ||
this.log(200, 'OK ' + path); | ||
res.send(this.insertIntoIndexHTML(body)); | ||
res.send(this.insertIntoIndexHTML(result.title, result.body)); | ||
}; | ||
@@ -45,3 +44,3 @@ | ||
this.log(404, "Not Found " + path); | ||
res.sendStatus(400); | ||
res.sendStatus(404); | ||
} else { | ||
@@ -69,3 +68,2 @@ console.log(error.stack); | ||
debug("handling url; url=%s", path); | ||
debug("handleURL; %s", handleURL); | ||
handleURL(path).then( | ||
@@ -76,11 +74,12 @@ success, failure | ||
}); | ||
}) | ||
.catch(failure); | ||
function success(body) { | ||
server.handleSuccess(res, path, body); | ||
} | ||
function success(result) { | ||
server.handleSuccess(res, path, result); | ||
} | ||
function failure(error) { | ||
server.handleFailure(res, path, error); | ||
} | ||
}); | ||
function failure(error) { | ||
server.handleFailure(res, path, error); | ||
} | ||
}.bind(this); | ||
@@ -87,0 +86,0 @@ }; |
{ | ||
"name": "ember-cli-fastboot", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Server-side rendering for Ember.js apps", | ||
@@ -10,2 +10,7 @@ "directories": { | ||
"repository": "https://github.com/tildeio/ember-cli-fastboot", | ||
"scripts": { | ||
"start": "ember server", | ||
"build": "ember build", | ||
"test": "mocha tests/acceptance" | ||
}, | ||
"engines": { | ||
@@ -18,12 +23,17 @@ "node": ">= 0.10.0" | ||
"broccoli-asset-rev": "^2.0.0", | ||
"broccoli-ember-hbs-template-compiler": "^1.6.1", | ||
"ember-cli": "0.1.7", | ||
"chai": "^2.2.0", | ||
"ember-cli": "0.2.3", | ||
"ember-cli-app-version": "0.3.2", | ||
"ember-cli-babel": "^4.0.0", | ||
"ember-cli-content-security-policy": "0.3.0", | ||
"ember-cli-dependency-checker": "0.0.7", | ||
"ember-cli-6to5": "0.2.1", | ||
"ember-cli-dependency-checker": "0.0.8", | ||
"ember-cli-htmlbars": "0.7.4", | ||
"ember-cli-ic-ajax": "0.1.1", | ||
"ember-cli-inject-live-reload": "^1.3.0", | ||
"ember-cli-qunit": "0.1.2", | ||
"ember-data": "1.0.0-beta.12", | ||
"ember-export-application-global": "^1.0.0" | ||
"ember-cli-qunit": "0.3.9", | ||
"ember-cli-uglify": "1.0.1", | ||
"ember-data": "1.0.0-beta.16.1", | ||
"ember-export-application-global": "^1.0.2", | ||
"mocha": "^2.2.4", | ||
"request": "^2.55.0" | ||
}, | ||
@@ -40,3 +50,3 @@ "keywords": [ | ||
"rsvp": "^3.0.16", | ||
"simple-dom": "0.2.1", | ||
"simple-dom": "^0.2.7", | ||
"chalk": "^0.5.1", | ||
@@ -43,0 +53,0 @@ "express": "^4.8.5", |
129
README.md
@@ -19,32 +19,9 @@ # Ember FastBoot | ||
``` | ||
ember install:addon ember-cli-fastboot | ||
ember install ember-cli-fastboot | ||
``` | ||
In order to get FastBoot working, you will first need to do the | ||
following: | ||
In order to get FastBoot working, you will first need to enable Ember Canary: | ||
* Disable Ember CLI's default configuration meta tag | ||
* Install Ember Canary and enable HTMLbars | ||
* Enable the required feature flags | ||
* Set the router's location to NoneLocation | ||
#### Disable Default Configuration | ||
Modify your application's generated `Brocfile` to disable storing | ||
configuration information in a `<meta>` tag: | ||
```js | ||
// Brocfile.js | ||
var app = new EmberApp({ | ||
storeConfigInMeta: false | ||
}); | ||
``` | ||
#### Install Ember Canary and Enable HTMLbars | ||
To enable Ember canary and HTMLbars, run the following commands: | ||
``` | ||
rm -rf bower_components | ||
bower install --save handlebars#~2.0.0 | ||
bower install --save ember#canary | ||
@@ -55,37 +32,7 @@ bower install | ||
Bower also prompts you to confirm various "resolutions" that it is | ||
unsure of. Make sure you pick ember#canary and Handlebars 2.0 if | ||
prompted. | ||
unsure of. Make sure you pick ember#canary if prompted. | ||
Then update the npm dependencies: | ||
``` | ||
npm uninstall --save-dev broccoli-ember-hbs-template-compiler | ||
npm install --save-dev ember-cli-htmlbars | ||
``` | ||
For more details, [see this blog | ||
post](http://reefpoints.dockyard.com/2014/11/30/htmlbars_calling_all_testers.html). | ||
#### Enable Required Feature Flags | ||
Lastly, enabled the following feature flags: | ||
* `ember-application-instance-initializers` | ||
* `ember-application-visit` | ||
To enable the these flags, add the following to your | ||
`config/environment.js` (under the `EmberENV.FEATURES` section): | ||
```js | ||
EmberENV: { | ||
FEATURES: { | ||
'ember-application-instance-initializers': true, | ||
'ember-application-visit': true | ||
} | ||
}, | ||
``` | ||
## Running | ||
* `ember fastboot` | ||
* `ember fastboot --serve-assets` | ||
* Visit your app at `http://localhost:3000`. | ||
@@ -156,1 +103,69 @@ | ||
crawlers. | ||
## Troubleshooting | ||
Because your app is now running in Node.js, not the browser, you'll | ||
need a new set of tools to diagnose problems when things go wrong. Here | ||
are some tips and tricks we use for debugging our own apps. | ||
### Verbose Logging | ||
Enable verbose logging by running the FastBoot server with the following | ||
environment variables set: | ||
```sh | ||
DEBUG=ember-cli-fastboot:* ember fastboot | ||
``` | ||
PRs adding or improving logging facilities are very welcome. | ||
### Developer Tools | ||
You can get a debugging environment similar to the Chrome developer | ||
tools running with a FastBoot app, although it's not (yet) as easy as | ||
in the browser. | ||
First, install the Node Inspector: | ||
```sh | ||
npm install node-inspector -g | ||
``` | ||
Make sure you install a recent release; in our experience, older | ||
versions will segfault when used in conjunction with Contextify, which | ||
FastBoot uses for sandboxing. | ||
Next, start the inspector server. We found the experience too slow to be | ||
usable until we discovered the `--no-preload` flag, which waits to | ||
fetch the source code for a given file until it's actually needed. | ||
```sh | ||
node-inspector --no-preload | ||
``` | ||
Once the debug server is running, you'll want to start up the FastBoot | ||
server with Node in debug mode. One thing about debug mode: it makes | ||
everything much slower. Since the `ember fastboot` command does a full | ||
build when launched, this becomes agonizingly slow in debug mode. | ||
Avoid the slowness by manually running the build in normal mode, then | ||
running FastBoot in debug mode without doing a build: | ||
```sh | ||
ember build && node --debug-brk ./node_modules/.bin/ember fastboot --no-build | ||
``` | ||
This does a full rebuild and then starts the FastBoot server in debug | ||
mode. Note that the `--debug-brk` flag will cause your app to start | ||
paused to give you a chance to open the debugger. | ||
Once you see the output `debugger listening on port 5858`, visit | ||
[http://127.0.0.1:8080/debug?port=5858](http://127.0.0.1:8080/debug?port=5858) | ||
in your browser. Once it loads, click the "Resume script execution" | ||
button (it has a ▶︎ icon) to let FastBoot continue loading. | ||
Assuming your app loads without an exception, after a few seconds you | ||
will see a message that FastBoot is listening on port 3000. Once you see | ||
that, you can open a connection; any exceptions should be logged in the | ||
console, and you can use the tools you'd expect such as `console.log`, | ||
`debugger` statements, etc. |
{ | ||
"framework": "qunit", | ||
"test_page": "tests/index.html", | ||
"test_page": "tests/index.html?hidepassed", | ||
"launch_in_ci": [ | ||
@@ -5,0 +5,0 @@ "PhantomJS" |
@@ -9,4 +9,6 @@ import Ember from 'ember'; | ||
Router.map(function() { | ||
this.route('posts'); | ||
this.route('boom'); | ||
}); | ||
export default Router; |
@@ -7,7 +7,1 @@ import resolver from './helpers/resolver'; | ||
setResolver(resolver); | ||
document.write('<div id="ember-testing-container"><div id="ember-testing"></div></div>'); | ||
QUnit.config.urlConfig.push({ id: 'nocontainer', label: 'Hide container'}); | ||
var containerVisibility = QUnit.urlParams.nocontainer ? 'hidden' : 'visible'; | ||
document.getElementById('ember-testing-container').style.visibility = containerVisibility; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
36249
52
694
169
16
10
+ Addedsimple-dom@0.2.7(transitive)
- Removedsimple-dom@0.2.1(transitive)
Updatedsimple-dom@^0.2.7