Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rule to disallow this.$ to prepare apps to remove jQuery #121

Merged
merged 6 commits into from
Sep 1, 2017

Conversation

cibernox
Copy link
Contributor

@cibernox cibernox commented Aug 4, 2017

In modern browsers jQuery is less and less needed as many features are not built in
into modern browsers and the bugs that jQuery used to help you avoid have been fixed.
However, jQuery still adds ~30KB (min + gzip) to every Ember app, which can add up to
1 second of download + parse times on mobile devices. Is is now possible to remove
jQuery from Ember apps, and one of the main features in Ember that cannot be used on
an app that intends to remove jQuery in a near future is this.$, either inside
component's methods or within tests.

This PR adds a rule, that is entirely optional and I do not think it should
be enabled by default to yell at anyone who uses this.$.

Please let me know what else has to be done (documentation, etc...) to make
this mergeable.

@kevinkucharczyk
Copy link
Contributor

Thank you for the PR @cibernox! Personally I think this is a fantastic idea and definitely a step in the right direction. I also agree on not making the rule enabled by default, since it would break a lot of apps.
You should add a documentation file for this rule under docs/rules and finally run yarn run update to automatically update the repo's readme with your new rule. There's a short contribution guide in the readme here: https://github.com/ember-cli/eslint-plugin-ember#-contribution-guide

README.md Outdated

| | Rule ID | Description |
|:---|:--------|:------------|
| | [no-this-jquery](./docs/rules/no-this-jquery.md) | Disallow use of `this.# eslint-plugin-ember
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems that the script doesn't like this.$ 🤔

@cibernox
Copy link
Contributor Author

cibernox commented Aug 7, 2017

I added docs and regenerated the readme, but I think there is too many changes.

@cibernox cibernox mentioned this pull request Aug 7, 2017
@cibernox
Copy link
Contributor Author

cibernox commented Aug 7, 2017

After some conversation, this rule is going to be edited to be no-jquery and y must forbid several things.

Tasks:

  • Disallow this.$
  • Disallow global jQuery.
  • Disallow import whatever from 'jquery';
  • Disallow Ember.$
  • Disallow const { $ } = Ember;
  • Rename rule to no-jquery or similar
  • Regenerate docs

@cibernox
Copy link
Contributor Author

cibernox commented Aug 8, 2017

I've updated the PR to be a no-jquery, which covers pretty much any reasonable usage of jQuery.

README.md Outdated

| | Rule ID | Description |
|:---|:--------|:------------|
| | [no-jquery](./docs/rules/no-jquery.md) | Disallow use of `this.# eslint-plugin-ember
Copy link
Member

Choose a reason for hiding this comment

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

this.# should be this.$ (and there is a missing backtick)

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 know, but this is autogenerated. If we don't fix the error in the generator the next one in running the script will ruin this again.

Copy link
Member

Choose a reason for hiding this comment

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

Gotcha! I didn't realize it was auto-generated, sorry 😸

Copy link
Member

Choose a reason for hiding this comment

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

We should make sure to create an issue for that (so we can track down the bug).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On it

Copy link
Collaborator

Choose a reason for hiding this comment

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

👍

@lynchbomb
Copy link

@cibernox
Copy link
Contributor Author

cibernox commented Aug 9, 2017

@lynchbomb I believe that I've covered all that. Do you see anything not covered?

Copy link
Member

@michalsnik michalsnik left a comment

Choose a reason for hiding this comment

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

Please set additionally in no-global-jquery's meta docs:

replacedBy: 'no-jquery',
deprecated: true

I'll add extra list with replaced rules in readme later.

module.exports = {
meta: {
docs: {
description: 'Disallow use of `this.$` on components or tests',
Copy link
Member

Choose a reason for hiding this comment

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

You should update description of the rule, as now it disallows any jQuery usage. When you'll do this, please revert readme and execute npm run update once again.

},

MemberExpression(node) {
if ((node.object.name === 'Ember' || node.object.name === 'Em' || (emberImportAliasName && node.object.name === emberImportAliasName)) && node.property.name === '$') {
Copy link
Member

Choose a reason for hiding this comment

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

Please wrap this line to make it more readable

context.report(node, message);
}

if (isThisJquery(node)) {
Copy link
Member

Choose a reason for hiding this comment

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

I'm fine with this, however just to let you know you could also use eslint selectors:

'CallExpression > MemberExpression > ThisExpression' (node) {
		if (node.parent.property.name === '$') {
      // busted
     }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TIL. I'm pretty new to ESLint rules, but this is neat 👌


MemberExpression(node) {
if ((node.object.name === 'Ember' || node.object.name === 'Em' || (emberImportAliasName && node.object.name === emberImportAliasName)) && node.property.name === '$') {
report(node, message);
Copy link
Member

Choose a reason for hiding this comment

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

This function doesn't expect second argument. Anyway you should either use report function everywhere or context.report

}

if (isThisJquery(node)) {
report(node, specialisedMessageForThisJquery);
Copy link
Member

Choose a reason for hiding this comment

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

As I wrote above report doesn't seem to accept the second argument.

}]
},
{
code: `
Copy link
Member

Choose a reason for hiding this comment

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

Just to make this test case complete, please add filename field with real path including tests/

@cibernox
Copy link
Contributor Author

@michalsnik I've applied the feedback

@scalvert
Copy link
Collaborator

This seems good if we're extending no-global-jquery. I'm all for consolidating in this rule.

The intent of no-global-jquery was to ensure that people were using Ember.$|Ember.jQuery vs. global $|jQuery. IMO the rules are different, even though they overlap.

Perhaps we should instead keep them distinct?

@michalsnik
Copy link
Member

Having two rules that overlaps might be a bit strange @scalvert. On the other hand that could be intentional. Perhaps if we recommend one rule over another in recommended configuration they could live alongside each other 🤔 WDYT @cibernox @Turbo87 ? I'm ok with both approaches to be honest..

@cibernox
Copy link
Contributor Author

@michalsnik As part of this PR, requested on the code review, I've marked the no-global-jquery rule as deprecated and replaced by this one, so your suggestion is already done.

I wouldn't oppose to allow both to coexist. This one is a superset of the other one, so there is no point in enabling the other one if this one is, but I think it's just a matter of documenting in the readme how both rules are different and people can decide which one they want to enable.

@michalsnik
Copy link
Member

Yeah that was my recommendation if we were to remove the other rule in the next major release. But if we decide to leave it than my recommendation was wrong and we should keep both rules, but only of them marked as recommended - the new one. But given the fact that any change to recommended setting is a breaking change we would change our recommendations in the next major release (+/- 2 weeks) and for now keep it as is (recommended: false). That would also give us enough time to see how the new rule works in real projects.

Sorry for the confusion @cibernox. But I thought this through once more after last comment from @scalvert and I'd remove:

replacedBy: 'no-jquery',
deprecated: true

which I proposed before. We're probably not going to deprecate this rule, as in old living projects removing jQuery could be a truly daunting task, but making sure that it doesn't use global jquery would be a quick win, small step towards better code base. With this in mind removing no-global-jquery would not be so smart move.

@Turbo87
Copy link
Member

Turbo87 commented Aug 16, 2017

@michalsnik again I strongly advise against yet another major release in the near future. It will create a lot of unnecessary churn and IMHO we should wait a few months until things have settled down a bit.

In modern browsers jQuery is less and less needed as many features are not built in
into modern browsers and the bugs that jQuery used to help you avoid have been fixed.
However, jQuery still adds ~30KB (min + gzip) to every Ember app, which can add up to
1 second of download + parse times on mobile devices. Is is not possible to remove
jQuery from Ember apps, and one of the main features in Ember that cannot be used on
an app that intends to remove jQuery in a near future is `this.$`, either inside
component's methods or within tests.

This PR adds a rule, that is entirely options and **I do not think** it should
be enabled by default to yell at anyone who uses `this.$`.

Please let me know what else has to be done (documentation, etc...) to make
this mergeable.
@cibernox
Copy link
Contributor Author

@michalsnik I've removed those options so both rules coexist. Also since I've changed the description of the rule, #127 doesn't affect the new docs.

Copy link
Member

@michalsnik michalsnik left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@cibernox
Copy link
Contributor Author

Can we merge?

@michalsnik michalsnik merged commit 4dcc3f0 into ember-cli:master Sep 1, 2017
@michalsnik
Copy link
Member

Thanks @cibernox ! Released in v4.5.0 🎉

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

Successfully merging this pull request may close these issues.

7 participants