Skip to content
This repository has been archived by the owner on Jan 20, 2019. It is now read-only.

Make addons honour app's transpilation by default #89

Closed
wants to merge 10 commits into from

Conversation

cibernox
Copy link
Contributor

@cibernox cibernox commented Dec 7, 2016

some experimental ones.

What is less know is that this configuration only affects the application code. The transpilation
of code living in addons is done according to the configuration of those addons. While there is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be specific: the app config affects the transpilation of everything inside app/, even those app/ folders inside of addons!

# Detailed design

The idea is to still allow addons to be in control of their own transpilation process, but
make them honour uses preferenced by default.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: user preferences


# Motivation

Ember-cli as allowed users to write ES6 code and transpile it to ES5/3 since almost the beginning
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either ember-cli or Ember CLI

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also as -> has


By example, an addon that uses `async-await` which right now are only available in Chrome Canary
could either use the host app's configuration plus this feature or it could just assume the user
has enabled it and tell them to do so in the docs.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or it could use a blueprint that adjusts the Babel settings for the user

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this approach, I think. The addon shouldn't require anything here, it should possibly specify which features it needs support for, and then get venn diagram processing.

Maybe it's cooperative? The root application specifies what its target is, the child addons specify how to achieve that goal?


None that I can think of, beside of not doing this.

# Unresolved questions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we would also have to figure out how Babel resolves plugins. normally they are referenced by name and loaded relative to the Babel package itself, which can be a problem when e.g. ember-cli-babel is npm linked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently plugins can also be just required and passed to Babel.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is somewhat correct, yes. this does not work inside of a .babelrc file though which is JSON-based.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that the app should parse its .babelrc file and convert it to a JS object. This object is the one that gets deepcloned and passed to addons so they can manipulate it.

I think that for addons that need to mangle the transpilation the .babelrc manifest is not expresive enough.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note: this RFC does not suggest migration to .babelrc

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwjblue I know, but I'd like us to be aware of that option. We shouldn't build anything that blocks our way of using those files if we want to.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Turbo87 - Ya, I completely agree. I wasn't very clear either, I think the RFC should address (or at least mention) .babelrc and other concepts that we are required to chart through on our road to babel@6 (see other comment in #89 (comment)).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as reference there is a PR to add a .js to babelrc babel/babel#4892

create-react-app and others do a require.resolve: https://github.com/facebookincubator/create-react-app/blob/ab3913cc113b2392fa0329f699571bae3c213308/packages/babel-preset-react-app/index.js#L15

Copy link
Member

@rwjblue rwjblue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this, well done!

Today that is done through `ember-cli-babel`, an addon that is in the default blueprint and
that the huge majority of apps use.

This transpilation process has some sensitive defaults that work for most people, but also allow
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/sensitive/sensible/ (I think)


# Motivation

Ember-cli as allowed users to write ES6 code and transpile it to ES5/3 since almost the beginning
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ember-cli has

some use configuration for, by example, disable some transformations enabled by default or enable
some experimental ones.

What is less know is that this configuration only affects the application code. The transpilation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/know/known/


# Detailed design

The idea is to still allow addons to be in control of their own transpilation process, but
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight tweak suggested here:

The idea is to still have addons control their own transpilation process, but

The idea is to still allow addons to be in control of their own transpilation process, but
make them honour uses preferenced by default.

There is three different scenarios for addons:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/is/are/


This has no impact for apps, just for addons.

Most addons will not require any change. Only those that want to modify this the transpilation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not actually see how ember-computed-decorators needs to be changed at all to support this. If you read through the recommended snippet here:

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

    this.options = this.options || {};
    this.options.babel = this.options.babel || {};
    this.options.babel.optional = this.options.babel.optional || [];

    if (this.options.babel.optional.indexOf('es7.decorators') === -1) {
      this.options.babel.optional.push('es7.decorators');
    }
  }

You will notice that it already honors any this.options.babel settings that are present.


#### How can addons be in charge of their own transpilation and yet honor user preferences?

Ember-cli should provide to each addon a deep clone of the configuration defined in the host app
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must address how to do this properly with the upcoming babel@5 -> babel@6 transition. It is possible that this RFC would be blocked on that transition being completed, or only take effect when both app and individual addons are using babel@6.

This needs more thought/design, but I think it is doable...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the idea of deep-cloning the host's app and use that is universal, whatever version of babel we use.

There is an obvious problem if the app uses babel6 and the addon expects babel5, because the options are not compatible between them, but seems a problem of the babel upgrade more than a problem of this RFC per se.

I think that that want to customize the transpilation will have to support both babels at least for a while.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an obvious problem if the app uses babel6 and the addon expects babel5, because the options are not compatible between them, but seems a problem of the babel upgrade more than a problem of this RFC per se.

@cibernox - Right, I totally agree with your assessment here. However, I am willing to completely block this RFC so that we can focus on the babel@6 upgrade if this will make that migration more complicated. If we want to ship this sooner, we need to at least address how it doesn't make matters worse (via some sort of mitigation as I suggested above).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to get to Babel6 first and then land this RFC regardless of any design that demonstrates painlessness. I simply think it's a cleaner migration path less likely to leave skeletons behind.

@Turbo87
Copy link
Member

Turbo87 commented Dec 7, 2016

one thing to keep in mind when thinking about this RFC is https://github.com/babel/babel-preset-env, which I would like to eventually adopt as the default for Babel transpilation in Ember CLI.

Copy link
Contributor

@nathanhammond nathanhammond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finishing this review since it got updated out from under me.


# Motivation

Ember-cli as allowed users to write ES6 code and transpile it to ES5/3 since almost the beginning
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ember CLI

of the project. It's one of those things that people take for granted.

Today that is done through `ember-cli-babel`, an addon that is in the default blueprint and
that the huge majority of apps use.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apps and addons

Today that is done through `ember-cli-babel`, an addon that is in the default blueprint and
that the huge majority of apps use.

This transpilation process has some sensitive defaults that work for most people, but also allow
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/sensitive/sensible

that the huge majority of apps use.

This transpilation process has some sensitive defaults that work for most people, but also allow
some use configuration for, by example, disable some transformations enabled by default or enable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- , by example, disable
+ disabling

- enable
+ enabling

some use configuration for, by example, disable some transformations enabled by default or enable
some experimental ones.

What is less know is that this configuration only affects the application code. The transpilation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/know/known/

some experimental ones.

What is less know is that this configuration only affects the application code. The transpilation
of code living in addons is done according to the configuration of those addons. While there is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/there is/there are

#### The addon doesn't care about the transpilation process.
This is the most common common situation. Most addons are authored in ES6 and they don't
mess with the host app's configuration.
Those addons should just transpile their code user the host's apps settings.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/user/using/, s/host/root/


By example, an addon that uses `async-await` which right now are only available in Chrome Canary
could either use the host app's configuration plus this feature or it could just assume the user
has enabled it and tell them to do so in the docs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer this approach, I think. The addon shouldn't require anything here, it should possibly specify which features it needs support for, and then get venn diagram processing.

Maybe it's cooperative? The root application specifies what its target is, the child addons specify how to achieve that goal?


#### How can addons be in charge of their own transpilation and yet honor user preferences?

Ember-cli should provide to each addon a deep clone of the configuration defined in the host app
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to get to Babel6 first and then land this RFC regardless of any design that demonstrates painlessness. I simply think it's a cleaner migration path less likely to leave skeletons behind.

custom plugins, enable specific features or just throw a warning message if the app's config
doesn't have required specific transformation enabled.

By modifying this clone, their changes will not affect the host app or other addons.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's theoretically possible that the config defines functions that have scopes and side effects such that the clone isn't valid. We could use vue's global proxy pattern: http://www.2ality.com/2016/11/trace-globals-proxy.html

For this approach it doesn't matter if the version of babel is 5 or 6, however the plugins and their
names are funamentally incompatible.

- Should addons that depend on `ember-cli-babel` be compiled with their version or with the app's version?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer we only allow this behavior with homogenous versions. If you're not all Babel6 you get current behavior.

Copy link
Contributor

@stefanpenner stefanpenner Dec 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure.

Allowing the system to progressively transition has its benefits. For example, as add-ons upgrade more and more of the users code-gen would no longer need to cater to the lowest common denominator (ES3).

The downside to this, is you may have some ES3 safe code, mixed with your ES6 safe code. Which seems ok.

This would allow our users to see incremental progress. Especially if the most popular / largest add-ons (like ember-data or even ember) made the change more quickly.

The alternative, requiring homogenous setup. Requires the entire universe to transition before progress is seen.

I suspect coupling incremental + a Quest issue, would enable the best outcomes. (e.g. incremental rewards for our community)

@nathanhammond
Copy link
Contributor

I think I want this to be cooperative. The addon knows which features it is using, the root application knows what its target is (ES3, ES6, whatever). If the transpilation target is understood then the addon should know what it needs to do to get there, starting by building on top of the root application's configuration settings. Which plugins it uses to get there do not communicate exactly what the target is, it specifies only a blacklist (and is thus incomplete).

Moving to this model fits very well with our Broccoli build model where addons are able to build themselves based upon a known target. If we're trying to make the addon guess what to do it will likely always opt for ES3 for max compatibility (I would).

@nathanhammond
Copy link
Contributor

This concern is partially alleviated by adopting something like https://github.com/babel/babel-preset-env which @Turbo87 linked us to. If the root app specifies this then the addon knows "what" instead of "how." "How" is simply not enough information to do the right thing 100% of the time.

We should probably encourage adoption of this in root level apps.

/cc @hzoo

@cibernox
Copy link
Contributor Author

cibernox commented Dec 7, 2016

@nathanhammond The idea of the app declaring intentions and the addon reacting to those intentions based on the knowledge of the features it uses seems hard.

The app will express is intentions in targets (p.e. lastest 2 versions of current active browsers), but addons might express their needs in features (p.e. async/await).

I'm not sure how to make them understand each other in a way that it's not madness.

@cibernox cibernox changed the title Allow apps to control addon's transpilation Make addons honour app's transpilation by default Dec 12, 2016
Copy link
Contributor

@stefanpenner stefanpenner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good direction for us to take.

Question:

  • Do we need to concern ourselves with "what happens" when an APP and and Addon have incompatible compilation preferences?


By example, applications that only target evergreen browsers may want to disable transpilation of
all ES6 feature since moden browsers already ship them.
With ES6 being fully implemented in all modern browsers and many ES2016/ES2017 already starting to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, for this reason. This is quite important to land.

@cibernox
Copy link
Contributor Author

Do we need to concern ourselves with "what happens" when an APP and and Addon have incompatible compilation preferences?

I'd say we don't. The only incompatibility I can think about is an addon enforcing the transpilation of something the user doesn't want to transpile. I think the addon config always win, although I would consider that addon a bad boy for not obeying its parent. But it's not worse than what we have already.

If we are talking about the app providing babel6 config and the addon expecting babel5 config, that is a harder question, but I think that the answer belongs more to the Babel5 -> 6 upgrade rather than this RFC.

Can some addons be transpiled by babel5 and other by babel6? /cc @Turbo87

@Turbo87
Copy link
Member

Turbo87 commented Dec 12, 2016

Can some addons be transpiled by babel5 and other by babel6?

That was the original plan and it would be very beneficial in the transition period. Otherwise you end up in a situation where some addons only work with older Babel and some only with Babel 6 and you'd have to choose between them...

@stefanpenner
Copy link
Contributor

stefanpenner commented Dec 12, 2016

@cibernox and myself had a quick call:

Summary (from @cibernox's #ember-cli-dev summary of the call):

[8:41 AM]  
the outcome of the hangout is that giving too much power to users for very little benefit can make transitions harder so the idea would be:
1. Make `babel-preset-env` be part of the babel6 upgrade
2. Just provide addons with the `preset` configuration of the parent app, which typically consist on only a list of target browsers, expressed as `chrome latest` or `> 2%`

[8:42]  
I agree on that, I need to check if this still allows users to plug their own transformations, like ember-data does (edited)

[8:43]  
if so, the RFC could pivot towards "Make `babel-preset-env` a default and make addons obey that by default"

@hzoo
Copy link

hzoo commented Dec 12, 2016

babel-preset-env only covers preset-latest (no experimental plugins) so it would be the best default behavior but yeah output depends on browser support

@cibernox
Copy link
Contributor Author

@hzoo now that you're here, one of the open point to discussion of this RFC is how addons get access to the babeljs configuration. Addons must be able to customize how they transpile, by example to add their own plugins that perform things like remove intrumentation in production builds and things like that or enable experimental ones if they use stuff that is not yet in the specs, enable loose mode for perf reasons and such.

At the same time, we want to give to the addon the least amount of configuration possible to do their job. @stefanpenner suggested that they should get only the configuration for env.

By example, if the configuration in a project is

{
  "presets": [
    ["env", {
      "targets": { "chrome": 52 },
      "modules": false,
      "loose": true
    }]
  ]
}

The addon would only have access to:

{
  "targets": { "chrome": 52 },
  "modules": false,
  "loose": true
}

Users can add their own custom transformations having access to just this bit of the configuration?

@hzoo
Copy link

hzoo commented Dec 12, 2016

preset-env itself doesn't include custom transforms so you would have to allow them to append to the preset/plugins array at the top level of the config then? preset-env would only be able to whitelist/blacklist plugins already included if we add those options.

@cibernox
Copy link
Contributor Author

So, the configuration of a project with custom plugins looks like this:

{
  "presets": [
    ["env", {
      "targets": { "chrome": 52 },
      "modules": false,
      "loose": true
    }]
  ],
  "plugins": ["plugin1", "plugin2", require('./lib/my-plugin')]
}

@stefanpenner that makes me think that we might need to pass the configuration pristine to the addons, or alternatively provide a hook/object that gives the user access to only the env entry and the plugins array.

@cibernox
Copy link
Contributor Author

@rwjblue After ember-cli-babel exists beta, this RFC is essentially implemented, right?

@rwjblue
Copy link
Member

rwjblue commented Mar 13, 2017

yes, but not the specific API's suggested IIRC

@rwjblue
Copy link
Member

rwjblue commented Apr 19, 2017

@cibernox - I think we can close this one, can you confirm (or update to reflect the current state of things)?

@cibernox
Copy link
Contributor Author

cibernox commented Apr 19, 2017

@rwjblue Can you confirm that addons that use babel6 inside babel6 applications with targets also use those targets? That is the only bit I'm not sure if it's implemented.

@cibernox
Copy link
Contributor Author

As of ember-cli-babel@6.0.0, this RFC has been implemented. In a few days will be released in the stable channel.

@cibernox cibernox closed this Apr 21, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants