-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
perf(props): Remove propTypes from production build #731
Conversation
cf01fab
to
2451875
Compare
I think this could work, although I'm not too excited about What about this:
I'm still not 100% sure what the const propValues = {
close: ['very'],
position: SUI.FLOATS,
size: _.without(SUI.SIZES, 'medium'),
}
Rail.propTypes = {
// snip ...
/** A rail can be presented on the left or right side of a container. */
position: PropTypes.oneOf(propValues.position).isRequired,
} Or we could just inline them: Rail.propTypes = {
// snip ...
/** A rail can be presented on the left or right side of a container. */
position: PropTypes.oneOf(SUI.FLOATS).isRequired,
} |
babel-plugin-transform-react-remove-prop-typesI love this plugin, however, I don't think we can remove the propTypes in any of our builds since the user needs to have them in dev. If we strip them, then only we'll have them in dev. We need to only remove them when the user builds for production. It is worth noting however that this plugin has a
|
8c99c72
to
a54be2c
Compare
What's doneI've added some perf plugins:
|
List of propsSeems, babel plugin is good idea, I suggested it at the beginning of discussion, it can make code cleaner. I can start on it after What it must do?Collect values of:
And ands it to |
@layershifter - Adds it as |
I started to work on babel-plugin. |
Great, can't wait to see this one come to life! |
@levithomason Hey, plugin was completed, take a look here. I've implemented cases for stateless and statefull component. Seems, we need plugin's code to this PR. Where I can store plugin? I'm thinking about |
Exactly what I was thinking 👍 EDIT It would be nice to also include the README.md for it in the |
I was just informed by @davezuko that we can use babel-plugin-lodash directly with our project if we structure it in a friendly format on publish. We just then need to set the |
@layershifter @levithomason - thoughts on making this babel plugin slightly more generic and possibly either shipping it separately or at least making it usable outside this project? I've come across a few places in my app where I've wanted to use the pattern of consuming props and passing the rest through but don't want to rely on Instead of (SUI-react specific): Component._meta = {
props: ['children', 'className']
} it could output (more general): Component.handledProps = ['children', 'className'] Could name it |
@levithomason I've imported code to this PR.
close: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['very']),
]), |
@levithomason Any response? 😢 |
Whoops, just got done doing a maintenance sweep but overlooked this one :/ Sorry! I try to hit all unread issues/PRs and anything labeled "Ready For Review" each time I do a maintenance sweep. I may not be available the rest of today but will get to this in the next sweep. I'll add the label so as not to miss it again. |
I tried this in my project and wanted to report back. I analyzed my webpack-bundled files using https://github.com/th0r/webpack-bundle-analyzer (super cool tool, btw!). Here's the before/after (I think "parsed size" is post-minification, "stat size" is all the file sizes summed): Usage is just: webpackConfig.module.loaders.push({
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'babel',
query: {
// ... snip
plugins: [
// ... snip
'lodash', // Run module cherry-picker on lodash
['lodash', { 'id': 'semantic-ui-react' }] // Run module cherry-picker on semantic-ui-react
],
// ... snip Not bad for one line of config 😁 . Will be cool to see how much further this number drops once this PR makes it in 👍 |
Awesome, I also have a branch in progress that generates alias files for all components, so we can: import Button from 'semantic-ui-react/Button' @jcarbo I'm actually curios how that worked without that PR... Did you manually add index files for it?
I think this is a great idea. |
@levithomason - I only added that one config line, no other code. The code in
I think it will do the following conversion: // from
import { Button } from 'semantic-ui-react'
// to
import Button from 'semantic-ui-react/dist/commonjs/elements/Button'` |
Result of lodash plugin looks awesome 👍 @levithomason So what we do with plugin? After @jcarbo offer I think we need to do this:
close: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.oneOf(['very']),
]), |
@layershifter - that sounds good to me! I think inlining the options is the cleanest way to do it. In most cases, those will be constants so I think it will actually read pretty clearly (e.g. @levithomason - thoughts? |
I agree on all counts here. Let's do it. |
@davezuko what needs to be emitted there? I am emitting 'development' if I'm in development build, otherwise I leave it empty. [EDIT] I am actually emitting 'production'
[EDIT2] The production veriable is specified correctly and code removal is ok, as I am eliminating in the same way mobx-react-devtools. This is the size I am seeing now. It is the same as during development build: |
@tomitrescak that's exactly what I meant, and it was just a guess at that, so perhaps I'm on the wrong track. I just casually saw this issue and figured I'd inject a thought, but I'll keep thinking on it. As an aside, I'm curious about that snippet you posted. I'm fairly certain that, at least at some point, that was not valid code for the define plugin due to how it injected globals; you'd actually have to stringify // without stringifying (NODE_ENV: 'production')
if (process.env.NODE_ENV === 'production') // before compile
if (production === 'production') // after compile, ERROR! production is not defined
// vs (NODE_ENV: JSON.stringify('production') [or just '"production"']).
if (process.env.NODE_ENV === 'production') // before compile
if ("production" === 'production') // after compile, no error This is a whole 'nother tangent, and you'd likely have already encountered this problem in previous builds. I could be totally off base here, but it's all I can think of at the moment. Aside #2: Does webpack inject this global into non-webpacked packages? Meaning, you import SUIR, but webpack simply imports it, but does not transform it in any way (i.e. with babel and the lot), so perhaps it is not stripping out that code? Yes, |
@davezuko that's exactly how I had it with JSON.stringify, I just changed it for this example. I think it's just BundleAnalyser acting up. When I go the minified source code of semantic-ui-react the PropTypes are missing (in dev build they are there), yet BundleAnalyser reports exactly the same size. [EDIT] An it's most probably true:
|
Yep, it makes this.
We used const names = [] // long array
function Flag (props) {}
Flag._meta = {
// something there
props: {
name: names
}
} Yes,
Yep, I'm working on it, for example, Before
After:
As soon as I can. Lowering bundle size is my priority in this time. |
We'll likely lose some definitions in this file and it will become drastically smaller since things like |
For details - #524
This PR might to do:
getUnhandledProps
function;ComponentProps
component in docs (we can't rely onmeta
anymore).@levithomason I've updated
Rail
component, waiting for review there.