Skip to content

Instantly share code, notes, and snippets.

@tomdale
Created September 21, 2016 18:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomdale/537f7cd99ddbb88ddd776378cfea3da9 to your computer and use it in GitHub Desktop.
Save tomdale/537f7cd99ddbb88ddd776378cfea3da9 to your computer and use it in GitHub Desktop.
WIP Targets RFC

Targets RFC

  • Start Date: (fill me in with today's date, YYYY-MM-DD)
  • RFC PR: (leave this empty)
  • Ember Issue: (leave this empty)

Summary

Gives Ember developers and addon authors the ability to build an Ember app for targets in addition to the browser.

Motivation

Currently, the Ember CLI build infrastructure is hard-coded towards building an Ember.js application that runs inside a browser. As the ecosystem has grown, however, we have seen addons that adapt Ember apps to run in different environments. Two examples of this are ember-electron, which targets native apps running in an Electron wrapper, and ember-cli-fastboot, which builds apps that run inside a Node.js sandbox.

If adopted, this RFC would provide a common vocabulary used to describe these various build targets. While the browser will remain the default target, adding the idea of a build target to Ember CLI will allow for addons that bring Ember to different environments to work without resorting to hacks and multiple builds.

Detailed design

This is the bulk of the RFC. Explain the design in enough detail for somebody familiar with the framework to understand, and for somebody familiar with the implementation to implement. This should get into specifics and corner-cases, and include examples of how the feature is used. Any new terminology should be defined here.

How We Teach This

What names and terminology work best for these concepts and why? How is this idea best presented? As a continuation of existing Ember patterns, or as a wholly new one?

Would the acceptance of this proposal mean the Ember guides must be re-organized or altered? Does it change how Ember is taught to new users at any level?

How should this feature be introduced and taught to existing Ember users?

Drawbacks

Why should we not do this? Please consider the impact on teaching Ember, on the integration of this feature with other existing and planned features, on the impact of the API churn on existing apps, etc.

There are tradeoffs to choosing any path, please attempt to identify them here.

Alternatives

What other designs have been considered? What is the impact of not doing this?

Unresolved questions

Optional, but suggested for first drafts. What parts of the design are still TBD?


Direction of what we need

ember build -prod --target=fastboot

app.import('some-lib.js') //all

app.import('other.js', { targets: ['browser', 'fasboot'] })

  • config injection prevents us from a single app.js (currently)

  • FastBoot build -> Do Browser build then do a second fastboot build that disables browser only modules and adds fastboot modules: Append only operation

    • Is this harder to debug because we have code that is disabled later?
  • FastBoot build file size is less importand than browser file size

  • ConcatFiles

  • use ember-cli-css as inspiration

  • fastboot requires the asset map from the browser build

    • Use DAG and link targets?
    • Other ways?
  • Need to deal with the fact that each target will have different options

    • Would be annoying to keep options in the command line (.embercli)
  • Need an API to declare a new target (which is a brocolli tree)

    • If our target depends on another, the dependent tree is run first and passed into our target
  • File System

    • Browser build remains in dist/ for compatibility
    • Other targets go in builds/ - builds/browser - builds/fastboot - builds/electron
let target = new FastBootTarget({
  build(dependencyTrees) {
  }
});

this.registerTarget('fastboot', target, {
  dependencies: ['browser']
});

let browserTarget = app.getTarget('browser');
browserTarget.addPreconcatFilter(tree => {
  return brew.filter(tree, 'initializers/fastboot/**.js');
});

var flattenedTargets = [...];
var targets = {};
var trees = [];
flattenedTargets.forEach(t => {
  var tree = target.build(buildDependencies(target));
  tree = stew.mv(tree, `${t.name}`);
  trees.push(tree);
});

this.builder = new broccoli.Builder(mergeTrees(trees));

First step: --target=browser skips the default broccoli builder, uses the builder class we provide that replicates the current process

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment