Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ export default {
name: "clear-double-boot",

initialize: function(instance) {
var originalDidCreateRootView = instance.didCreateRootView;
if (typeof FastBoot === 'undefined') {
var originalDidCreateRootView = instance.didCreateRootView;

instance.didCreateRootView = function() {
let elements = document.querySelectorAll(instance.rootElement + ' .ember-view');
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
element.parentNode.removeChild(element);
}
instance.didCreateRootView = function() {
let elements = document.querySelectorAll(instance.rootElement + ' .ember-view');
for (let i = 0; i < elements.length; i++) {
let element = elements[i];
element.parentNode.removeChild(element);
}

originalDidCreateRootView.apply(instance, arguments);
};
originalDidCreateRootView.apply(instance, arguments);
};
}
}
}
File renamed without changes.
222 changes: 153 additions & 69 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,67 +1,76 @@
/* eslint-env node */
'use strict';

var path = require('path');
const path = require('path');
const fs = require('fs');

var EventEmitter = require('events').EventEmitter;
var mergeTrees = require('broccoli-merge-trees');
var VersionChecker = require('ember-cli-version-checker');
var FastBootExpressMiddleware = require('fastboot-express-middleware');
var FastBoot = require('fastboot');
var chalk = require('chalk');
const EventEmitter = require('events').EventEmitter;
const MergeTrees = require('broccoli-merge-trees');
const FastBootExpressMiddleware = require('fastboot-express-middleware');
const FastBoot = require('fastboot');
const chalk = require('chalk');

var patchEmberApp = require('./lib/ext/patch-ember-app');
var fastbootAppModule = require('./lib/utilities/fastboot-app-module');
const fastbootAppModule = require('./lib/utilities/fastboot-app-module');
const FastBootConfig = require('./lib/broccoli/fastboot-config');
const migrateInitializers = require('./lib/build-utilities/migrate-initializers');

var filterInitializers = require('fastboot-filter-initializers');
var FastBootBuild = require('./lib/broccoli/fastboot-build');
const Concat = require('broccoli-concat');
const Funnel = require('broccoli-funnel');
const p = require('ember-cli-preprocess-registry/preprocessors');
const existsSync = require('exists-sync');

/*
* Main entrypoint for the Ember CLI addon.
*/

module.exports = {
name: 'ember-cli-fastboot',


init() {
this._super.init && this._super.init.apply(this, arguments);

// TODO remove once serve PR is checked in
this.emitter = new EventEmitter();
},

// TODO remove once serve PR is checked in
includedCommands: function() {
return {
'fastboot': require('./lib/commands/fastboot')(this),

/* fastboot:build is deprecated and will be removed in a future version */
'fastboot:build': require('./lib/commands/fastboot-build')
};
},

// TODO remove once serve PR is checked in
on: function() {
this.emitter.on.apply(this.emitter, arguments);
},

// TODO remove once serve PR is checked in
emit: function() {
this.emitter.emit.apply(this.emitter, arguments);
},

/**
* Called at the start of the build process to let the addon know it will be
* used. At this point, we can rely on the EMBER_CLI_FASTBOOT environment
* variable being set.
* used. Sets the auto run on app to be false so that we create and route app
* automatically only in browser.
*
* Once we've determined which mode we're in (browser build or FastBoot build),
* we mixin additional Ember addon hooks appropriate to the current build target.
* See: https://ember-cli.com/user-guide/#integration
*/
included: function(app) {
patchEmberApp(app);
},

config: function() {
if (this.app && this.app.options.__is_building_fastboot__) {
return { APP: { autoboot: false } };
}
// set autoRun to false since we will conditionally include creating app when app files
// is eval'd in app-boot
app.options.autoRun = false;
// get the app registry object and app name so that we can build the fastboot
// tree
this._appRegistry = app.registry;
this._name = app.name;

// set a environment variable to allow addons to use `fastboot-filter-initializers`
// for old versions.
process.env.FASTBOOT_NEW_BUILD = true;

migrateInitializers(this.project);
},

/**
Expand All @@ -79,83 +88,156 @@ module.exports = {
}

if (type === 'app-boot') {
return fastbootAppModule(config.modulePrefix);
return fastbootAppModule(config.modulePrefix, JSON.stringify(config.APP || {}));
}

if (type === 'config-module' && this.app.options.__is_building_fastboot__) {
var linesToRemove = contents.length;
while(linesToRemove) {
// Clear out the default config from ember-cli
contents.pop();
linesToRemove--;
}

return 'return FastBoot.config();';
// if the fastboot addon is installed, we overwrite the config-module so that the config can be read
// from meta tag for browser build and from Fastboot config for fastboot target
if (type === 'config-module') {
const emberCliPath = path.join(this.app.project.nodeModulesPath, 'ember-cli');
contents.splice(0, contents.length);
contents.push('if (typeof FastBoot !== \'undefined\') {');
contents.push('return FastBoot.config();');
contents.push('} else {');
contents.push('var prefix = \'' + config.modulePrefix + '\';');
contents.push(fs.readFileSync(path.join(emberCliPath, 'lib/broccoli/app-config-from-meta.js')));
contents.push('}');
return;
}
},

treeForApp: function(defaultTree) {
var trees = [defaultTree];
treeForFastBoot: function(tree) {
let fastbootHtmlBarsTree;

// check the ember-cli version and conditionally patch the DOM api
if (this._getEmberVersion().lt('2.10.0-alpha.1')) {
trees.push(this.treeGenerator(path.resolve(this.root, 'app-lt-2-9')));
fastbootHtmlBarsTree = this.treeGenerator(path.resolve(__dirname, 'fastboot-app-lt-2-9'));
return tree ? new MergeTrees([tree, fastbootHtmlBarsTree]) : fastbootHtmlBarsTree;
}

return mergeTrees(trees, { overwrite: true });
return tree;
},

/**
* Filters out initializers and instance initializers that should only run in
* browser mode.
* Function that builds the fastboot tree from all fastboot complaint addons
* and project and transpiles it into appname-fastboot.js
*/
preconcatTree: function(tree) {
return filterInitializers(tree, this.app.name);
_getFastbootTree: function() {
const appName = this._name;
const nodeModulesPath = this.project.nodeModulesPath;

let fastbootTrees = [];
this.project.addons.forEach((addon) => {
// walk through each addon and grab its fastboot tree
const currentAddonFastbootPath = path.join(nodeModulesPath, addon.name, 'fastboot');
let fastbootTree;
if (existsSync(currentAddonFastbootPath)) {
fastbootTree = this.treeGenerator(currentAddonFastbootPath);
fastbootTrees.push(fastbootTree);
}

// invoke addToFastBootTree for every addon
if (addon.treeForFastBoot) {
let additionalFastBootTree = addon.treeForFastBoot(fastbootTree);
if (additionalFastBootTree) {
fastbootTrees.push(additionalFastBootTree);
}
}
});

// check the parent containing the fastboot directory
const projectFastbootPath = path.join(this.project.root, 'fastboot');
if (existsSync(projectFastbootPath)) {
let fastbootTree = this.treeGenerator(projectFastbootPath);
fastbootTrees.push(fastbootTree);
}

// transpile the fastboot JS tree
let mergedFastBootTree = new MergeTrees(fastbootTrees, {
overwrite: true
});
let funneledFastbootTrees = new Funnel(mergedFastBootTree, {
destDir: appName
});
const processExtraTree = p.preprocessJs(funneledFastbootTrees, '/', this._name, {
registry: this._appRegistry
});

let fileAppName = path.basename(this.app.options.outputPaths.app.js).split('.')[0];
let finalFastbootTree = new Concat(processExtraTree, {
outputFile: 'assets/' + fileAppName + '-fastboot.js'
});

return finalFastbootTree;
},

treeForPublic(tree) {
let fastbootTree = this._getFastbootTree();
let trees = [];
if (tree) {
trees.push(tree);
}
trees.push(fastbootTree);

let newTree = new MergeTrees(trees);

return newTree;
},

/**
* After the entire Broccoli tree has been built for the `dist` directory,
* adds the `fastboot-config.json` file to the root.
*
* FASTBOOT_DISABLED is a pre 1.0 power user flag to
* disable the fastboot build while retaining the fastboot service.
*/
postprocessTree: function(type, tree) {
if (type === 'all' && !process.env.FASTBOOT_DISABLED) {
var fastbootTree = this.buildFastBootTree();
if (type === 'all') {
let fastbootConfigTree = this._buildFastbootConfigTree(tree);

// Merge the package.json with the existing tree
return mergeTrees([tree, fastbootTree], {overwrite: true});
return new MergeTrees([tree, fastbootConfigTree], {overwrite: true});
}

return tree;
},

buildFastBootTree: function() {
var fastbootBuild = new FastBootBuild({
ui: this.ui,
_buildFastbootConfigTree : function(tree) {
let env = this.app.env;
let config = this.project.config(env);
let fastbootConfig = config.fastboot;
// do not boot the app automatically in fastboot. The instance is booted and
// lives for the lifetime of the request.
if ('APP' in config) {
config['APP']['autoboot'] = false;
} else {
config['APP'] = {
'autoboot': false
}
}

return new FastBootConfig(tree, {
assetMapPath: this.assetMapPath,
project: this.project,
app: this.app,
parent: this.parent
name: this.app.name,
outputPaths: this.app.options.outputPaths,
ui: this.ui,
fastbootAppConfig: fastbootConfig,
appConfig: config
});

return fastbootBuild.toTree();
},

serverMiddleware: function(options) {
var emberCliVersion = this._getEmberCliVersion();
var app = options.app;
var options = options.options;
let emberCliVersion = this._getEmberCliVersion();
let app = options.app;

if (emberCliVersion.gte('2.12.0-beta.1')) {
// only run the middleware when ember-cli version for app is above 2.12.0-beta.1 since
// that version contains API to hook fastboot into ember-cli

app.use((req, resp, next) => {
var fastbootQueryParam = (req.query.hasOwnProperty('fastboot') && req.query.fastboot === 'false') ? false : true;
var enableFastBootServe = !process.env.FASTBOOT_DISABLED && fastbootQueryParam;
var broccoliHeader = req.headers['x-broccoli'];
var outputPath = broccoliHeader['outputPath'];
const fastbootQueryParam = (req.query.hasOwnProperty('fastboot') && req.query.fastboot === 'false') ? false : true;
const enableFastBootServe = !process.env.FASTBOOT_DISABLED && fastbootQueryParam;
const broccoliHeader = req.headers['x-broccoli'];
const outputPath = broccoliHeader['outputPath'];

if (broccoliHeader['url'] === req.serveUrl && enableFastBootServe) {
// if it is a base page request, then have fastboot serve the base page
Expand All @@ -168,7 +250,7 @@ module.exports = {
});
}

var fastbootMiddleware = FastBootExpressMiddleware({
let fastbootMiddleware = FastBootExpressMiddleware({
fastboot: this.fastboot
});

Expand All @@ -181,10 +263,12 @@ module.exports = {
}
},

// TODO remove once serve PR is checked in
outputReady: function() {
this.emit('outputReady');
},

// TODO remove once serve PR is checked in
postBuild: function(result) {
this.emit('postBuild');
if (this.fastboot) {
Expand All @@ -199,16 +283,16 @@ module.exports = {
},

_getEmberCliVersion: function() {
var VersionChecker = require('ember-cli-version-checker');
var checker = new VersionChecker(this);
const VersionChecker = require('ember-cli-version-checker');
const checker = new VersionChecker(this);

return checker.for('ember-cli', 'npm');
},

_getEmberVersion: function() {
var VersionChecker = require('ember-cli-version-checker');
var checker = new VersionChecker(this);
var emberVersionChecker = checker.for('ember-source', 'npm');
const VersionChecker = require('ember-cli-version-checker');
const checker = new VersionChecker(this);
const emberVersionChecker = checker.for('ember-source', 'npm');

if (emberVersionChecker.version) {
return emberVersionChecker;
Expand Down
Loading