diff --git a/README.md b/README.md index 5990aa403..c14592aef 100644 --- a/README.md +++ b/README.md @@ -551,6 +551,20 @@ fastbootConfigTree() { The above configuration will be available in Node via the `FastBoot.config()` function. Therefore, in order to get the above config, the addon/app can call `FastBoot.config('')`. +## Custom FastBoot Implementation + +This addon comes with the FastBoot library by default. If you must use a specific version of the FastBoot library or a fork of it, you can add it to your `package.json` and specify it inside your app's `ember-cli-build.js`: + +```js +const FastBoot = require('my-fastboot-fork'); + +const app = new EmberApp({ + fastboot: { + implementation: FastBoot + } +}); +``` + ## Known Limitations While FastBoot is under active development, there are several major diff --git a/index.js b/index.js index 97a06ad13..8196b4e5f 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,6 @@ const fs = require('fs'); const MergeTrees = require('broccoli-merge-trees'); const FastBootExpressMiddleware = require('fastboot-express-middleware'); -const FastBoot = require('fastboot'); const chalk = require('chalk'); const fastbootAppBoot = require('./lib/utilities/fastboot-app-boot'); @@ -307,6 +306,9 @@ module.exports = { }, serverMiddleware(options) { + const { implementation } = this.app.options.fastboot || {}; + const FastBoot = implementation || require('fastboot'); + let emberCliVersion = this._getEmberCliVersion(); let app = options.app; diff --git a/test/custom-implementation-test.js b/test/custom-implementation-test.js new file mode 100644 index 000000000..bdd2faeb1 --- /dev/null +++ b/test/custom-implementation-test.js @@ -0,0 +1,41 @@ +'use strict'; + +const expect = require('chai').use(require('chai-string')).expect; +const RSVP = require('rsvp'); +const request = RSVP.denodeify(require('request')); + +const AddonTestApp = require('ember-cli-addon-tests').AddonTestApp; + +describe('custom fastboot implementation', function() { + this.timeout(300000); + + let app; + + before(function() { + app = new AddonTestApp(); + + return app.create('custom-implementation') + .then(function() { + return app.startServer({ + command: 'serve' + }); + }); + }); + + after(function() { + return app.stopServer(); + }); + + it('uses custom implementation', function() { + return request({ + url: 'http://localhost:49741/', + headers: { + 'Accept': 'text/html' + } + }) + .then(function(response) { + expect(response.statusCode).to.equal(200); + expect(response.body).to.equal('foobar'); + }); + }); +}); diff --git a/test/fixtures/custom-implementation/README.md b/test/fixtures/custom-implementation/README.md new file mode 100644 index 000000000..d6078e3ea --- /dev/null +++ b/test/fixtures/custom-implementation/README.md @@ -0,0 +1 @@ +This fixture app demonstrates the use of a custom FastBoot implementation. \ No newline at end of file diff --git a/test/fixtures/custom-implementation/config/environment.js b/test/fixtures/custom-implementation/config/environment.js new file mode 100644 index 000000000..e2584d5f0 --- /dev/null +++ b/test/fixtures/custom-implementation/config/environment.js @@ -0,0 +1,51 @@ +/* jshint node: true */ + +module.exports = function(environment) { + var ENV = { + modulePrefix: 'custom-implementation', + environment: environment, + baseURL: '/', + locationType: 'auto', + EmberENV: { + FEATURES: { + // Here you can enable experimental features on an ember canary build + // e.g. 'with-controller': true + } + }, + + APP: { + // Here you can pass flags/options to your application instance + // when it is created + }, + + fastboot: { + hostWhitelist: ['example.com', 'subdomain.example.com', /localhost:\d+/] + } + }; + + if (environment === 'development') { + // ENV.APP.LOG_RESOLVER = true; + // ENV.APP.LOG_ACTIVE_GENERATION = true; + // ENV.APP.LOG_TRANSITIONS = true; + // ENV.APP.LOG_TRANSITIONS_INTERNAL = true; + // ENV.APP.LOG_VIEW_LOOKUPS = true; + } + + if (environment === 'test') { + // Testem prefers this... + ENV.baseURL = '/'; + ENV.locationType = 'none'; + + // keep test console output quieter + ENV.APP.LOG_ACTIVE_GENERATION = false; + ENV.APP.LOG_VIEW_LOOKUPS = false; + + ENV.APP.rootElement = '#ember-testing'; + } + + if (environment === 'production') { + + } + + return ENV; +}; diff --git a/test/fixtures/custom-implementation/ember-cli-build.js b/test/fixtures/custom-implementation/ember-cli-build.js new file mode 100644 index 000000000..1cc62f89f --- /dev/null +++ b/test/fixtures/custom-implementation/ember-cli-build.js @@ -0,0 +1,30 @@ +class FakeFastBoot { + visit() { + return new Promise(resolve => { + resolve({ + statusCode: 200, + headers: { + entries() { + return []; + } + }, + html() { + return new Promise(resolve => { + resolve('foobar'); + }); + } + }) + }); + } +} + +module.exports = function(defaults) { + var EmberApp = require('ember-cli/lib/broccoli/ember-app'); + var app = new EmberApp(defaults, { + fastboot: { + implementation: FakeFastBoot + } + }); + + return app.toTree(); +};