-
Notifications
You must be signed in to change notification settings - Fork 61
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
Remove newly unreferenced VariableDeclarators #146
Remove newly unreferenced VariableDeclarators #146
Conversation
7c9e2f0
to
d048465
Compare
@lencioni Thanks for the failing test case. It comes down to this plugin only removing the reference between the React component and the prop types, deferring potential dead code elimination to another tool. |
Yeah, I think that's a pretty accurate assessment. If I put up a PR that addresses this, would you be open to getting it merged in and published? |
@lencioni It might increase the time this plugin takes, but nobody is benchmarking that, so we are good. As for the potential bug it might introduce, I have trust in you, so yes, I'm more than happy to review such work! |
@oliviertassinari Sounds great! Before I begin working on an implementation, do you think the test cases I've added here are adequate? Or are there more cases we want to test against? |
Maybe one more with an export of the proptypes? I can't think of anything else. |
db98c38
to
990c22a
Compare
@oliviertassinari I've updated this PR with a solution that passes all tests. I've never really worked with Babel plugins before, so it is likely that I've made some weird decisions. I'd love your feedback on this! |
990c22a
to
9001851
Compare
As a sanity check, I ran this on our large internal component library project and it seems to be doing the right thing. |
|
||
if ( | ||
path.parent.type === 'ObjectProperty' && | ||
(path.parent.key === path.node || path.parent.shorthand) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to check if path.parent.computed
?
{ [computedKey]: 'foo' }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I think we still want identifiers in computed object keys, since by removing the object we may no longer need the identifier used in the computed key and we will want to clean those up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I think we might not actually need the next check for CallExpressions. I'll remove that now.
src/index.js
Outdated
return | ||
} | ||
|
||
if (path.parent.type === 'CallExpression' && path.parent.callee === path.node) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't actually need this check. I don't actually remember why I added it in the first place.
I've noticed that a common pattern used to assign propTypes--first define a variable for the propTypes, and then assign it to the component by reference--ends up deoptimizing this plugin, which leads to larger bundles in production than desired. The original hypothesis that minification would clean up these dead references works well for the simplest of propTypes, but unfortunately it doesn't hold up as soon as you have a function call in the propTypes variable (such as is the case for propTypes like `arrayOf`, `objectOf`, `shape`, etc.) because the minfier does not know that the function call will not have side-effects: ```js const propTypes = { foo: PropTypes.arrayOf(PropTypes.number), }; ``` I believe this should be solved by this plugin because we can make the assumption that function calls inside of propTypes have no side-effects. There seems to be a weird issue where the transform adds a semicolon when using in wrapped mode. For now, I decided to simply add the additional semicolons in the test fixtures, since they will be minified out anyway. I don't have much experience working with Babel plugins yet, so it is likely that I'm doing things in a weird or sub-optimal way here.
9001851
to
07b667c
Compare
@oliviertassinari are there any changes you want me to make to this PR? |
@lencioni Thank you for your time! No, I need to find some to review the pull request :) |
Great PR or greatest PR? This is fabulous. +1000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any tests to cover React.createClass
/create-react-class
?
src/index.js
Outdated
@@ -53,9 +53,39 @@ function isReactClass(superClass, scope, globalOptions) { | |||
return answer | |||
} | |||
|
|||
function areSetsEqual(set1, set2) { | |||
if (set1.size !== set2.size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even tho it doesn't matter for this use case, i'd probably add an additional bailout; if (set1 === set2) { return true; }
:-)
@@ -1,8 +1,8 @@ | |||
"use strict"; | |||
|
|||
var propTypes = { | |||
var propTypes = process.env.NODE_ENV !== "production" ? { | |||
foo: PropTypes.string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add some tests for get bar() { return PropTypes.string; }
and similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, it'd be good to ensure that this doesn't crash:
var propTypes = {
...({ foo: PropTypes.string }),
};
foo: PropTypes.string | ||
}; | ||
} : {};; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are the double semicolons intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There seems to be a weird issue where the transform adds a semicolon
when using in wrapped mode. For now, I decided to simply add the
additional semicolons in the test fixtures, since they will be minified
out anyway.
If you know why they are there, I'd love to fix!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh oops, missed that.
i don't know why; not that big a deal ofc.
foo: PropTypes.string | ||
}; | ||
} : {};; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also here
bar: PropTypes.string | ||
}; | ||
|
||
const propTypesWithExtraReference = Object.assign({}, extraReference, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an object spread example could be good alongside this
Although this probably doesn't matter for our use-case, it is more complete.
This gives us more assurance that this code is working as expected.
I'm not entirely sure if this is the desired result, but I think it maybe is, since anything could be using the getter.
@ljharb Thanks for the review! I've added some tests. |
@oliviertassinari If you are too busy to work on this, I'd be happy to merge this and publish a new version of the plugin for you if you want. |
@lencioni I would love that. Let me send the needed invitation. Thanks. |
My npm username is |
@oliviertassinari thanks for the permissions on this repo! I've merged this change and once you give me publish access on npm, I can get a new release out. https://www.npmjs.com/package/babel-plugin-transform-react-remove-prop-types |
@lencioni You should already have the access. |
The website pages are cached and take awhile to update; try |
The |
I can't wait to try it out 🎉 ! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought of this later
export default function(api) { | ||
const { template, types, traverse } = api | ||
|
||
const nestedIdentifiers = new Set() | ||
const removedPaths = new Set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this contains objects, and is never traversed, so it probably should be a WeakSet
I've noticed that a common pattern used to assign propTypes--first
define a variable for the propTypes, and then assign it to the component
by reference--ends up deoptimizing this plugin, which leads to larger
bundles in production than desired. The original hypothesis that
minification would clean up these dead references works well for the
simplest of propTypes, but unfortunately it doesn't hold up as
soon as you have a function call in the propTypes variable (such as is
the case for propTypes like
arrayOf
,objectOf
,shape
, etc.)because the minfier does not know that the function call will not have
side-effects:
I believe this should be solved by this plugin because we can make the
assumption that function calls inside of propTypes have no side-effects.
There seems to be a weird issue where the transform adds a semicolon
when using in wrapped mode. For now, I decided to simply add the
additional semicolons in the test fixtures, since they will be minified
out anyway.
I don't have much experience working with Babel plugins yet, so it is
likely that I'm doing things in a weird or sub-optimal way here.
Fixes #145