├── 0000-template.md ├── CODE_OF_CONDUCT.md ├── README.md ├── active ├── .gitkeep ├── 0003-ember-doctor.md ├── 0023-command-line-completion.md ├── 0046-improved-release-process.md ├── 0050-production-code-stripping.md ├── 0051-packaging.md ├── 0086-firefox-in-ci.md ├── 0105-addons-optionalDependencies.md ├── 0108-add-custom-transform.md ├── 0114-add-template-lint-addon.md ├── 0116-qunit-dom.md ├── 0120-cli-guides.md └── 0121-remove-ember-cli-eslint.md └── complete ├── 0012-help-json-output.md ├── 0020-sri-default.md ├── 0028-app-import-output-file.md ├── 0029-addon-black-and-whitelist-for-apps.md ├── 0055-anonymous-amd.md ├── 0080-serve-file-api.md ├── 0090-addon-tree-caching.md ├── 0091-addon-instrumentation-experimental-hooks.md ├── 0092-blueprint-remove-old-files.md ├── 0095-standardise-targets.md └── 0096-enable-yarn-usage.md /0000-template.md: -------------------------------------------------------------------------------- 1 | - Start Date: (fill me in with today's date, YYYY-MM-DD) 2 | - RFC PR: (leave this empty) 3 | 4 | # Summary 5 | 6 | One paragraph explanation of the feature. 7 | 8 | # Motivation 9 | 10 | Why are we doing this? What use cases does it support? What is the expected 11 | outcome? 12 | 13 | # Detailed design 14 | 15 | This is the bulk of the RFC. Explain the design in enough detail for somebody 16 | familiar with the tool to understand, and for somebody familiar with the 17 | implementation to implement. This should get into specifics and corner-cases, 18 | and include examples of how the feature is used. Any new terminology should be 19 | defined here. 20 | 21 | # How We Teach This 22 | 23 | What names and terminology work best for these concepts and why? How is this 24 | idea best presented? As a continuation of existing Ember CLI patterns, or as a 25 | wholly new one? 26 | 27 | Would the acceptance of this proposal mean the Ember guides must be 28 | re-organized or altered? Does it change how Ember is taught to new users 29 | at any level? 30 | 31 | How should this feature be introduced and taught to existing Ember 32 | users? 33 | 34 | # Drawbacks 35 | 36 | Why should we *not* do this? Please consider the impact on teaching Ember, 37 | on the integration of this feature with other existing and planned features, 38 | on the impact of the API churn on existing apps, etc. 39 | 40 | There are tradeoffs to choosing any path, please attempt to identify them here. 41 | 42 | # Alternatives 43 | 44 | What other designs have been considered? What is the impact of not doing this? 45 | 46 | # Unresolved questions 47 | 48 | Optional, but suggested for first drafts. What parts of the design are still 49 | TBD? 50 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | The Ember team and community are committed to everyone having a safe and inclusive experience. 2 | 3 | **Our Community Guidelines / Code of Conduct can be found here**: 4 | 5 | http://emberjs.com/guidelines/ 6 | 7 | For a history of updates, see the page history here: 8 | 9 | https://github.com/emberjs/website/commits/master/source/guidelines.html.erb 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :boom: Ember CLI RFCs should now be submitted through the [Ember RFCs repo](https://github.com/emberjs/rfcs) 2 | 3 | This repo is archived. The Ember CLI RFC process has merged into [`emberjs/rfcs`](https://github.com/emberjs/rfcs). To read more about the move, see [Ember RFC #300](https://github.com/emberjs/rfcs/blob/master/text/0300-rfc-process-update.md). 4 | -------------------------------------------------------------------------------- /active/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ember-cli/rfcs/301d2608605258f19111033d75db926c9e406feb/active/.gitkeep -------------------------------------------------------------------------------- /active/0003-ember-doctor.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2015-01-10 2 | - RFC PR: [#3](https://github.com/ember-cli/rfcs/pull/3) 3 | 4 | # Summary 5 | 6 | We need a way to run diagnostics on Ember CLI based projects to let developers know about potential system level incompatibilities. Developers should also be able to get a bill of health for their project for things like outdated dependencies. This bill of health should also be extensible. Output from running this command should be as consise and only ever log things that don't seem healthy. 7 | 8 | # Motivation 9 | 10 | The motivation behind this is 2 pronged: 11 | 12 | 1. Allows developers to submit system level information in pull requests, so that bugs can be filed and potentially replicated. 13 | 2. Gives developers the ability to know about the health of their project and to potentially help with stagnation. 14 | 15 | # Detailed design 16 | 17 | The design for this is rather simple. We would first introduce a command called `ember doctor` that would run some default checks. The default checks would do the following: 18 | 19 | - Run `ember v --verbose` and complain loudly for incompatible versions 20 | - Run `npm outdated --depth 0` to check on outdated modules 21 | - Run `bower list` and display out of date bower components 22 | - Run check to grab OS information 23 | 24 | These are what is considered default `checks`. 25 | 26 | In your project developers can setup their own Doctor `checks` that get merged in with the default checks. To allow for this Ember CLI will have `ember generate doctor check:service-health`. 27 | 28 | This command will generate the following directory structure in the root of the project: 29 | 30 | ``` 31 | doctor/ 32 | checks/ 33 | service-health.js 34 | index.js 35 | ``` 36 | 37 | When `ember doctor` is ran we simply will do a merge of the default checks and the ones provided by the application. 38 | 39 | There should also be a way of excluding checks to be ran. Developers should be able to simply pass flags for things they do not care to run e.g. `ember doctor --skip=npm,os`. 40 | 41 | # Addon Design 42 | Much like the project addons can add their own diagnostics as projects. 43 | In the addons main entry point there will be a hook much like 44 | `includedCommands` that allows Ember CLI to look up the diagnostics and 45 | role them into the consuming project. 46 | 47 | ``` 48 | var checks = require('./checks'); 49 | ... 50 | includedChecks: function() { 51 | return checks; 52 | } 53 | ... 54 | ``` 55 | 56 | # Expected Output 57 | Output of running the doctor command should be as concise as possible. 58 | Unless there are any issues with the project that is being analyzed, the 59 | output should be something like the following: 60 | 61 | ``` 62 | Success: All diagnostics checked out fine. 63 | ``` 64 | 65 | In the event that there is an issue with the project that is being 66 | analyzed the output will look something like the following: 67 | 68 | ``` 69 | Warning: NPM modules out of date. Below are the out of date modules. 70 | ╔══════╤═══════╤═════════╗ 71 | ║ Name │ Yours │ Current ║ 72 | ╟──────┼───────┼─────────╢ 73 | ║ glob │ 1.1.2 │ 1.2.3 ║ 74 | ╚══════╧═══════╧═════════╝ 75 | ``` 76 | 77 | # Drawbacks 78 | 79 | This adds "yet another thing" to the Ember CLI API surface. Doctor will be bound to a network connection such as checking outdated dependencies. 80 | 81 | # Alternatives 82 | 83 | There have been other other attempts to put checking for system level checking in various places. The BDFL's would like to consolidate this into an `ember doctor` command. 84 | 85 | # Unresolved questions 86 | -------------------------------------------------------------------------------- /active/0023-command-line-completion.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2015-08-18 2 | - RFC PR: [#23](https://github.com/ember-cli/rfcs/pull/23) 3 | 4 | # Summary 5 | 6 | Adds command line completion *(tab completion)* to ember-cli that fills in partially typed commands by the user and suggests available sub commands or options. *(from now on i will refer to "strings in the command line" as "cli-commands" and "generate" and "new" as unprefixed "commands")* 7 | 8 | ![](http://zippy.gfycat.com/PrestigiousLoneHalicore.gif) 9 | 10 | # Motivation 11 | 12 | With all the already existing commands and especially all blueprints, plus the fact that any addon can add even more blueprints to your tool kit, users can get overwhelmed. Currently, when you want to execute a specific task and you don't quite know the correct cli-command you have to invoke `ember help` which is noisy and slow *( especially when you just want to know the spelling of a specific thing)*. This feature will enable the user to choose from all existing cli-commands by pressing __[tab]__ or just to let ember-cli fill partially typed cli-commands for speed. 13 | 14 | # Detailed design 15 | 16 | The two main components of that feature are a __completion function__ that is responsible for the actual tab-completion, and a __generation function__ that will write the cli-command hierarchy together with metadata into a JSON file for fast processing. 17 | 18 | ## completion function 19 | 20 | To enable this feature, a __completion function__ will run at the main entry point of the process *(making use of [omelette](https://github.com/f/omelettev) for shell completion)*. On every __[tab]__ it will parse the command line and either completes a partially typed, unambiguous cli-command, or suggests possible cli-commands for the current context. 21 | 22 | The user interface will work as you would expect it from a shell completion: 23 | 24 | - it suggests all commands if none are typed yet 25 | 26 | ``` 27 | $ ember 28 | > addon destroy help install serve version 29 | build generate init new test 30 | ``` 31 | - it completes partially typed commands 32 | 33 | ``` 34 | $ ember gen 35 | $ ember generate 36 | ``` 37 | - it completes to suggests commands based on user input (note how it __should__ understand aliases) 38 | 39 | ``` 40 | $ ember g ad 41 | > adapter adapter-test addon 42 | ``` 43 | - it, by default, will not suggest options 44 | 45 | ``` 46 | $ ember g resource 47 | ``` 48 | - it will suggest options on demand (note how it __should__ know when an option needs a value) 49 | 50 | ``` 51 | $ ember g resource post -- 52 | --dry-run --in-repo-addon= --verbose 53 | --dummy --pod 54 | ``` 55 | 56 | ## generation function 57 | 58 | For a good user experience we don't want to figure out those suggestions on runtime or the completion feature would not be substantially faster then the `ember help` command. So there will be a __generation function__ that generates a JSON file once after ember-cli is installed and then during every `ember install some-addon` command to ensure that blueprints added by new addons are recognized aswell. 59 | 60 | Here an example snippet of a cli-command with one cli-subcommand: 61 | ``` 62 | ... 63 | { 64 | "name": "command-name", 65 | "aliases": [ 66 | "cn", 67 | "c" 68 | ], 69 | "options": [ 70 | ], 71 | "commands": [ 72 | { 73 | "name": "some-subcommand", 74 | "aliases": [ 75 | ], 76 | "options": [ 77 | { 78 | "name": "pods", 79 | "type": "boolean" 80 | } 81 | ], 82 | "commands": [ 83 | ] 84 | } 85 | ] 86 | } 87 | ... 88 | ``` 89 | The __generation function__ will, as a first step, iterate over all commands and reads the following properties: 90 | - __name:__ a string, the autocompletion function will suggest 91 | - __aliases:__ this is what the autocompletion function will accept in the cli-command chain 92 | - __availableOptions:__ an array of options that need to have a `name` and a `type` property those will be accumulated for every cli-command in the cli-command chain and suggested on `some-command --` 93 | - __cliCommands:__ can either be an array or a function that returns an array of objects that themselfs will be parsed for the properties in this list those cli-commands will be accepted as subcommands of the current cli-command. 94 | - __skipHelp:__ whenever this property is set to true, the cli-command will also not be suggested by the autocompletion 95 | 96 | Whenever an object does not have one of the above properties, a reasonable default is chosen (except for `name`. If it has no name, it will not be shown at all). This way it is easy to extend that feature in the future to handle arbitrary nested cli-commands. 97 | 98 | # Alternatives 99 | 100 | - Currently the __completion function__ will just expect certain properties to be on a cli-command, this way most commands and blueprints work out of the box but maybe some architectual pattern, like a cli-command mixin or the like would be more robust and obvious. 101 | - Someone with more experience with ember-cli could have an idea of how to generate all cli-commands fast enough at runtime. So that we would not need to store the data in a JSON file. 102 | 103 | # Unresolved questions 104 | 105 | Currently the autocompletion will figure out your default shell and configures it to allow tab-completion for ember. However on __first-time usage__ you would need to resource your config file (or close and open your terminal) and I haven't figured out how to do this programmatically. 106 | -------------------------------------------------------------------------------- /active/0046-improved-release-process.md: -------------------------------------------------------------------------------- 1 | # Improved Release Process 2 | 3 | - Start Date: 2016-03-26 4 | - RFC PR: #46 5 | 6 | ## Summary & Motivation 7 | 8 | ember-cli has followed an ad hoc release process throughout its existence which has made it difficult to know exactly when releases would come out, what features would and would not be supported, and the degree to which it would support existing Ember applications. With the proposal for lockstep SemVer there were ideals of guaranteeing compatibility, which we have mostly met, but that resulted in making decisions of delaying an official 2.X release of ember-cli to avoid additional major version bumps. 9 | 10 | We propose that we adopt a pattern similar to Ember itself in order to align with the expectations of the Ember community, more-clearly communicate around our release lifecycle, and provide rigor around our support structure. Anything which is not specifically called out as a difference in this document is inferred to be following the patterns specified by Ember itself. 11 | 12 | ## Channel Design 13 | 14 | To begin there will be three separate channels: canary, beta, and release. We intend to investigate an LTS channel after this process has matured. 15 | 16 | - **Canary**: represents the latest work in ember-cli, and is synonymous with the `HEAD` of the `master` branch and is the least stable of all channels. 17 | - **Beta**: branched off of master every six weeks, exact commit decided upon manually. Updated and released weekly with commits that are prefixed `[BUGFIX beta]`. Less stable than `release` as it is a proving ground. No new features will be added once the branch has been created to allow for existing features to mature. Tags will match Ember's patterns, for example `v2.6.0-beta.1`. Branch name: `beta`. 18 | - **Release**: branched off of Beta every six weeks. Only rarely will this be updated, but possible for security issues and uncaught regressions. Branch name: `release`. 19 | 20 | ember-cli will not support daily releases as time-based packaging doesn't make a lot of sense. 21 | 22 | ## New Features 23 | 24 | New features to ember-cli must be protected by feature flags. Incomplete and WIP features will be available in the Canary channel, but will not be available in the Beta or release channels. 25 | 26 | ## Tooling Design 27 | 28 | We must create additional tooling and patterns in order to make this efficient. Since ember-cli successfully installs and works from npm without modification we don't need to bundle and publish an asset for each Canary build. We'll publish tags to npm for `beta` and `release` channel releases so that they're not tied to a git remote URL. The `latest` tag for npm (the default when installing via `npm install -g ember-cli`) will track our `release` channel at all times. We will publish tagged releases (i.e. v2.6.0-beta.1) to the npm `beta` tag which is used via `npm install --save-dev ember-cli@beta`. 29 | 30 | ## Timeline 31 | 32 | Since the ember-cli project is presently designed to track Ember development, we'll run our release schedule on a one week delay from Ember itself. This ensures that we're able to incorporate the latest changes from Ember into ember-cli and gives us a week to check for Ember-introduced regressions. As Ember itself becomes an npm module this will become less of a concern and we can diverge on our release schedule as best suits the ember-cli project. We will ship the last beta coincidentally with the newest Ember release. 33 | 34 | ## Drawbacks 35 | 36 | The largest drawback is also a feature: we require more rigor in our release processes. This process presently requires a weekly manual review of new commits to master and their prefixes which then get cherry-picked to the appropriate `release` and `beta` branches. 37 | 38 | We've also encountered issues with `npm` in the past which may require investigation into other tools. 39 | 40 | ## Effort 41 | 42 | In order to undertake this task, there are multiple workflows which must occur: 43 | 44 | - [ ] Updates to the website and documentation communicating this plan. 45 | - [ ] Teaching new patterns to ember-cli contributors, most specifically commit tagging and feature flagging. 46 | - [ ] Increased automation of the release process. 47 | - [ ] Tooling to support feature flags. 48 | 49 | ## References 50 | 51 | - [Ember's Post-1.0 Release Cycle](http://emberjs.com/blog/2013/09/06/new-ember-release-process.html) 52 | - [Ember RFC #56 - Improved Release Cycle](https://github.com/emberjs/rfcs/blob/master/text/0056-improved-release-cycle.md) 53 | - [Announcing Ember's First LTS Release](http://emberjs.com/blog/2016/02/25/announcing-embers-first-lts.html) 54 | - [ember-cli Release Instructions](https://github.com/ember-cli/ember-cli/blob/master/RELEASE.md) 55 | -------------------------------------------------------------------------------- /active/0050-production-code-stripping.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-04-06 2 | - RFC PR: [#50](https://github.com/ember-cli/rfcs/pull/50) 3 | 4 | # Summary 5 | 6 | A number of Ember framework function calls are no-ops in production. Ember CLI should strip these no-op function invocations from production builds by default. 7 | 8 | # Motivation 9 | 10 | Removing code that isn't required in production results in smaller and faster applications. 11 | 12 | # Detailed design 13 | 14 | The following framework function calls will be removed from ember-cli production builds by default: 15 | 16 | * [`Ember.assert`](http://emberjs.com/api/#method_assert) 17 | * [`Ember.debug`](http://emberjs.com/api/#method_debug) 18 | * [`Ember.deprecate`](http://emberjs.com/api/#method_deprecate) 19 | * [`Ember.info`](http://emberjs.com/api/#method_info) 20 | * [`Ember.runInDebug`](http://emberjs.com/api/#method_runInDebug) 21 | * [`Ember.warn`](http://emberjs.com/api/#method_warn) 22 | 23 | The API documentation will be updated where necessary to indicate that these function calls will be stripped from production builds. 24 | 25 | A babel plugin will execute the removal of these function calls based on provided configuration. The plugin will affect the code of the current app or addon only and won't affect code in child or grandchild addons. As this change becomes part of the default ember-cli configuration, addons will adopt the code stripping as they upgrade to newer ember-cli versions. 26 | 27 | The plugin configuration will define an array of modules or global functions to remove. Here's an example of what this configuration might look like: 28 | 29 | ```js 30 | { 31 | removals: [ 32 | { 33 | module: 'ember', //eg. import Em from 'ember'; 34 | paths: [ 35 | 'assert', //Em.assert will be removed 36 | 'debug', //Em.debug will be removed 37 | 'a.b.c' //Em.a.b.c will be removed 38 | ] 39 | }, { 40 | global: 'Ember', 41 | paths: [ 42 | 'deprecate' //Ember.deprecate will be removed 43 | ] 44 | }, { 45 | paths: [ 46 | 'console.log' //console.log will be removed 47 | ] 48 | } 49 | ] 50 | } 51 | ``` 52 | 53 | The plugin will support removal of destructured and reassigned invocations of these functions and will support both Babel 5 and 6. 54 | 55 | An app or addon can disable the code removal by removing the babel plugin. 56 | 57 | # How We Teach This 58 | 59 | This change doesn't bring any new functionality. Other than updating the Ember API docs, we don't need to make guide or other documentation changes. At the time of releasing, we may want to point out the possible side effects in a release blog post (see the _Drawbacks_ section below). 60 | 61 | If we want to expose the configuration options so that application authors can customize the settings, we can include a new section in the Ember CLI docs. 62 | 63 | # Drawbacks 64 | 65 | This may introduce an unexpected change in production builds as arguments that have side effects will no longer be executed. For example: 66 | 67 | ```js 68 | Ember.assert('Some assertion', someSideEffect()); 69 | ``` 70 | 71 | Currently, the `someSideEffect` function will be executed in production. When this RFC lands, it won't. 72 | 73 | # Alternatives 74 | 75 | An Ember addon could provide opt-in function stripping for applications that want it. If this RFC isn't deemed a good default for Ember CLI, that option should be explored. 76 | -------------------------------------------------------------------------------- /active/0051-packaging.md: -------------------------------------------------------------------------------- 1 | + Start Date: 2017-09-07 2 | + RFC PR: (leave this empty) 3 | 4 | # Summary 5 | 6 | The goal of this RFC is to solidify the next version of the mechanism that 7 | `ember-cli` uses to build final assets. It will allow for a more flexible build 8 | pipeline for Ember applications. It also unlocks building experimental features 9 | on top. It is a backward compatible change. 10 | 11 | # Motivation 12 | 13 | The [Packager 14 | RFC](https://github.com/chadhietala/rfcs/blob/packager/active/0002-packager.md) 15 | submitted by [Chad Hietala](https://github.com/chadhietala) is a little over 2 16 | years old. A lot of things have changed since then and it requires a revision. 17 | 18 | The current application build process merges and concatenates input broccoli 19 | trees. This behaviour is not well documented and is a tribal knowledge. While 20 | the simplicity of this approach is nice, it doesn't allow for extension. We can 21 | refactor our build process and provide more flexibility when desired. 22 | 23 | Most importantly, the approach described below helps us achieve: 24 | 25 | + defining and developing a common language around the subject 26 | + removing highly coupled code and streamline technical implementation (Ember 27 | Engines and Fastboot) 28 | + unlock a whole different set of plugins we couldn't have before: 29 | + ability to create custom bundles (i.e per-engine and per-route bundles) 30 | + take advantage of [HTTP2 31 | multiplexing](https://http2.github.io/faq/#why-is-http2-multiplexed) and 32 | [cache 33 | pushing](https://www.mnot.net/blog/2014/01/30/http2_expectations#4-cache-pushing) 34 | + optimising plugins (JavaScript and CSS tree-shaking) 35 | 36 | # Scope 37 | 38 | + New public API for customising build process and giving more granular control over 39 | the final build output 40 | 41 | # Terminology 42 | 43 | + **Packaging** - The process of designing, evaluating, and producing final build assets. 44 | 45 | # Detailed design 46 | 47 | The detailed design is separated in various sections so that it is easier for a 48 | reader to understand. 49 | 50 | ## Packaging 51 | 52 | It gives you granular control over the final build output. It could be used in many 53 | different ways (we are going to go over use cases below). Note, it isn't meant to be 54 | used for "postprocess" transformations; "postprocess" is called after packaging is 55 | finished. 56 | 57 | Currently, Ember.js application and all of its depedencies get assembled under one 58 | directory with the following structure: 59 | 60 | ```ruby 61 | bundler:js:input/ 62 | ├── addon-tree-output/ 63 | ├── the-app-name-folder/ 64 | ├── node_modules/ 65 | └── vendor/ 66 | ``` 67 | 68 | where: 69 | 70 | + `addon-tree-output` is a folder that contains dependencies from Ember add-ons. 71 | + `the-app-name-folder` is a folder that contains Ember application code. 72 | + `node_modules` is a folder that contains node dependencies. 73 | + `tests` is a folder that contains test code. 74 | + `vendor` is a folder that contains other dependencies. 75 | 76 | Note, for clarity purposes we should rename `addon-tree-output` to `addon-modules` as 77 | both `tree` and `output` don't communicate well about the contents of the folder. 78 | 79 | During packaging process the final output will be generated (everything that currently 80 | resides under `dist/` folder when a developer runs `ember build`). 81 | 82 | ### `package` API 83 | 84 | A new public `package` method will be introduced to open up a way to customise packaging process: 85 | 86 | ```javascript 87 | // ember-cli-build.js 88 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 89 | 90 | module.exports = function(defaults) { 91 | const app = new EmberApp(defaults, { 92 | package(inputTree) { 93 | // customise `inputTree` 94 | // and return customised `inputTree` 95 | } 96 | }); 97 | 98 | return app.toTree(); 99 | } 100 | ``` 101 | 102 | `package` function has the following signature: 103 | 104 | ```typescript 105 | interface EmberApp { 106 | package(inputTree: BroccoliTree): BroccoliTree; 107 | } 108 | ``` 109 | 110 | where `inputTree` will have the following structure: 111 | 112 | ```ruby 113 | bundler:js:input/ 114 | ├── addon-modules/ 115 | ├── the-app-name-folder/ 116 | ├── node_modules/ 117 | ├── tests/ 118 | └── vendor/ 119 | ``` 120 | 121 | Note, that `package` method must return a broccoli tree. 122 | 123 | This change should be behind an experiment flag, `PACKAGING`. 124 | This will allow us to start experimenting right away and not being 125 | tied to a particular release cycle. 126 | 127 | Note, that `package` is optional. If you don't define it, you're 128 | effectively "opting out" of the feature and using the default 129 | behaviour. 130 | 131 | ### `defaultPackager` API 132 | 133 | It's important to make it easy for users to still use default Ember CLI 134 | packaging. 135 | 136 | `defaultPackager` is a way for the users to access out-of-the-box packaging while 137 | still be able to customise the final build output. 138 | 139 | ```javascript 140 | // ember-cli-build.js 141 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 142 | const defaultPackager = require('ember-cli-default-packager'); 143 | 144 | module.exports = function(defaults) { 145 | const app = new EmberApp(defaults, { 146 | package(inputTree) { 147 | // customise `inputTree` 148 | 149 | return defaultPackager(app, inputTree); 150 | } 151 | }); 152 | 153 | return app.toTree(); 154 | } 155 | ``` 156 | 157 | `defaultPackager` has the following signature: 158 | 159 | ```typescript 160 | function defaultPackager(app: EmberApp, inputTree: BroccoliTreel): BroccoliTree; 161 | ``` 162 | 163 | `defaultPackager` must return a `BroccoliTree`. 164 | 165 | ### Possible usages 166 | 167 | #### Debug/Analyse 168 | 169 | One of the applications of `package` API would be to run different analysis on the 170 | Ember applications. Take 171 | [broccoli-concat-analyser](https://github.com/stefanpenner/broccoli-concat-analyser), 172 | for example. This could be easily incorporated into the build. 173 | 174 | ```javascript 175 | // ember-cli-build.js 176 | const EmberApp = require('ember-cli/lib/broccoli/ember-app'); 177 | const defaultPackager = require('ember-cli-default-packager'); 178 | 179 | module.exports = function(defaults) { 180 | const app = new EmberApp(defaults, { }); 181 | 182 | app.package = function(inputTree) { 183 | const analysedTree = new BroccoliConcatAnalyser(inputTree); 184 | 185 | return defaultPackager(app, analysedTree); 186 | } 187 | 188 | return app.toTree(); 189 | } 190 | ``` 191 | 192 | #### Static Assets Split 193 | 194 | One of the techniques for improving site speed is isolating changes throughout 195 | application deployments. Assuming the application assets are uploaded to CDN, 196 | the reasoning is very simple: if `ember.js` or `jQuery` (possibly along with 197 | other third party libraries) don't change with every deployment, why bust CDN 198 | cache for them? 199 | 200 | #### ES6 Modules 201 | 202 | ES6 modules are [starting](https://caniuse.com/#feat=es6-module) to land in browsers. 203 | This means that you can use ``. 204 | 205 | This [article](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/) [explains](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/#is-this-really-worth-the-extra-effort) the benefits of using ES6 modules over ES2015 (smaller total file sizes, faster to parse and evaluate). 206 | 207 | `package` API will make it possible to package your application for both ES2015 only browsers as well 208 | the ones with ES6 modules support. 209 | 210 | # Topics for Future RFCs 211 | 212 | While working on this RFC, some ideas were brought into focus regarding existing 213 | and new features in Ember CLI. They all likely require separate discussions in 214 | future RFCs, but the discussion points have been included below. 215 | 216 | ## Tree-shaking 217 | 218 | Firstly, what's _tree-shaking_? AFAIK, the term 219 | [originated](https://groups.google.com/forum/#!msg/comp.lang.lisp/6zpZsWFFW18/-z_8hHRAIf4J) 220 | in Lisp. The gist of the idea is "how about we start using _only_ the code that 221 | we actually need?" 222 | 223 | Secondly, how is it different from [Dead Code 224 | Elimination](https://en.wikipedia.org/wiki/Dead_code_elimination)? [Rich 225 | Harris](https://twitter.com/Rich_Harris) 226 | [offers](https://medium.com/@Rich_Harris/tree-shaking-versus-dead-code-elimination-d3765df85c80) 227 | a pretty good explanation in the context of [Rollup](https://rollupjs.org/). The 228 | gist is dead code elimination happens on a final product by removing bits that 229 | are unused. Tree-shaking is quite different - given an object we want to construct, what is the exact set of dependencies we need?. 230 | 231 | With this RFC, we lay out the foundation and create a framework by which both 232 | dead code elimination and tree-shaking code be implemented. 233 | 234 | However, there are still several things that are missing: 235 | 236 | + **Linker** - Responsible for resolving and reducing the graph to a tree 237 | containing only reachable modules. 238 | + **File System Resolver** - Responsible for connecting a module name with a 239 | file path. 240 | 241 | `Linker` would be responsible for: 242 | 243 | + building a minimal dependency graph as well as check for redundant edges in 244 | the graph (more on the topic, [Transitive reduction of a directed 245 | graph](https://en.wikipedia.org/wiki/Transitive_reduction#Graph_algorithms_for_transitive_reduction)); 246 | + producing an application tree with only used modules 247 | 248 | Dependency graph represents dependencies using module names, there is a need to 249 | be able to convert module name to file path. This is where `File System 250 | Resolver` comes in. Here's couple of examples: 251 | 252 | ```javascript 253 | fileSystemResolver.resolve('lodash') => `some-path/node_modules/lodash/lodash.js` 254 | fileSystemResolver.resolve('ember-ajax') => `some-path/addon-modules/ember-ajax/index.js` 255 | fileSystemResolver.resolve('ember-data') => `some-path/addon-modules/modules/ember-data/index.js` 256 | fileSystemResolver.resolve('ember-data/-private') => `some-path/addon-modules/modules/-private.js` 257 | ``` 258 | 259 | This effort could be broken down into several phases: 260 | 261 | + dead modules elimination inside of the `addons/` (application would be the 262 | main entry point and unused modules are removed only from `addons/`) 263 | + dead modules elimination inside of the `app/` 264 | + removing unused components and helpers (requires analysing templates) 265 | + removing unused initializers/services (this likely entails work on 266 | dependency injection layer as we would need access to a resolver resolution 267 | map) 268 | + tree-shaking (Rollup-like tree-shaking where we include *only* the code that is 269 | used) 270 | 271 | `Linker` would be able to take an `exclude` list of modules as a parameter. 272 | Although, valuable in some situations, it should be clearly marked as advanced 273 | API. It should be used as a last resort and serve as an "escape hatch". 274 | 275 | It would make sense to implement `Linker` as a strategy. Developers would be 276 | able to "opt in"/"opt out" of optimising behaviour. 277 | 278 | ## Deprecating `app.import` API 279 | 280 | Ember applications which choose to use `Linker` strategy should be able to 281 | remove usages of `app.import`. 282 | 283 | ## Tools 284 | 285 | With growing complexity of Ember applications, it is crucial to provide more 286 | insights into final assets. 287 | 288 | Main goals are: 289 | 290 | - report raw/uglified/compressed asset sizes; 291 | [broccoli-concat-analyser](https://github.com/stefanpenner/broccoli-concat-analyser) 292 | - find source code duplication across your javascript assets (enables you to 293 | fine tune code splitting parameters to reduce bundle invalidation rates as 294 | well as improve repeat page load performance) 295 | 296 | # How We Teach This 297 | 298 | This is a backward compatible change to the existing Ember CLI ecosystem. In 299 | order to teach users how to use `package` API, we need to update the API docs 300 | with a section for this and the best practices of when to use this. A more 301 | general purpose blog post could be beneficial as well. 302 | 303 | # Drawbacks 304 | 305 | There are several potential drawbacks that are worth noting. 306 | 307 | _Build performance_. There is minimal overhead in instantiating strategies and 308 | calling methods on them and I believe this approach shouldn't degrade build 309 | performance. 310 | 311 | _A note on add-ons_. Add-ons don't rely on the way Ember CLI does bundling. That 312 | means existing build system continues to work as expected and add-ons won't have 313 | to change their implementation. 314 | 315 | # Alternatives 316 | 317 | This RFC allows us to customise packaging when needed. 318 | [Webpack](https://webpack.js.org) has become very popular in solving this 319 | similar problem. One could implement a `package` function that would use Webpack 320 | for packaging. Ultimately, we need something that is aware of how Ember apps are 321 | assembled and how Ember apps utilise dependency injection that takes advantage 322 | of existing tools. The long term plan is to have a dependency graph that is 323 | aware of application structure so can avoid the "wall of configuration" that 324 | other asset packaging systems are susceptible to. 325 | 326 | # Unresolved questions 327 | 328 | + Will it increase build time? 329 | + Should we introduce the same API on add-on level? 330 | 331 | # Thanks 332 | 333 | Many thanks for [@stefanpenner](https://github.com/stefanpenner/), 334 | [@rwjblue](https://github.com/rwjblue/) and 335 | [@chadhietala](https://github.com/chadhietala/) for helping me to drive this 336 | forward. 337 | -------------------------------------------------------------------------------- /active/0086-firefox-in-ci.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-12-04 2 | - RFC PR: https://github.com/ember-cli/rfcs/pull/86 3 | - Ember CLI Issue: 4 | 5 | # Summary 6 | 7 | Replace PhantomJS with Firefox as the default browser for continuous integration testing. 8 | 9 | # Motivation 10 | 11 | We want to provide the best possible out-of-the-box continuous integration testing experience for Ember apps. Today that means shipping with configurations for testem and TravisCI. Those configurations use PhantomJS. 12 | 13 | But PhantomJS is a weird environment. Users must often fix Phantom-specific browser bugs, which is wasted effort since real users never run your app in Phantom. And "how to debug in Phantom" is an entire extra skill people are forced to learn. 14 | 15 | A user-targeted, standards-compliant, modern browser makes a better default choice. Firefox is a good candidate because it's 100% open source, well-supported by Testem on all major operating system, and built-in to TravisCI. Debugging in Firefox has a dramatically nicer learner curve than PhantomJS. 16 | 17 | # Detailed design 18 | 19 | This is a proposed change to the blueprints for new apps and addons. Existing apps and addons would only be affected when they re-run `ember init` as part of an upgrade and choose to take the updated configuration. 20 | 21 | ## Changes in testem.js 22 | 23 | Replace `PhantomJS` with `Firefox`. 24 | 25 | ## Changes in travis.yml 26 | 27 | Add the following new section to start up a virtual display: 28 | 29 | ``` 30 | before_script: 31 | - export DISPLAY=:99; sh -e /etc/init.d/xvfb start; sleep 3 32 | ``` 33 | 34 | # How We Teach This 35 | 36 | In the guides, replace instructions for installing PhantomJS with instructions for installing Firefox. Since Firefox is a consumer-facing browser with widely-understood installers and behavior, this is one less intimidating thing for newbies to learn. 37 | 38 | # Drawbacks 39 | 40 | PhantomJS has two primary benefits over other browsers: being headless and being scriptable. 41 | 42 | ## Headlessness 43 | 44 | Firefox is not headless, so it needs to render to a display. That is why the Travis configuration needs xvfb. 45 | 46 | ## Scriptability 47 | 48 | PhantomJS is scriptable, but we don't rely on that functionality anyway. We want cross-browser test suites, so Phantom's scriptability is not particularly useful. 49 | 50 | # Alternatives 51 | 52 | The default alternative is to do nothing and keep PhantomJS. 53 | 54 | Another alternative would be to pick Chrome, since it is a very popular browser. However, Chrome is not 100% open source, which complicates distribution. It's not built into Travis, and the popular methods of installing it there require users to opt into non-container-based images, which are heavier and slower to boot. 55 | 56 | Chromium is the fully-open-source parts of Chrome, but like PhantomJS it is an odd duck that's not really well-packaged for end users. It's also not installed by default in Travis. 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /active/0105-addons-optionalDependencies.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2017-4-23 2 | - RFC PR: [#105](https://github.com/ember-cli/rfcs/pull/105) 3 | 4 | # Summary 5 | 6 | It should be possible to specify packages/addons in `optionalDependencies` of the `package.json` of an `ember-cli project`, and ember-cli should scan for packages/addons mentioned in optionalDependencies while processing the build so that such packages/addons could also be included into the consuming application. 7 | 8 | The build need not fail asserting "missing dependency" if any of the dependencies specified in optionalDependencies is missing/absent. 9 | 10 | # Motivation 11 | 12 | In general, the current ember-cli build process will scan for the packages specified in the `dependencies` hash and `devDependencies hash` from the downloaded packages in the node_modules folder, discovers and then includes them into the consuming application. The build is designed to fail if any of the packages specified in these two dependencies hash is missing in the `node_modules` folder. But this procedure may not be sufficient for a variety of cases. 13 | 14 | So there could be an option for the developer to specify packages in optionalDependencies and ember-cli can lookup optionalDependencies while processing the build. The Build need not fail if there is any package specified in optionalDependencies is missing, since it is only optional and moreover may only be required for developmental purposes. This way the developer can have more control over the choice of packages he wishes to use for development and skip for production by giving appropriate commands like `npm install --no-optional`, thereby preventing the installation of packages itself rather than blacklisting in `ember-cli-build.js` which suggests preventing the installed addons sepcifed in the `blacklist` array from being included into the consuming application. 15 | 16 | # Detailed design 17 | We can tweak ember-cli addon/package discovery process to lookup for optionalDependencies as well and if the package is missing, we can make ember-cli proceed the build without terminating. 18 | 19 | # How We Teach This 20 | 21 | This functionality can simply be documented in ember-cli guides to teach. 22 | 23 | # Alternatives 24 | 25 | None. 26 | -------------------------------------------------------------------------------- /active/0108-add-custom-transform.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2017-06-18 2 | - RFC PR: https://github.com/ember-cli/rfcs/pull/108 3 | 4 | # Summary 5 | 6 | This RFC proposes to add a new API to allow addons to register a custom transformation. This transformation can then be used by other addons when calling `app.import` with `using` API. 7 | 8 | # Motivation 9 | 10 | Addons or apps may want import browser only compatible libraries using `app.import` via bower or npm. These libraries should not be running in Node. 11 | 12 | When FastBoot was doing two builds (to generate different assets for browser and Node environment), addon or apps often conditionally imported these libraries relying on the value of `process.env.EMBER_CLI_FASTBOOT`. With the new scheme of the build where only additional Node assets are built, this enviornment is no longer exposed. 13 | 14 | In order to expose better semantics to allow apps and addon authors to easily import these libraries without much overhead (see issue [here](https://github.com/ember-fastboot/ember-cli-fastboot/issues/413)), we need to have these libraries wrapped with an FastBoot check. This can be achieved by extending the `using` API of `app.import`. FastBoot addon would like to register a custom transformation that other FastBoot compatible addons may chose to use in a declarative API. 15 | 16 | # Detailed design 17 | 18 | Today, Ember CLI supports transforming anonymous AMD modules imported via `app.import` into named AMD modules: 19 | 20 | ```js 21 | app.import('/path/to/module.js', { 22 | using: [ 23 | { transformation: 'amd', as: 'some-dep' } 24 | ] 25 | }); 26 | ``` 27 | 28 | The `amd` transform is hardcoded in Ember CLI. However, it is not possible for addon authors to provide any additional transformation that other addons can use when importing third-party modules. Addons like, FastBoot would like to provide custom transformation for other addons to use so that they can wrap their third party libraries in Node environments. 29 | 30 | In order to do this, we would like to expose an API that allows addons to register a custom transformation. This API will be an advanced API and will only be used by addons that want to provide custom transformation. Other addons can chose to use that custom transformation using its name. 31 | 32 | The API to register a custom transformation in Ember CLI will be defined in `index.js` of the addon and will be an advanced API: 33 | 34 | ```js 35 | importTransforms() { 36 | return { 37 | 'fastboot-shim': function(tree, options) { 38 | 39 | return stew.map(tree, function(content, relativePath) { 40 | return `if (typeof FastBoot === 'undefined) { ${content} }`; 41 | }); 42 | } 43 | } 44 | } 45 | ``` 46 | 47 | `importTransforms` returns a map of the name of the transform and a callback function that will be run on every module that uses the transform. The callback function takes the `tree` as broccoli tree contain all the files that want to run this transform and `options` map (optional) that contains the additional key value pairs that a consumer transformer provides. The later argument would be used by transformations like `amd` (explained below). 48 | 49 | With this, we also should move the hard coded `amd` transform into an in-repo addon in Ember CLI. This would allow other addons that define their own transformation to also control the order of their transformation (using `before` or `after` hooks of addon initialization). The registeration of `amd` transform would be: 50 | 51 | ```js 52 | importTransforms() { 53 | return { 54 | 'amd': function(tree, options) { 55 | 56 | return stew.map(tree, function(content, relativePath) { 57 | const name = options[relativePath].using; 58 | if (name) { 59 | return [ 60 | '(function(define){\n', 61 | content, 62 | '\n})((function(){ function newDefine(){ var args = Array.prototype.slice.call(arguments); args.unshift("', 63 | name, 64 | '"); return define.apply(null, args); }; newDefine.amd = true; return newDefine; })());', 65 | ].join(''); 66 | } else { 67 | return content; 68 | } 69 | }); 70 | } 71 | } 72 | } 73 | ``` 74 | 75 | As seen above, `options` contains the optional AMD module ID that the consumer of `amd` transform can provide. If registered transforms want to depend on any other user provided values, those can easily be available during the transforms. 76 | 77 | When the addons are initialized, we will check if `importTransforms` is defined and store these callbacks and transform names in an array. 78 | 79 | Now, if addon authors would like to use these transforms when importing libraries, they would simply do the following: 80 | 81 | ```js 82 | app.import('/path/to/module.js', { 83 | using: [ 84 | { transformation: 'fastboot-shim' }, 85 | { transformation: 'amd', as: 'some-dep' } 86 | ] 87 | }); 88 | ``` 89 | 90 | As seen above, an addon author could provide the list of transformations to run and Ember CLI would run them in the order of when the transformations were registered. 91 | Internally, for every transform we will maintain an array of file paths that need to run this transform. When the transformations need to run, we will read the registration order, run the transformation on those files. The output of the transformation will then be merged back and then the next transformation would run. This will ensure that more than one transformation can be correctly applied to a module. 92 | 93 | ## Same name conflict 94 | 95 | Allowing addons to define custom transform could lead to naming conflicts where more than two addons may provide transform functions with the same name but slightly or totally different functionality. Therefore, if more than one addon provides a same name for a transform by default the last addon in the order that registered its transform will win. In addition, we will also warn the users of the name conflicts and which addon's registered transformation is going to run. 96 | 97 | # How We Teach This 98 | 99 | The registeration of transform is an advanced API of Ember CLI that very few addons would use. We will be updating the guides [here](https://ember-cli.com/user-guide/#standard-anonymous-amd-asset). 100 | 101 | # Drawbacks 102 | 103 | The drawback of this approach is that the order of running the transformation is controlled by the addon that provides the transform rather than the addon that uses the transform. The reasoning for this is mainly for performance reasons (in order to not create a funnel per asset path) and to make sure the more than one transform can be applied correctly on an asset path. 104 | 105 | # Alternatives 106 | 107 | Currently the alternative is for addons to import their bower or npm dependency in `vendor` via `treeForVendor` and manually use broccoli plugins to do transformations. The alternative for apps is to create an in-repo addon to do this. 108 | 109 | # Unresolved questions 110 | 111 | N/A 112 | -------------------------------------------------------------------------------- /active/0114-add-template-lint-addon.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2018-01-04 2 | - RFC PR: https://github.com/ember-cli/rfcs/pull/114 3 | 4 | # Summary 5 | 6 | Add https://github.com/rwjblue/ember-cli-template-lint as a default addon for the app and addon blueprints using the recommended rules. 7 | 8 | # Motivation 9 | 10 | Linting and security in templates would help not only individual developers write better apps with better accessibility and security, but would also help teams to be on the same page and stick to a handful of standards. 11 | 12 | # Detailed design 13 | 14 | 1. Move ember-cli-template-lint to the ember-cli org (better for contributing and getting work off one person, @rwjblue) 15 | 2. Add the dependency to the app blueprint here: https://github.com/ember-cli/ember-cli/blob/master/blueprints/app/files/package.json#L19 16 | 3. Also add it to the addon blueprint, like the eslint addon here: https://github.com/ember-cli/ember-cli/blob/master/blueprints/addon/index.js#L66 17 | 18 | # How We Teach This 19 | 20 | The same way that we teach ESLint being on by default. 21 | 22 | # Drawbacks 23 | 24 | - More chatter in the terminal. 25 | - An additional dependency. 26 | - Recommended rules might not be good for everyone.. but that same issue probably exists with ESLint. 27 | 28 | # Alternatives 29 | 30 | Do nothing and have people write sub par template code. 31 | 32 | # Unresolved questions 33 | 34 | None 35 | -------------------------------------------------------------------------------- /active/0116-qunit-dom.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2018-02-12 2 | - RFC PR: #116 3 | 4 | # Summary 5 | 6 | Introduce [`qunit-dom`] as a dependency by default in the `app` and `addon` blueprints. 7 | 8 | [`qunit-dom`]: https://github.com/simplabs/qunit-dom 9 | 10 | # Motivation 11 | 12 | > Why are we doing this? 13 | 14 | In a modern Ember application making assertions around the state of the DOM is 15 | fundamental to confirming your applications functionality. These assertions are 16 | often quite verbose: 17 | 18 | ```js 19 | assert.equal(this.element.querySelector('.title').textContent.trim(), 'Hello World!'); 20 | ``` 21 | 22 | Using the `find()` helper of `@ember/test-helpers` we can simplify the DOM 23 | element lookup, but the signal-to-noise ratio of the code is still not great: 24 | 25 | ```js 26 | assert.equal(find('.title').textContent.trim(), 'Hello World!'); 27 | ``` 28 | 29 | With `qunit-dom` we can write much more readable assertions for DOM elements: 30 | 31 | ```js 32 | assert.dom('.title').hasText('Hello World!'); 33 | ``` 34 | 35 | > What use cases does it support? 36 | 37 | It supports the most common assertions on DOM elements, like: 38 | 39 | - what text does the element have? 40 | - what value does the `` element have? 41 | - is a certain CSS class applied to the element 42 | 43 | The full API is documented at . 44 | 45 | > What is the expected outcome? 46 | 47 | Using `qunit-dom` will lead to more simple and readable test code. 48 | 49 | 50 | # Detailed design 51 | 52 | The necessary changes to `ember-cli` are relatively small since we only need 53 | to add the dependency to the `app` blueprint, and the `addon` blueprint will 54 | inherit it automatically. 55 | 56 | This has the advantage (over including it as an implicit dependency), that 57 | apps and addons that don't want to use it for some reason can opt-out by 58 | removing the dependency from their `package.json` file. 59 | 60 | A WIP pull request has been created already at . 61 | 62 | 63 | # How We Teach This 64 | 65 | > Would the acceptance of this proposal mean the Ember guides must be 66 | > re-organized or altered? Does it change how Ember is taught to new users 67 | > at any level? 68 | 69 | Once we decide that this is the right way to go, we should update the official 70 | Ember.js testing guides to use `qunit-dom` assertions by default. This has the 71 | nice side effect of making the testing code in the guides easier to read too. 72 | 73 | At the same time (same minor release) we should update the relevant blueprints 74 | in the `ember-source` package to use `qunit-dom` by default. This should be a 75 | relatively small change as only the `component` and `helper` tests use 76 | DOM assertions. 77 | 78 | > How should this feature be introduced and taught to existing Ember 79 | > users? 80 | 81 | We should also explicitly mention this change in the release blog post and 82 | recommend that people use this from now on. For those users that want to 83 | migrate their existing tests to `qunit-dom` a basic codemod exists at 84 | . 85 | 86 | 87 | # Drawbacks 88 | 89 | > Why should we *not* do this? Please consider the impact on teaching Ember, 90 | > on the integration of this feature with other existing and planned features, 91 | > on the impact of the API churn on existing apps, etc. 92 | > 93 | > There are tradeoffs to choosing any path, please attempt to identify them here. 94 | 95 | - `qunit-dom` is "owned" by a third-party consulting company (simplabs) and 96 | the Ember CLI team is not directly in control. 97 | 98 | - `qunit-dom` has not reached v1.0.0 yet so there might be small breaking 99 | changes in the future. 100 | 101 | - `qunit-dom` is another abstraction layer on top of the raw QUnit assertions 102 | which adds to the existing learning curve. 103 | 104 | - Adding `qunit-dom` to the default blueprint could make it look even more like 105 | `ember-mocha` is only a second-class citizen. Since we add it to the default 106 | `package.json` file it is easy to opt-out though and can be replaced with 107 | `chai-jquery` or `chai-dom` for a roughly similar API. 108 | 109 | 110 | # Alternatives 111 | 112 | > What other designs have been considered? 113 | 114 | - Using the `find()` helper functions can be considered an alternative, but 115 | as mentioned above they still result in more verbose code than using 116 | `qunit-dom`. Another advantage is that `qunit-dom` generates a useful 117 | assertion description by default, while `assert.equal()` will just show 118 | something like "A does not match B". 119 | 120 | > What is the impact of not doing this? 121 | 122 | We will keep using hard-to-read assertions by default and leave it up to our 123 | users to discover `qunit-dom` by themselves. 124 | 125 | 126 | # Unresolved questions 127 | 128 | - Should the `ember-source` blueprints detect `qunit-dom` usage and fallback 129 | to raw QUnit assertions if the dependency can't be found? 130 | -------------------------------------------------------------------------------- /active/0120-cli-guides.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2018-07-30 2 | - RFC PR: [#120](https://github.com/ember-cli/rfcs/pull/120) 3 | 4 | # Ember CLI Docs 5 | 6 | ## Summary 7 | 8 | This RFC proposes converting the existing [Ember CLI website](https://ember-cli.com/) into an 9 | Ember app, restructuring the table of contents, replacing a significant 10 | portion of the learning material, and inviting community members to participate in writing new content. 11 | 12 | ## Motivation 13 | 14 | The purpose of these changes are to empower new contributors, create a consistent 15 | narrative structure, correct outdated information, and lead new readers through an easier learning progression. 16 | 17 | Ember's public sites are being migrated from Ruby apps to Ember apps 18 | in order to improve maintainability and empower new contributors. The CLI docs 19 | are currently a Jekyll app. Similar migrations have been very successful. 20 | 21 | The rewrite and/or reorganization of content is driven by an audit of the existing 22 | content's relevance and balance. While trying to plan a refactor in place, it became clear that a greenfield approach is more time efficient and will lead to a 23 | better learning experience. A significant portion of the content from the current guides site can be ported over once a new structure is in place. 24 | 25 | ## Detailed design 26 | 27 | This app will have a new table of contents. The architecture will follow the 28 | same patterns successfully used in other apps that have been converted from 29 | Middleman apps to Ember. 30 | 31 | ### Writing process 32 | 33 | Writing new content and porting over existing information is a job that will require the help of many contributors! After this RFC is accepted, a call for contributors will be made. 34 | 35 | Here are some strategies to help contributor work to be successful: 36 | - A quest issue will outline sections that need work so that people can volunteer 37 | - Collaboration will be encouraged so that no one person blocks writing on a particular topic 38 | - Contributing can take multiple forms. For example, developers with some CLI expertise who don't have time/interest for formal writing can share some brief notes or suggestions to help out the writers. Writers don't need to be experts. In some cases, it's better when someone isn't very familiar with the content because they can help identify gaps. 39 | - Each unwritten section will have comments in the markdown indicating which topics to cover. In cases where content has been ported over, comments will indicate which sections to fact-check, clarify, or revise. 40 | - A strike team channel will be created on a chat 41 | - A writing styleguide will be provided for contributors 42 | - Following a verson one release, writing work will be organized via normal GitHub issues. 43 | 44 | Since maintaining consistent voice and structure across a blank slate is a challenge, beta content for the core learning experience has already been drafted, including Basic Use guides and a tutorial for creating an addon from start to finish. 45 | 46 | The beta version of the CLI Guides content can be found at [ember-learn/cli-guides-source](https://github.com/ember-learn/cli-guides-source). The Markdown files there are rendered by [ember-learn/cli-guides-app](https://github.com/ember-learn/cli-guides-source). The app is currently deployed to a temporary endpoint for testing and UX validation. The link is available on the repositories. 47 | 48 | ### User Personas 49 | 50 | The content layout should follow the progression of an Ember developer's 51 | learning experience. There are four main user personas for the 52 | CLI documentation: 53 | 54 | 1. A new or "typical" Ember CLI user - someone whose primary work is 55 | running common commands like `ember serve` and who has a "zero 56 | config" type of experience with Ember 57 | 2. Power users - developers who make their own configurations to the 58 | build pipeline 59 | 3. Beginner addon authors - those who are looking to build simple 60 | shared UI components, methods, or wrappers for existing npm libraries 61 | 4. Advanced addon authors - those who dig into internals to make their 62 | addon work, or who are planning for broad extensibility 63 | 64 | ### Table of Contents 65 | 66 | Applying these User Personas to the CLI content, the following topics layout emerges. "Beginner" topics will include links to later "Advanced" 67 | topics, similar to how the Guides link to the API docs. 68 | 69 | - Introduction 70 | - how to install ember cli 71 | - a very simple, short definition of what it is (the official way to create, build, and test an Ember app) 72 | - Why is the CLI needed 73 | - Guidance on learning path 74 | - How to contribute 75 | - Basic use (explain options of each) 76 | - CLI Commands: Explain how to use the `help` command and common commands like `ember new`, `ember server`, `ember generate`, etc. Each is explained briefly, together with an example usage and a link to the Main Ember Guides with more information about how to use those files. 77 | - How to find and use addons 78 | - How to use npm packages 79 | - Installation and Upgrading the CLI (including a note about upgrading your app, with a link to more resources) 80 | - feature flags & configurations 81 | - Advanced use 82 | - shims 83 | - broccoli 84 | - custom blueprints 85 | - CSS compilation 86 | - Using another testing library 87 | - more on dependencies 88 | - more configurations 89 | - Writing Addons 90 | - Overview 91 | - Tutorial: Creating a standalone addon and an in-repo addon, 92 | - Using the dummy app 93 | - Including assets 94 | - Configuration 95 | - Nested addons 96 | - Testing your addon 97 | - Sharing your addon (deploying) 98 | - API Documentation 99 | - brief description of the target audience and a link 100 | 101 | ### Versioning 102 | 103 | Only one version of the documentation will be deployed and maintained. 104 | The documentation app itself will have clear releases 105 | as major changes are made, so that users working on 106 | older apps can still go back in time if they need to. 107 | 108 | The url will contain `/release/` so that if versioning is needed in the future, 109 | the option is available. 110 | 111 | ### Transition and legacy links 112 | 113 | While the project is in development, it will be worked on as a separate site, and the main site, [https://ember-cli.com](https://ember-cli.com) will remain in place. 114 | 115 | Legacy links should be maintained because deprecating the links would cause SEO problems. Consensus seems to be that the best option is to create individualized redirects from pages within [https://ember-cli.com](https://ember-cli.com) to the new site. 116 | 117 | Upon reaching feature parity, [https://ember-cli.com](https://ember-cli.com) will redirect to the new site. Ultimately, content will be hosted at [https://cli.emberjs.com/](https://cli.emberjs.com/). This improves the SEO of our emberjs domain. 118 | 119 | ### Application architecture 120 | 121 | The application architecture will follow similar patterns as other Middleman 122 | apps that have been successfully turned into Ember apps. Some examples of past conversions are: 123 | 124 | - [Deprecations](https://github.com/ember-learn/deprecation-app) 125 | - [The Guides](https://github.com/ember-learn/guides-app) 126 | - [The API docs](https://github.com/ember-learn/ember-api-docs) 127 | 128 | [Chris Manson](https://github.com/mansona?tab=overview&from=2018-06-01&to=2018-06-30) has a project in development that automates the creation of documentation apps, integrating the lessons learned from these past conversions. Early results are looking great! 129 | 130 | The resulting app will make use of typography and UI assets from 131 | [ember-styleguide](https://github.com/ember-learn/ember-styleguide) 132 | 133 | Although only one version will be deployed/maintained for the forseeable future, the URL structure will allow for future growth, i.e. `https://cli.emberjs.com/release/some-topic` 134 | 135 | ### Maintaining content 136 | 137 | With module unification and tree shaking refactors underway, there may be some big changes to Ember's 138 | file structure. There are a few ways to mitigate this, while still maintaining only one version of these guides: 139 | 140 | 1. Whenever possible, the CLI guides should link to the Ember Guides. The details of file layout and syntax are best handled in a resource that is versioned. 141 | 2. The CLI guides can also frequently give a nod to past configurations/features. A url checker will make sure that these "legacy" resource links still exist. The pace of major version releases is slow enough that this should be sustainable. 142 | 3. As mentioned earlier, the urls for the cli guides will include `/release/` in case future versioning is needed 143 | 144 | Members of both the Learning Core Team and Ember CLI Core team will have merge access. 145 | 146 | ## How we teach this 147 | 148 | Overall, bringing the CLI docs content up to speed and making it 149 | more maintainable should result in better integration of the 150 | CLI documentation into the Guides. The current content is out 151 | of date, and so it is not frequently linked. 152 | 153 | The impact to new users will be a better experience. Existing 154 | Ember users may have an adjustment period to learn the new layout, 155 | but the current layout is confusing, so we believe there will be 156 | net improvement from day one. The addition of search tools will help 157 | with the transition. 158 | 159 | Links in the Guides will need to be updated to point 160 | to the new documentation app. There are 41 links to the 161 | current ember-cli website, but only a handful are unique. 162 | 163 | The Ember CLI website is not referenced in the API docs. 164 | 165 | ## Drawbacks 166 | 167 | Some potential drawbacks include: 168 | 169 | - Old bookmarks will still point to old content, and it is significant engineering effort to maintain those legacy links 170 | - Users may be used to finding content in a particular place 171 | - Some existing content will be deemphasized or removed 172 | - It's another app to keep in step with the main website 173 | 174 | ## Alternatives 175 | 176 | An alternative is to refactor the content in place. This will be more 177 | time consuming, and will not achieve a consistent narrative voice or cumulative learning experience. 178 | -------------------------------------------------------------------------------- /active/0121-remove-ember-cli-eslint.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2018-08-13 2 | - RFC PR: [#121](https://github.com/ember-cli/rfcs/pull/121) 3 | 4 | # Summary 5 | 6 | Remove https://github.com/ember-cli/ember-cli-eslint from projects generated by 7 | `ember-cli`. 8 | 9 | [ember-cli-eslint](https://github.com/ember-cli/ember-cli-eslint) is an addon 10 | designed to show lint errors during test runs. Tooling around `eslint` has 11 | improved enough where this feature may no longer be necessary. 12 | 13 | To be clear, the proposal is _not_ to remove linting in tests. It is to follow 14 | the rest of JavaScript community and follow the standard tooling process. 15 | 16 | There are multiple ways to run `eslint`: 17 | 18 | 1. Integration with editors 19 | 2. Utilize precommit hooks with `eslint` 20 | 3. Support a standard way to run `eslint` (such as `yarn lint:js`) 21 | 22 | We can also discuss configuring `testem` to automatically run `eslint` as part 23 | of `yarn test` 24 | 25 | # Motivation 26 | 27 | 1. Improve our build speed 28 | 2. Simplicity. `eslint` is common among JS stack, and integrations with editors 29 | / precommit-hooks are ubiquitous. Removing this layer of abstraction will 30 | simplify how `eslint` is used throughout `ember-cli`. Most editors have 31 | plugins available for `eslint`, and as long as the `.eslint.rc` is not 32 | removed, we should still see the benefits of `eslint` in our Ember projects. 33 | 3. Hacks required to support features such as [PR #122 34 | broccoli-lint-eslint](https://github.com/ember-cli/broccoli-lint-eslint/pull/122#discussion-diff-153937455R28) 35 | 36 | # Detailed design 37 | 38 | 1. Change blueprint to pull in `eslint` as opposed to `ember-cli-eslint` under 39 | `devDependencies`. 40 | 2. Provide documentation on `eslint` and editor integration as well as precommit hooks 41 | 42 | Redefine `npm test` or `yarn test` (depending on whether the `--yarn` option was 43 | used to create project) to 44 | 45 | ``` 46 | ember test && npm run lint:js && npm run lint:hbs 47 | ``` 48 | 49 | and 50 | 51 | ``` 52 | ember test && yarn lint:js && yarn lint:hbs 53 | ``` 54 | 55 | 56 | # How We Teach This 57 | 58 | Providing documentation regarding how to run linting should suffice as well as 59 | documentation to editor integration. 60 | 61 | Deleting abstractions and going towards a explicit path, `eslint` within the 62 | `ember-cli` ecosystem becomes _easier_ to teach. 63 | 64 | # Drawbacks 65 | 66 | 1. No console warnings during builds 67 | 2. lint failures are no longer included in browser tests 68 | 69 | # Alternatives 70 | 71 | 1. Leave `ember-cli-eslint` alone 72 | 73 | # Unresolved questions 74 | 75 | N/A 76 | -------------------------------------------------------------------------------- /complete/0012-help-json-output.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2015-05-16 2 | - RFC PR: [#12](https://github.com/ember-cli/rfcs/pull/12) 3 | 4 | # Summary 5 | 6 | This has come up in [#3699](https://github.com/ember-cli/ember-cli/issues/3699) and [EmberTown/ember-hearth/#66](https://github.com/EmberTown/ember-hearth/issues/66). 7 | 8 | In short, it would be nice for tools that depend on Ember-CLI to be able to read the help output as JSON (for example `ember g --help --json`). 9 | 10 | # Motivation 11 | 12 | In our specific use case in [Ember Hearth](https://github.com/EmberTown/ember-hearth/) we would like to be able to render a dynamic GUI for some tasks, like generating blueprints. This way we could also include any blueprints added by addons. This will also apply to any other tools interfacing with Ember-CLI. 13 | 14 | # Detailed design 15 | We should probably make the internal help-functions (like `printBasicHelp` and `printDetailedHelp`) use JSON internally, and parse to human readable before printing (unless `--json` is specified). 16 | 17 | I'm imagining the json output would be something like this: 18 | 19 | ```json 20 | { 21 | "name":"generate", 22 | "description":"Generates new code from blueprints.", 23 | "aliases":["g"], 24 | "flags":[ 25 | { 26 | "flag":"--verbose", 27 | "aliases":["-v"], 28 | "description":"Verbose output" 29 | }, {…}], 30 | "commands":[ 31 | { 32 | "command":"template", 33 | "description":"Generates a template.", 34 | "arguments":["name"] 35 | }, 36 | { 37 | "command":"model", 38 | "description":"Generate an ember-data model.", 39 | "arguments":[ 40 | "name", 41 | { 42 | "argument":"attr:type", 43 | "description":"Add attributes to the model, e.g. 'name:String age:Number'", 44 | "multiple":true 45 | }] 46 | }, {…}] 47 | } 48 | ``` 49 | 50 | Note that this output contains a bit more info than the current --help, specifically in the attr:type argument for the model command. This is something I feel is currently missing (I did not understand the model generator command without consulting a colleague, for example), and would be nice to add while we're at it. 51 | 52 | It should be pretty straight forward to generate a human readable output from this JSON. There are a few things missing: However: The generate help command specifically groups commands by addon. I'm not sure how this should be accomplished, and if this matches the other help outputs. Ideally, any tools reading the JSON should be able to rely on the format being the same for all commands. This would keep the internals cleaner as well, including the human readable parser. 53 | 54 | # Drawbacks 55 | 56 | * Requires rewrite of help methods, possibly also for some addons (unless we can provide backwards compatability) 57 | * Increases codebase size 58 | 59 | # Alternatives 60 | 61 | * We could standardize help output enough that it can be safely regexed by other tools 62 | * We could not do this, and require any tools to update whenever Ember-CLI changes any commands 63 | 64 | # Unresolved questions 65 | 66 | * Internal architecture specifics (rewrite printBasicHelp or create a new setup, etc) 67 | * Specifying JSON format details 68 | * List any dependencies, like docs, that will need to be updated with this change 69 | -------------------------------------------------------------------------------- /complete/0020-sri-default.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2015-07-10 2 | - RFC PR: [#20](https://github.com/ember-cli/rfcs/pull/20) 3 | 4 | # Summary 5 | 6 | Enable [Subresource Integrity [SRI]](http://www.w3.org/TR/SRI/) checks by default. 7 | 8 | # Motivation 9 | 10 | To promote the use of SRI in Ember apps as a safe default. Applications should be built with integrity attributes when it is safe to do so. (Unfortunately the main advantage won't be met by default, however confirming one attribute will) 11 | 12 | This solves having poisoned CDN content: [An introduction to JavaScript-based DDoS](https://blog.cloudflare.com/an-introduction-to-javascript-based-ddos/) 13 | 14 | 15 | # Detailed design 16 | 17 | Install [ember-cli-sri](https://www.npmjs.com/package/ember-cli-sri) by default. 18 | 19 | - Applications with relative paths will get SRI. 20 | - Applications with `SRI.crossorigin` will get SRI on `fingerprint.prepend` assets 21 | - Applications with `fingerprint.prepend` and `origin` specified and matching get a `SRI.crossorigin` of anonymous on `fingerprint.prepend` assets 22 | 23 | By default development environments wont run SRI for performance reasons. 24 | 25 | Further explanation available in: [ember-cli-sri](https://www.npmjs.com/package/ember-cli-sri) 26 | 27 | # Drawbacks 28 | 29 | - SRI won't always be on for sites with prepend due to SRI requiring CORS. 30 | - CORS requirement adds a barrier to entry to some users. 31 | - Broken SRI attrs would break the application. 32 | 33 | # Alternatives 34 | 35 | No other alternatives appear suitable. 36 | 37 | # Unresolved questions 38 | 39 | - Adding origin attribute to add a safe same-origin check that doesn't need CORS. 40 | - Could users be warned until they explicitly set `SRI.enabled = false` or `SRI.crossorigin = `? 41 | -------------------------------------------------------------------------------- /complete/0028-app-import-output-file.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2015-11-02 2 | - RFC PR: [#28](https://github.com/ember-cli/rfcs/pull/28) 3 | 4 | # Summary 5 | 6 | Allow `app.import` to specify outputFIle of a given import. 7 | The default `app.import` would be considered to have an outputFile of 8 | `assets/vendor.js` 9 | 10 | # Motivation 11 | 12 | It is common for individuals to want control over the outputFile for a given 13 | dependency. For example, one may want to load some asm.js code independently 14 | rather then via the single vendor.js blob. 15 | 16 | It is also common for developers to want to group various dependencies 17 | together, and then lazy-load them in the routes they are required. 18 | 19 | Although not as automatic as we would like, it does provide a rather elegant 20 | escape valve. Further work will likely continue to explore automation. 21 | 22 | # Detailed design 23 | 24 | `outputFile:` option, specifies the target file for the given import. If 25 | multiple imports share an outputFile, they will be concatenated (regardless of 26 | type, css/images/videos/js/txt) in the order they where imported. 27 | 28 | `outputFile:` will default to `assets/vendor.js` 29 | 30 | ## Examples 31 | 32 | 33 | #### variation 0: the default 34 | 35 | ```js 36 | app.import('vendor/vim.js', { outputFile: 'assets/vendor.js'}); 37 | ``` 38 | 39 | #### variation 1: 1 file -> 1 outputFile 40 | 41 | ```js 42 | app.import('vendor/vim.js', { outputFile: 'assets/vim.js'}); 43 | ``` 44 | 45 | * `vendor/vim.js` becomes `assets/vim.js` 46 | * in prod it is: 47 | * uglified (unless using the uglify options it is excluded) 48 | * fingerprinted (unless it is excluded via the asset-rev options) 49 | 50 | #### variation 2, multiple files to same outputFile 51 | 52 | ```js 53 | app.import('vendor/dependency-1.js', { outputFile: 'assets/alternate-vendor.js'}); 54 | app.import('vendor/dependency-2.js', { outputFile: 'assets/alternate-vendor.js'}); 55 | ``` 56 | 57 | * in-order of the corresponding `app.import` invocation, using sourceMap 58 | concat, the files are combined into `assets/alternate-vendor.js` 59 | * `vendor/dependency-1.js` + `vendor/dependency-2.js` >> `assets/alternative-vendor.js` 60 | 61 | #### variation n, multiple files to same outputFile 62 | 63 | ```js 64 | app.import('vendor/dependency-1.js', { outputFile: 'assets/alternate-vendor.js'}); 65 | app.import('vendor/dependency-2.js', { outputFile: 'assets/alternate-vendor.js'}); 66 | app.import('vendor/dependency-n.js', { outputFile: 'assets/alternate-vendor.js'}); 67 | ``` 68 | 69 | * resulting concat is: 70 | * `vendor/dependency-1.js` + `vendor/dependency-2.js` ... `vendor/dependency-n.js`>> `assets/alternative-vendor.js` 71 | 72 | # Drawbacks 73 | 74 | * potential overlap with @chadhietala's packager/linker work 75 | * does not offer additional build-pipeline hooks for these files 76 | 77 | # Alternatives 78 | 79 | Alternatives exist, such as adding support to the linker/packager 80 | effort, or instructing developers to drop down and use 81 | broccoli-funnel/source-map-concat. 82 | 83 | The linker/packager effort is still a ways off, and could be thought of as 84 | complementary. 85 | 86 | Dropping down to broccoli is a solution available today, but for this problem, 87 | it feels like a slightly too low level of abstraction. 88 | 89 | # Unresolved questions 90 | 91 | * how does this relate to `type` in `app.import(..., { type: ... })` ? 92 | * should additional build-steps be allowed for specific output files? (I 93 | suspect maybe, but a future RFC can likely explore) 94 | -------------------------------------------------------------------------------- /complete/0029-addon-black-and-whitelist-for-apps.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2015-11-11 2 | - RFC PR: [#29](https://github.com/ember-cli/rfcs/pull/29) 3 | 4 | # Summary 5 | 6 | It should be possible to white- and/or blacklist addons in `EmberApp`. 7 | 8 | # Motivation 9 | 10 | If there are two (or more) `EmberApp`s, it's very likely that not all applications need all addons. 11 | E.g. if there is a main page application and one application for embeddable widgets, the main page might need all sorts of addons like `ember-modal-dialog` which adds completely useless bytes to widgets javascript and css files for the widgets. Other addons may add useless initializers or other things that have runtime performance penalties for no benefit. 12 | 13 | # Detailed design 14 | 15 | When EmberApp ctor gets passed a blacklist like this 16 | 17 | ```javascript 18 | EmberApp({ 19 | addonBlacklist: ['ember-modal-dialog'] 20 | }); 21 | ``` 22 | 23 | it won't add addons whose `name` matches `ember-modal-dialog` to the list of addons for this app, just as if the addon's `isEnabled()` hook returned `false`. 24 | 25 | C.f. https://github.com/ember-cli/ember-cli/blob/master/lib/broccoli/ember-app.js#L344, this is also were I would add this check. 26 | 27 | Whitelist could work analogously. 28 | 29 | # Drawbacks 30 | 31 | - It adds a bit of API surface while you (possibly) don't care for the multiple app use case of ember-cli. 32 | 33 | - It kinda makes the `name` of an addon public api, so people might change it, not noticing they are breaking people's build (and people might not notice it either). Some addons have names like `Ember CLI ic-ajax` which seems awkward to use as an identifier. 34 | 35 | # Alternatives 36 | 37 | - Add a unified way to enable/disable an addon via normal config 38 | - if that is added one day, the white/blacklist could still be an abstraction for that 39 | 40 | # Unresolved questions 41 | 42 | None. 43 | -------------------------------------------------------------------------------- /complete/0055-anonymous-amd.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-06-14 2 | - RFC PR: [#55](https://github.com/ember-cli/rfcs/pull/55) 3 | 4 | # Summary 5 | 6 | This RFC proposes extending the `app.import` API to consume anonymous AMD modules. It accompanies [ember-cli PR 5976](https://github.com/ember-cli/ember-cli/pull/5976). 7 | 8 | # Motivation 9 | 10 | AMD modules come in two flavors: named and anonymous. _Anonymous AMD_ is the more portable distribution format, but it typically requires preprocessing into _named AMD_ before it can be included into an application. 11 | 12 | /* Anonymous AMD Examples */ 13 | 14 | // direct value 15 | define({ color: 'black' }); 16 | 17 | // function returning value 18 | define(function() { return { color: 'black' }; }); 19 | 20 | // function returning value, with declared dependencies 21 | define(["jquery", "moment"], function(jQuery, moment) { 22 | return { 23 | injectTime: function() { 24 | jQuery('#time-box').html(moment().format('HH:MM')); 25 | } 26 | } 27 | }); 28 | 29 | /* Named AMD Examples */ 30 | 31 | // direct value 32 | define('my-config', { color: 'black' }); 33 | 34 | // function returning value 35 | define('my-config', function() { return { color: 'black' }; }); 36 | 37 | // function returning value, with declared dependencies 38 | define('time-utils', ["jquery", "moment"], function(jQuery, moment) { 39 | return { 40 | injectTime: function() { 41 | jQuery('#time-box').html(moment().format('HH:MM')); 42 | } 43 | } 44 | }); 45 | 46 | 47 | Today, ember-cli users can add arbitrary third-party _named AMD_ modules into their application via: 48 | 49 | app.import('/path/to/module.js'); 50 | 51 | But this does not support _anonymous AMD_ modules, which is annoying because _anonymous AMD_ is the better format for library distribution and is widely used. 52 | 53 | # Detailed design 54 | 55 | In order to de-anonymize AMD, it's necessary to choose a name for the module for use within a given application. So I propose extending the: 56 | 57 | app.import('/path/to/module.js'); 58 | 59 | API with an additional argument: 60 | 61 | app.import('/path/to/module.js', { 62 | using: [ 63 | { transformation: 'amd', as: 'some-dep' } 64 | ] 65 | }); 66 | 67 | `using` provides a list of transformations. Each transformation is identified by its `transformation` property. Any other properties are treated as arguments to the transformation implementation -- they are opaque to ember-cli. Transformations will run in the given order. 68 | 69 | In this particular case, the `amd` transformation will run and receive the argument `{as: 'some-dep'}`. 70 | 71 | The exactly meaning of the `amd` transformation is: within this Javascript file, any call(s) to the global `define()` function will be intercepted and the given module name (`some-dep` in the above example) will be prepended to the argument list. 72 | 73 | [A complete implementation is available here](https://github.com/ember-cli/ember-cli/pull/5976). (As of this edit it lags behind updates to this RFC.) 74 | 75 | # Learning 76 | 77 | An appropriate place to document this feature is [here](https://ember-cli.com/user-guide/#standard-amd-asset). That existing documentation is silent on the distinction between named and anonymous AMD, which probably trips people up. 78 | 79 | # Drawbacks 80 | 81 | I am not attempting to specify static error detection, mostly because doing that well would require fully parsing and understanding the imported module, which is likely to be more expensive and fragile. 82 | 83 | Examples of static errors that would theoretically be nice to detect would be the presence of a _named AMD_ module in the file, the lack of any AMD module in the file, or the present of multiple _anonymous AMD_ modules in the file. 84 | 85 | The current implementation causes any sourcemap information inside the imported file to be discarded (you don't get an invalid sourcemap, but you lose detail). 86 | 87 | I have not specified a pluggable way to add additional transformations. My intent is to reserve space in our public API so that future extraction and pluggability is fully backward compatible. 88 | 89 | # Alternatives 90 | 91 | Many libraries fall back to global variables if they cannot detect a valid AMD loader. I suspect this is the most common alternate pattern that's in use in the community. 92 | 93 | Some applications include their own manually written shims in `vendor` or elsewhere. 94 | 95 | # Unresolved questions 96 | 97 | We should confirm that my implementation performs well in apps with very large dependency directories. 98 | -------------------------------------------------------------------------------- /complete/0080-serve-file-api.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-11-21 2 | - RFC PR: [#80](https://github.com/ember-cli/rfcs/pull/80) 3 | 4 | # Summary 5 | 6 | This RFC attempts to expose a public API in `ember-cli` to allow other platforms/infrastructure to serve the base page (index.html) and other assets from the `tmp` directory in their own custom way. This is only for development as this will only be used with `ember serve`. Currently `ember serve` serves files from the tmp directory (which is built as part of the build process) using the `broccoli-middleware`. This middleware in addition to serving the files also sets the correct headers for the assets it is serving. This RFC aims to split the work of setting the header and serving the files into two different addons such that any other infrastructure can easily create a middleware to serve assets using its own logic. 7 | 8 | # Motivation 9 | 10 | FastBoot and other infrastructure (for example the infrastructure at LinkedIn to serve the base page) does not require the index.html to be served from the disk directly. FastBoot requires to serve the index.html after it has appended the serialized template for the current request. It therefore requires to do some runtime replacements in the index.html before it can be served to the client. At LinkedIn, we stream the index.html in chunks for performance reasons and require to do some string replacements in index.html on per request basis. 11 | 12 | During development, this requires us to create our own express middleware via `serverMiddleware` which should run before the `serve-files` middleware. It also requires us to almost copy paste the headers that are set by `broccoli-middleware`. In addition to the above, the ability to be able to serve from `tmp` directory allows FastBoot and other infrastructure to correctly serve the assets from the directory pointing to the current build. Currently (with using their own middleware) FastBoot serves assets from the `dist` directory which is not the correct behavior. 13 | 14 | In order to mitigate the need to diverge into another middleware which behaves almost same as `broccoli-middleware`, this RFC proposes to split the work of setting the headers and serving the files via `broccoli-middleware` and expose a public API that will allow an addon to define how it wants to serve the assets. It will be a low level public API that will be invoked by certain addons. 15 | 16 | # Detailed design 17 | 18 | Currently the [`serve-files`](https://github.com/ember-cli/ember-cli/blob/375f3a32f4564465d2eccc3815cb61b570ce29f0/lib/tasks/server/middleware/serve-files/index.js#L18) addon defines how it will serve the incoming asset requests. It invokes the `broccoli-middleware` which is responsible for three sets of things: 19 | 20 | 1. Setting the response headers 21 | 22 | 2. serving the files and ending the response 23 | 24 | 3. Shows an error template if it is a build error 25 | 26 | ## Public API 27 | This RFC proposes expose two new in-repo addons in `ember-cli` which will now split the above work and remove the `serve-files` addon: 28 | 29 | 1. `ember-cli:broccoli:watcher`: This addon will contain the middleware which will be responsible for making sure the build is done and will set the response headers that `broccoli-middleware` is doing today. After setting the response headers, it will call the next middleware in the chain. In addition, if the build results in an error, it will show the error template and not terminate the response. 30 | 31 | 2. `ember-cli:broccoli:serve-files`: This addon will always run *after* `ember-cli:broccoli:watcher` addon. It will contain a middleware that will be responsible for serving the files from the filesystem and ending the response. 32 | 33 | For any infrastructure that needs to serve the assets in its own way will be create an addon that will be injected between the above two addons. It will use the `serverMiddleware` public hook to provide its own middleware. Specifically the custom addon should run *before* `ember-cli:broccoli:serve-files` so that it can either override any response headers or can serve the files using its own logic and end the response. This will ensure that when the build is successful `ember-cli:broccoli:watcher` can call the correct next middleware in the chain. 34 | 35 | ## Implementation Details 36 | In order for the above API to be exposed, we need to drop the `serve-files` addon in `ember-cli`, refactor `broccoli-middleware` and create the two new addons. 37 | 38 | ### Refactor `broccoli-middleware` to expose additional middlewares 39 | *Note*: This refactor section is only for making the reader understand how the integration is meant to work in `ember-cli`. This is not going to be `ember-cli` public API. 40 | 41 | `broccoli-middleware` is currently responsible for setting the response headers and serving the files. It is a middleware that does these two tasks. It doesn't expose a proper middleware API to do the two tasks differently. We would like to refactor `broccoli-middleware` such that it exposes two additional middlewares: 42 | - `forWatcher(watcher)`: 43 | ```javascript 44 | /** 45 | * Function responsible for setting the response headers or creating the build error template 46 | * 47 | * @param {Object} watcher ember-cli watcher 48 | * @return {Function} middleware function 49 | */ 50 | forWatcher: function(watcher) { 51 | var outputPath = watcher.builder.outputPath; 52 | ... 53 | return function middleware(request, response, next) { 54 | watcher.then(function() { 55 | // mostly all of this https://github.com/ember-cli/broccoli-middleware/blob/master/lib/middleware.js#L96 56 | request.headers['x-broccoli'] = { 57 | outputPath: outputPath 58 | }; 59 | next(); 60 | }, function(buildError) { 61 | // mostly this: https://github.com/ember-cli/broccoli-middleware/blob/master/lib/middleware.js#L121 62 | }) 63 | } 64 | 65 | } 66 | ``` 67 | 68 | - `serveFiles()`: 69 | ```javascript 70 | /** 71 | * This function will be responsible for serving the files from the filesystem 72 | * 73 | * @param {HTTP.Request} request 74 | * @param {HTTP.Response} response 75 | * @param {Function} next 76 | */ 77 | serveFiles: function() { 78 | return function(req, resp, next) { 79 | // get the output path from from the request headers 80 | // most of `broccoli-middleware` https://github.com/ember-cli/broccoli-middleware/blob/master/lib/middleware.js#L115 81 | } 82 | } 83 | ``` 84 | 85 | ### Create `ember-cli:broccoli:watcher` addon 86 | The current `serve-files` addon invokes the `broccoli-middleware` and delegates the task to this middleware to serve the files and set the headers. We would like to change that and instead this new in-repo addon `ember-cli:broccoli:watcher` should only call `setResponseHeaders` function from `broccoli-middleware`. The `serverMiddleware` function of this [addon](https://github.com/ember-cli/ember-cli/blob/375f3a32f4564465d2eccc3815cb61b570ce29f0/lib/tasks/server/middleware/serve-files/index.js#L18) will now look as follows: 87 | ```javascript 88 | ServeFilesAddon.prototype.serverMiddleware = function(options) { 89 | var app = options.app; 90 | var watcher = options.options.watcher; 91 | var broccoliMiddleware = require('broccoli-middleware'); 92 | 93 | app.use(function(req, resp, next) { 94 | // copy over this: https://github.com/ember-cli/ember-cli/blob/375f3a32f4564465d2eccc3815cb61b570ce29f0/lib/tasks/server/middleware/serve-files/index.js#L33 95 | if (options.options.middleware) { 96 | // call the middleware that is provided for testemMiddleware 97 | } else { 98 | var watcherMiddleware = broccoliMiddleware.forWatcher(watcher); 99 | 100 | watcherMiddleware(req, resp, function(err) { 101 | if (err) { 102 | // log error 103 | } 104 | next(err); 105 | }); 106 | } 107 | }); 108 | } 109 | ``` 110 | 111 | As seen above `ember-cli:broccoli:watcher` will only be responsible for setting the headers and calling the the next middleware which will serve the files. 112 | 113 | ### Create `ember-cli:broccoli:serve-files` addon 114 | We will create a new in-repo addon called as `ember-cli:broccoli:serve-files` which will be responsible for serving the the files. This addon will run *after* `ember-cli:broccoli:watcher` addon. 115 | 116 | This function will be responsible for serving the incoming asset request from the filesystem. It will use the `serverMiddleware` API to serve the files using `broccoli-middleware`. 117 | ```javascript 118 | BroccoliServeFilesAddon.prototype.serverMiddleware = function(options) { 119 | var broccoliMiddleware = require('broccoli-middleware'); 120 | var outputPath = options.watcher.builder.outputPath; 121 | var autoIndex = false; 122 | 123 | var options = { outputPath, autoIndex }; 124 | app.use(function(req, resp, next) { 125 | var serveFileMiddlware = broccoliMiddleware.serveFiles(); 126 | serveFileMiddlware(req, resp, function(err) { 127 | next(err); 128 | }) 129 | }); 130 | } 131 | ``` 132 | 133 | In order for FastBoot to be able to serve the assets using its own logic, it will specific that it run *before* `ember-cli:broccoli:serve-files` addon so that it can serve the assets. In this way, FastBoot will be able to inject itself into the correct order and be able to serve assets from the `tmp` directory. 134 | 135 | ### Drop `serve-files` addon in ember-cli 136 | Since the work that `serve-files` does today is now split into two new in-repo addons, `serve-files` addon doesn't need to be present any longer. It is not exposing any public API or functionality that users may be using today and therefore can be dropped. 137 | 138 | # How We Teach This 139 | 140 | We will need to update the `ember-cli` website with this new in-repo addon and specify the above usecase with an example. 141 | 142 | # Drawbacks 143 | 144 | The only drawback is addon authors wanting to serve assets using their own logic, will need to know the correct order of middleware execution. Moreover, if someone has forked `ember-cli` to hack `serve-files` addon logic, it will be a breaking change for them. 145 | 146 | # Alternatives 147 | 148 | N/A 149 | 150 | # Unresolved questions 151 | - [ ] Should this addons be better named? 152 | -------------------------------------------------------------------------------- /complete/0090-addon-tree-caching.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-12-11 2 | - RFC PR: [#90](https://github.com/ember-cli/rfcs/pull/90) 3 | 4 | # Summary 5 | 6 | In Ember CLI today, all addons at each level are built through the standard `treeFor` / `treeFor*` hooks. These hooks are responsible for preprocessing the JavaScript included by the tree returned from that specific hook (e.g., `treeForAddon` preprocesses the JS for the addon tree). This RFC proposes a mechanism that would allow these returned trees to be cached by default (when no build time customization is done) and expose proper hooks for addon authors to control the degree to which we dedupe these trees. 7 | 8 | # Motivation 9 | 10 | Today, given the dependency graph: 11 | 12 | ``` 13 | ember-basic-dropdown: 14 | ember-wormhole@0.4.1 15 | 16 | ember-modal-dialog: 17 | ember-wormhole@0.4.1 18 | 19 | ember-paper: 20 | ember-wormhole@0.4.1 21 | ``` 22 | We would actually build `ember-wormhole`'s `addon` tree 3 different times, even though [as you can see](https://github.com/yapplabs/ember-wormhole/blob/0.4.1/index.js) there is absolutely no build time customization being done. After all of these `ember-wormhole` tree instances are built, we merge them such that the last tree wins (thus making all of the work to preprocess these trees completely moot). If you extrapolate this out to larger applications or ones using multiple engines (lazy or not) it is fairly common to see these sorts of dependencies shared upwards of 4 to 5 times. This can lead to significant build performance degradation. 23 | 24 | # Detailed design 25 | 26 | - Add a `Addon.prototype.cacheKeyForTree` method to [lib/models/addon.js](https://github.com/ember-cli/ember-cli/commits/master/lib/models/addon.js) that is invoked prior to calling `treeFor` for the same tree name. The `Addon.prototype.cacheKeyForTree` method is expected to return a cache key allowing multiple builds of the same tree to simply return the original tree (preventing duplicate work). If `Addon.prototype.cacheKeyForTree` returns `null` / `undefined` the tree in question will opt out of this caching system. 27 | - ember-cli's custom [`mergeTrees` implementation](https://github.com/ember-cli/ember-cli/blob/4ec7b5951e8a9dd292029faf20d1858abf7bdfa0/lib/broccoli/merge-trees.js) (which is already aware of other tree reduction techniques) will be updated so that calling `mergeTrees([treeA, treeA]);` simply returns `treeA`, and `mergeTrees([treeA, treeB, treeA])` removes the duplicated `treeA` in the input nodes. 28 | 29 | The proposed declaration for `Addon.prototype.cacheKeyForTree` in Typescript syntax is: 30 | 31 | ``` ts 32 | function cacheKeyForTree(treeType: string): string; 33 | ``` 34 | The default implementation for `Addon.prototype.cacheKeyForTree` will: 35 | 36 | - Utilize a shared NPM package (e.g. `calculate-cache-key-for-tree`) that will generate a cache key that incorporates at least the following pieces of information: 37 | - `this.name` - The addon's name (generally from `package.json`). 38 | - `this.pkg` - This builds a checksum accounting for the addon's `package.json`. 39 | - `treeType` - The specific tree in question (e.g. `addon`, `vendor`, `addonTestSupport`, `templates`, etc). 40 | 41 | - Resort to disabling all addon tree caching in the following scenarios 42 | - The addon implements a custom `treeFor` 43 | - The addon implements a custom `treeFor*` method (where `*` represents the tree type) 44 | 45 | 46 | Addons that implement custom `treeFor` or `treeFor*` methods can still opt-in to caching in scenarios that they can confirm are safe. To do this, they would implement a custom `cacheKeyForTree` method and return a cache key as appropriate for their caching needs. 47 | 48 | # How We Teach This 49 | 50 | This is something that we do not expect 99% of ember-cli users to have to learn and understand, however it is still important for it to be possible to determine what is going on and how to work within the system when building addons. 51 | 52 | The following should help us teach this to the correct audience (roughly "addon power users"): 53 | 54 | - Document the shared NPM package (referred to above as `calculate-cache-key-for-tree`). This will help authors of addons that need to implement `treeFor*` hooks understand how they can properly implement `Addon.prototype.cacheKeyForTree`. 55 | - Write API docs for the newly added `Addon.prototype.cacheKeyForTree` method. 56 | 57 | # Drawbacks 58 | 59 | - Cache invalidation is difficult to get right, and it is possible to accidentally troll our users. This can be mitigated by thorough review of the implementation and this RFC. 60 | 61 | # Alternatives 62 | 63 | # Unresolved questions 64 | 65 | - Confirm if including the same tree multiple times will only trigger a single build of that tree (this should be a Broccoli feature). We have confirmed that code exists in broccoli-builder ([see here](https://github.com/ember-cli/broccoli-builder/blob/0-18-x/lib/builder.js#L89-L97)), but still need to actually confirm `.build` / `.read` / `.rebuild` are not called twice within the same build. 66 | 67 | -------------------------------------------------------------------------------- /complete/0091-addon-instrumentation-experimental-hooks.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-12-14 2 | - RFC PR: [#91](https://github.com/ember-cli/rfcs/pull/91) 3 | 4 | # Summary 5 | 6 | Add an instrumentation hook that is available to addons. This enables users to 7 | write addons that do things like summarize and report build performance 8 | information. 9 | 10 | - see https://github.com/ember-cli/ember-cli/issues/6349 for additional context. 11 | - see https://github.com/ember-cli/ember-cli/pull/6606 for an experimental 12 | implementation. 13 | 14 | # Motivation 15 | 16 | Build performance is important to users. We want to enable users to: 17 | 18 | 1. Easily discover which portions of their build are costly; 19 | 2. Be able to summarize and report build information in an addon; 20 | 3. Be able to write addons that analyze build performance instrumentation so 21 | that they can more easily help diagnose build performance issues in projects 22 | to which they do not have direct access. This is of particular interest to 23 | @ember-cli/core &c. 24 | 25 | In order to provide these hooks to enable iteration and experimentation prior to 26 | making firm commitments to format, this rfc propose to initially expose them as 27 | experiments (see the experiments section below). 28 | 29 | # Detailed design 30 | 31 | ## Experiments 32 | 33 | Experiments live in `lib/experiments/index.js`. Unlike feature flags, there is 34 | no need to strip them from production. Experiments allow us to provide power 35 | user features that are not fully stable without their resorting to private API 36 | usage. 37 | 38 | Experiments are available only in canary builds. This is achieved by only 39 | including `lib/experiements/index.js` in canary, and making it the entry point 40 | for all experiments. 41 | 42 | ## Instrumentation Hook 43 | 44 | We have already a build instrumentation hook as an 45 | experiment in https://github.com/ember-cli/ember-cli/pull/6546 46 | 47 | A more encompassing instrumentation hook is implemented in 48 | https://github.com/ember-cli/ember-cli/pull/6606 49 | 50 | 51 | The goal of this RFC is: 52 | 53 | 1. To make the concept of experiments supported and explicit 54 | 2. To promote this particular experiment to public API 55 | 56 | ### Enabling Instrumentation 57 | 58 | Instrumentation is enabled if either the environment variable `BROCCOLI_VIZ` is 59 | set to `1` or if `EMBER_CLI_INSTRUMENTATION` is set to `1`. 60 | 61 | If `BROCCOLI_VIZ=1` then in addition to instrumentation hooks being invoked, a 62 | serialized form of the instrumentation information is written to disk, that is 63 | appropriate for consumption by [broccoli-viz](https://github.com/ember-cli/broccoli-viz) which is the current behaviour. 64 | 65 | ### Instrumentation 66 | 67 | #### Hook 68 | 69 | An addon that implements `instrumentation` will have this hook invoked when 70 | instrumentation is enabled. 71 | 72 | ```js 73 | module.exports = { 74 | name: 'my-great-addon', 75 | 76 | instrumentation(name, payload) { 77 | // format of instrumentation payload outlined below 78 | } 79 | }; 80 | ``` 81 | 82 | ##### name 83 | 84 | The `name` argument indicates what phase the instrumentation payload describes. 85 | In beta and released versions this will always be a string. 86 | 87 | On canary it could be a symbol from `lib/experiments` if we add more phases (eg 88 | more fine-grained phases) for instrumentation information. 89 | 90 | The initial set of phases this RFC advocates are: 91 | - `init` 92 | - `command` 93 | - `build` 94 | - `shutdown` 95 | 96 | ##### payload 97 | 98 | `payload` is an object with two properties, `summary` and `graph`. 99 | 100 | ##### payload.summary 101 | 102 | The exact format of `payload.summary` depends on the specific phase for which 103 | the instrumentation hook was called. In each case, the keys listed are the 104 | minimum keys that are guaranteed to be present, but there is no guarantee that 105 | additional information might not also be present. 106 | 107 | ###### init 108 | 109 | `init` covers the period up to, but not including, command execution. This 110 | means it's mostly dealing with `require` time. 111 | 112 | For `init`, the summary object has the following shape. 113 | 114 | ```js 115 | { 116 | totalTime, 117 | platform: { 118 | name, 119 | }, 120 | } 121 | ``` 122 | 123 | - `summary.totalTime` The total time spent during `init` 124 | - `summary.platform.name` The value of `process.platform` 125 | 126 | ###### build 127 | 128 | `build` covers the time spent in an individual build or rebuild. 129 | 130 | For `build`, the summary object has the following shape. 131 | 132 | ```js 133 | { 134 | build: { 135 | type, 136 | count, 137 | outputChangedFiles 138 | 139 | // additional fields for rebuilds 140 | primaryFile, 141 | primaryFileCount, 142 | changedFiles 143 | }, 144 | platform: { 145 | name, 146 | }, 147 | output, 148 | totalTime, 149 | buildSteps, 150 | } 151 | ``` 152 | 153 | - `summary.build.type` one of `'initial'` or `'rebuild'` 154 | - `summary.build.count` the number of the build (0 for initial build, > 0 for 155 | rebuilds). 156 | - `summary.build.outputChangedFiles` an array of paths to output files that 157 | changed during this build. These paths are relative to the `dist` directory. 158 | - `summary.build.primaryFile` only present for rebuilds. Indicates the first 159 | file the watcher noticed had changed. 160 | - `summary.build.changedFileCount` only present for rebuilds. The number of 161 | files the watcher had noticed changed before the build started. 162 | - `summary.build.changedFiles` only present for rebuilds. The first 10 files 163 | the watcher had noticed changed before the build started. 164 | - `summary.platform.name` The value of `process.platform` 165 | - `summary.output` The temp directory containing the results of the build. 166 | - `summary.totalTime` The total time (in nanoseconds) of the build. 167 | - `summary.buildSteps` The number of broccoli nodes built in this tree 168 | 169 | ###### command 170 | 171 | `command` covers the time spent during a command. When the command includes a 172 | build, there will be overlap between `command` and `build`. When the command is 173 | `serve`, this overlap will include only the last build, to avoid memory leaks. 174 | 175 | For `command`, the summary object has the following shape. 176 | 177 | ```js 178 | { 179 | totalTime, 180 | platform: { 181 | name, 182 | }, 183 | name, 184 | args 185 | } 186 | ``` 187 | 188 | - `summary.totalTime` The total time spent during `init` 189 | - `summary.platform.name` The value of `process.platform` 190 | - `summary.name` The name of the command that was run 191 | - `summary.args` The args of the command that was run 192 | 193 | ###### shutdown 194 | 195 | `shutdown` covers the period from the command completing to process exit, ie 196 | cleanup time. 197 | 198 | For `shutdown`, the summary object has the following shape. 199 | 200 | ```js 201 | { 202 | totalTime, 203 | platform: { 204 | name, 205 | }, 206 | } 207 | ``` 208 | 209 | - `summary.totalTime` The total time spent during `init` 210 | - `summary.platform.name` The value of `process.platform` 211 | 212 | ##### payload.graph 213 | 214 | `graph` is an object that represents the instrumentation information we have 215 | gathered for the build. It is a DAG, whose flow is inverted from the broccoli 216 | graph. It has a single source node (currently `TreeMerger (all trees)`). 217 | `payload.graph` is this single source node. 218 | 219 | Each node in the graph provides an API for iterating its subgraph as well as 220 | iterating its own stats. The specific nodes in the graph will change over time as 221 | the instrumentation within ember-cli changes. There is no particular guarantee 222 | about what the nodes will be, although we will continue to ensure that its 223 | `toJSON` format is consumable by 224 | [broccoli-viz](https://github.com/ember-cli/broccoli-viz) 225 | 226 | The API that each node supports is: 227 | 228 | - `label` 229 | - `toJSON` 230 | - `adjacentIterator` 231 | - `dfsIterator` 232 | - `bfsIterator` 233 | 234 | ###### label 235 | 236 | A POJO property that describes the node. It will always include a `name` 237 | property and for broccoli nodes will include a `broccoliNode` property. 238 | 239 | Example: 240 | ```js 241 | node.label === { 242 | name: 'TreeMerger (allTrees)', 243 | broccoliNode: true, 244 | } 245 | ``` 246 | 247 | ###### toJSON() 248 | 249 | Returns a POJO that represents the serialized subgraph rooted at this node (the 250 | entire tree if called on the root node). 251 | 252 | There is no particular guarantee about the format, except that whatever it is 253 | will be supported by [broccoli-viz](https://github.com/ember-cli/broccoli-viz). 254 | 255 | Example: 256 | ```js 257 | // for a graph 258 | // TreeMerger 259 | // |- Babel_1 260 | // |- Babel_2 261 | // |--|- Funnel 262 | console.log(JSON.stringify(node.toJSON(), null, 2)); 263 | // might print 264 | // 265 | { 266 | nodes: [{ 267 | id: 1, 268 | children: [2,3], 269 | stats: { 270 | time: { 271 | self: 5000000, 272 | }, 273 | fs: { 274 | lstat: { 275 | count: 2, 276 | time: 2000000 277 | } 278 | }, 279 | own: { 280 | } 281 | } 282 | }, { 283 | // ... 284 | }] 285 | } 286 | ``` 287 | 288 | ###### adjacentIterator 289 | 290 | Returns an iterator that yields each adjacent outbound node. There is no 291 | guarantee about the order in which they are yielded. 292 | 293 | ```js 294 | // for a tree 295 | // TreeMerger 296 | // |- Babel_1 297 | // |--|- Funnel 298 | // |- Babel_2 299 | node.label.name === "TreeMerger"; 300 | for (n of node.adjacentIterator()) { 301 | console.log(n.label.name); 302 | } 303 | // prints 304 | // 305 | // Babel_1 306 | // Babel_2 307 | 308 | 309 | for (n of node.preOrderIterator(x => x.label.name === 'Babel_2')) { 310 | console.log(n.label.name); 311 | } 312 | // prints 313 | // 314 | // TreeMerger 315 | // |- Babel_1 316 | ``` 317 | 318 | ###### dfsIterator(until) 319 | 320 | Returns an iterator that yields every node in the subgraph sourced at this node. 321 | Nodes are yielded in depth-first order. If the optional parameter `until` is 322 | passed, nodes for which `until` returns `true` will not be yielded, nor will 323 | nodes in their subgraph, unless those nodes are reachable by some other path. 324 | 325 | Example: 326 | ```js 327 | // for a graph 328 | // TreeMerger 329 | // |- Babel_1 330 | // |--|- Funnel 331 | // |- Babel_2 332 | for (n of node.dfsIterator()) { 333 | console.log(n.label.name); 334 | } 335 | // prints 336 | // 337 | // TreeMerger 338 | // Babel_1 339 | // Funnel 340 | // Babel_2 341 | ``` 342 | 343 | ###### bfsIterator() 344 | 345 | Returns an iterator that yields every node in the subgraph sourced at this node. 346 | Nodes are yielded in breadth-first order. If the optional parameter `until` is 347 | passed, nodes for which `until` returns `true` will not be yielded, nor will 348 | nodes in their subgraph, unless those nodes are reachable by some other path. 349 | 350 | 351 | Example: 352 | ```js 353 | // for a tree 354 | // TreeMerger 355 | // |- Babel_1 356 | // |--|- Funnel 357 | // |- Babel_2 358 | for (n of node.bfsIterator()) { 359 | console.log(n.label.name); 360 | } 361 | // prints 362 | // 363 | // TreeMerger 364 | // Babel_1 365 | // Babel_2 366 | // Funnel 367 | ``` 368 | 369 | ###### statsIterator() 370 | 371 | Returns an iterator that yields `[name, value]` pairs of stat names and values. 372 | 373 | Example: 374 | ```js 375 | // for a typical broccoli node 376 | for ([statName, statValue] of node.statsIterator()) { 377 | console.log(statName, statValue); 378 | } 379 | // prints 380 | // 381 | // "time.self" 64232794 382 | // "fs.statSync.count" 40 383 | // "fs.statSync.time" 401232123 384 | // ... 385 | ``` 386 | 387 | # How We Teach This 388 | 389 | This has no effect on day-to-day usage of ember-CLI. It is a tool to help users 390 | monitor and analyze their build performance, so documentation and teaching 391 | belong primarily in `PERF_GUIDE.md`. Having said that, we should also add a 392 | section to `https://ember-cli.com/extending/` and the API docs to make using 393 | this feature easier for addon authors and CLI power users. 394 | 395 | # Drawbacks 396 | 397 | * No drawbacks come to mind, besides the ever present issue of maintenance 398 | 399 | # Alternatives 400 | 401 | One alternative is the status quo: with `BROCCOLI_VIZ=1` users can output a file 402 | with a similar format that they can post-process offline. Although this works 403 | for manual analysis, it is considerably more cumbersome for any automated system 404 | (such as ongoing monitoring of build performance). It also does not include 405 | instrumentation outside of the build, most notably startup. 406 | 407 | # Unresolved questions 408 | 409 | - [heimdalljs-tree](https://github.com/heimdalljs/heimdalljs-tree) supports 410 | `Symbol.Iterator`; should we commit to this as part of our API? 411 | 412 | -------------------------------------------------------------------------------- /complete/0092-blueprint-remove-old-files.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2016-12-17 2 | - RFC PR: [#92](https://github.com/ember-cli/rfcs/pull/92) 3 | 4 | # Summary 5 | 6 | Give blueprint generators the ability to clean up old files. 7 | 8 | # Motivation 9 | 10 | We want to eliminate the noise of having old files laying after updating 11 | ember-cli using `ember init`. 12 | 13 | # Detailed design 14 | 15 | We'd like an API for blueprints to delete files instead of only 16 | create. It would be essentially syntactic sugar for removing the file yourself 17 | in an `afterInstall` hook. It would be a returned array on the blueprint's `index.js`. 18 | 19 | ```js 20 | // ember-cli/bluprints/blah/index.js 21 | module.exports = { 22 | // ... 23 | 24 | get oldFilesToRemove() { 25 | return [ 26 | 'brocfile.js', 27 | 'LICENSE.MD', 28 | 'testem.json' 29 | ]; 30 | } 31 | }; 32 | ``` 33 | 34 | # How We Teach This 35 | 36 | The guides could use this addition in the blueprints section, but I envision it 37 | being used by mostly power users. 38 | 39 | A changelog entry should be sufficient to teach this. 40 | 41 | # Drawbacks 42 | 43 | The only reason to not do this is to hold out for a large blueprint reworking. 44 | We would be locked into this API. 45 | 46 | # Alternatives 47 | 48 | The key name can be bikeshed. I chose `oldFilesToRemove` to be verbose and 49 | explicit, but it can be changed. 50 | -------------------------------------------------------------------------------- /complete/0095-standardise-targets.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2017-01-03 2 | - RFC PR: [#95](https://github.com/ember-cli/rfcs/pull/95) 3 | 4 | # Summary 5 | 6 | This RFC proposes the introduction of a official convention to specify the target browsers 7 | and node versions of an application. 8 | 9 | # Motivation 10 | 11 | Javascript and the platforms it runs on are moving targets. NodeJS and browsers release new 12 | versions every few weeks. Browsers auto update and each update brings new language features 13 | and APIs. 14 | 15 | Developers need an easy way to express intention that abstracts them from the ever-changing 16 | landscape of versions and feature matrices, so this RFC proposes the introduction of a unique 17 | place and syntax to let developers express their intended targets that all addons can use, 18 | instead of having each addon define it in a different way. 19 | 20 | This configuration should be easily available to addons, but this RFC doesn't impose 21 | any mandatory behavior on those addons. All addons that want to customize their behavior 22 | depending on the target browsers will have a single source of truth to get that 23 | information but it's up to them how to use it. 24 | 25 | The advantage of having a single source of truth for the targets compared to configure this 26 | on a per-addon basis like we do today is mostly for better ergonomics and across-the-board 27 | consistency. 28 | 29 | Examples of addons that would benefit from this conventions are `babel-preset-env`, `autoprefixer`, 30 | `stylelint` and `eslint` (vía `eslint-plugin-compat`) and more. Even Ember itself could, 31 | once converted into an addon, take advantage of that to avoid polyfilling or even taking 32 | advantage of some DOM API (`node.classList`?) deep in Glimmer's internals, helping the goal 33 | of Svelte Builds. 34 | 35 | # Detailed design 36 | 37 | What seems to be the most popular tool and the state of the art on building suport matrices 38 | for browser targets is the [browserlist](https://github.com/ai/browserslist) npm package. 39 | 40 | That package is the one behind `babel-preset-env`, `autoprefixer` and others, and uses the data from 41 | [Can I Use](http://caniuse.com/) for knowing the JS, CSS and other APIs available on every browser. 42 | 43 | The syntax of this package is natural but also pretty flexible, allowing complex 44 | queries like `Firefox >= 20`, `>2.5% in CA` (browsers with a market share over 2.5% in Canada) 45 | and logical combinations of the previous. 46 | 47 | The way this library work is by calculating the minimum common denominator support on a per-feature basis. 48 | 49 | Per example, if the support matrix for an app is `['IE11', 'Firefox latest']` and we have a linter 50 | that warns us when we use an unsupported browser API, it would warn us if we try to use 51 | pointer events (supported in IE11 but not in Firefox), would warn us also when using `fetch` (supported 52 | in firefox but not in IE) and would not warn us when using `MutationObserver` because it is supported by both. 53 | 54 | This library is very powerful and popular, making relatively easy to integrate with a good amount of 55 | tools that already use it with low effort. 56 | 57 | This configuration must be made available to addons but it's up to the addon authors to take advantage 58 | of it. 59 | 60 | ### Browser support 61 | 62 | The configution of target browsers must be placed in a file that allows javascript execution and exports an object 63 | with the configuration. The reason to prefer a javascript file over a JSON one is to allow users to 64 | dinamically generate different config depending on things like the environment they are building the app in or 65 | any other environment variable. 66 | 67 | One possible location for this configuration is the `.ember-cli` file. 68 | A new dedicated named `/config/targets.js` also seems a good option, similar way how addons use `config/ember-try.js` 69 | to configure the test version matrix. 70 | 71 | Ember CLI will require this file when building the app and make the configuration available to addons 72 | in a `this.project.targets` property. 73 | 74 | This `targets` object contains a getter named `browsers` that returns the provided configuration or the default 75 | one if the user didn't provide any. 76 | 77 | Example usage: 78 | 79 | ```js 80 | module.exports = { 81 | name: 'ember-data', 82 | 83 | included(app) { 84 | this._super.included.apply(this, arguments); 85 | 86 | console.log(this.project.targets.browsers); // ['>2%', 'last 3 iOS versions', 'not ie <= 8'] 87 | } 88 | }; 89 | ``` 90 | 91 | This `targets` object can, and probably will, be expanded in the future with new properties 92 | for different kind of targets, like cordoba apps or fastboot, but that will be 93 | done in a different RFC. 94 | 95 | # How We Teach This 96 | 97 | This is a new concept in Ember CLI, so guides will have to be updated to explain this 98 | concept. The good part is that this new concept can help enforcing with tools a task were 99 | traditionally enforced only with peer reviews. 100 | 101 | To ease the transition Ember CLI can also, in the absence of a specific value provided by the user, 102 | default to a predefined matrix of browsers that matches the browsers officially supported by the framework. 103 | 104 | As of today, the supported browser list for Ember.js, according to the platforms we test in saucelabs, is: 105 | 106 | `['IE9', 'Chrome current', 'Safari current', 'Firefox current']` 107 | 108 | There is no mention to IOS/Android, so this must be validated still. 109 | 110 | # Drawbacks 111 | 112 | While this RFC standardizes a concept that will open the door to better and more comprehensive tooling, 113 | it makes us choose one syntax (the one used by [browserlist](https://github.com/ai/browserslist)) over 114 | any other perhaps superior choice that may exist or appear in the future. 115 | 116 | # Alternatives 117 | 118 | Let every addon that wants to deal with targets to have a `targets`-like option in its configuration 119 | instead of standardizing a single configuration option, which effectively leaves things as they are 120 | right now. 121 | 122 | Example: 123 | 124 | ``` 125 | var app = new EmberApp(defaults, { 126 | 'ember-cli-autoprefixer': { 127 | browsers: ... 128 | }, 129 | 'ember-cli-babel': { 130 | targets: ... 131 | }, 132 | 'ember-cli-eslint': { 133 | engines: ... 134 | }, 135 | ... 136 | }); 137 | ``` 138 | 139 | # Unresolved questions 140 | 141 | The proposed syntax for node only supports a single version of node. Is it reasonable to 142 | make this property an array of versions? P.e. `["4.4", "6", "7"]` 143 | -------------------------------------------------------------------------------- /complete/0096-enable-yarn-usage.md: -------------------------------------------------------------------------------- 1 | - Start Date: 2017-02-02 2 | - RFC PR: [#96](https://github.com/ember-cli/rfcs/pull/96) 3 | 4 | # Summary 5 | 6 | Enable Ember CLI users to opt into using yarn for packagement management. 7 | 8 | # Motivation 9 | 10 | Ember CLI currently uses the npm command line tool to install dependencies when you run `ember install` or `ember new`/`ember addon`. However, several problems usually arise from npm's semantics. 11 | Dependency resolution and install times can be significant enough to disrupt workflows, as well as offline support, non-deterministic, non-flat dependency graphs. 12 | 13 | Yarn was introduced to the JavaScript community with the intent to provide a better developer experience in these areas: 14 | - Faster installs 15 | - Offline support 16 | - Deterministic dependency graphs 17 | - Lockfile semantics 18 | 19 | While Ember CLI users can currently use Yarn to manage their dependencies, Ember CLI will use the npm client internally when running the above mentioned commands. By allowing users to specify that Ember CLI should use Yarn for everything, we're hoping to provide a more consistent experience. 20 | 21 | # Detailed design 22 | 23 | Enabling Yarn is designed as opt-in to prevent disruptions to the developer's current workflow. 24 | We will address the two moments where this can happen. 25 | 26 | ## `ember install` 27 | 28 | There are two mechanisms through which to opt-in. 29 | The first one is the presence of a `yarn.lock` file in the project root. 30 | 31 | The `yarn.lock` file is generated by Yarn when you run `yarn install` (or the shorter `yarn`), 32 | so we assume that its presence means the developer intends to use Yarn to manage their dependencies. 33 | 34 | Alternatively you, you can force Ember CLI to use Yarn with the `--yarn` flag, and symmetrically, 35 | you can force Ember CLI to not use Yarn with the `--no-yarn` flag. 36 | 37 | To recap: 38 | 39 | - `ember install ember-cli-mirage` with `yarn.lock` present will use Yarn 40 | - `ember install ember-cli-mirage` without `yarn.lock` present will use npm 41 | - `ember install ember-cli-mirage --yarn` will use Yarn 42 | - `ember install ember-cli-mirage --no-yarn` will use npm 43 | 44 | ## `ember init`, `ember new`, `ember addon` 45 | 46 | Since this triad of commands is generally ran before a project is set up, there is no `yarn.lock` file presence to check. 47 | This means we are left with the `--yarn`/`--no-yarn` pair of flags, that will also be added to these commands: 48 | 49 | - `ember new my-app` will use npm 50 | - `ember new my-app --yarn` will use Yarn 51 | 52 | The above also applies to `ember addon` and `ember init`, noting that `ember init` doesn't receive any arguments. 53 | 54 | # How We Teach This 55 | 56 | Both the Ember.js Guides as well as the Ember CLI Guides will be updated to reflect the new flags, 57 | as well as the new semantics of `ember install` in the presence of `yarn.lock`. 58 | 59 | In addition, the built-in instructions for `ember help` will be updated to reflect this. 60 | 61 | # Drawbacks 62 | 63 | To be determined. 64 | 65 | # Alternatives 66 | 67 | Do nothing. 68 | 69 | # Unresolved questions 70 | 71 | To be determined. 72 | --------------------------------------------------------------------------------