-
Notifications
You must be signed in to change notification settings - Fork 4.1k
RFC: remove production propTypes, allow small custom builds #524
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
Comments
Agreed on both concerns. Removing propTypes in production and allowing smaller builds. Here are my thoughts. propTypesThere are transforms to remove propTypes in production builds, however, we're currently using them in Unused ComponentsIn the optimization phase (after getting the bulk of work completed) I plan to publish individual components. This way users can just install what they need. We should also consider structuring our primary published project to users can do something similar to: import Button from 'stardust/Button' If we did this, we could also provide a babel plugin like lodash has done with babel-plugin-lodash. It looks at usages of lodash and transforms the imports to only import what you use, drastically reducing build size. We use it on the doc site. |
propTypesThere are no change that we can remove I'm thinking about Babel plugin that will run following transform: Component.propTypes = {
className: PropTypes.string,
content: PropTypes.string,
header: customPropTypes.every(),
icon: customPropTypes.every()
}
Component.handledProps = ['className', 'content', 'header', 'icon'] So, we can modify if(process.env.NODE_ENV === 'production') {
const handledProps = Component.handledProps
} else {
const handledProps = _.union(
Component.autoControlledProps,
_.keys(Component.defaultProps),
_.keys(Component.propTypes),
)
} That might be splited on build to: const handledProps = Component.handledProps Thoughts? |
If we added this, I think we should use https://nkt.github.io/babel-plugin-react-remove-prop-types. This package strips them entirely. In that case, I think we should update I know it would be more code to write, however, the current function is weak in that it has external dependencies and makes assumptions about those dependencies. Currently, it takes in a Component and checks for 3 different props definitions. That would be replaced by a single hard coded array. This would make it faster, more reliable/reusable, and we could use the community leader for removing propTypes. Thoughts? |
We also need to remove the index files from each component "type" folder. Otherwise, we'll automatically bundle extra components. See https://github.com/TechnologyAdvice/stardust/pull/570#discussion_r81445116. Lastly, the common tests for exported components needs updated. The failure message instructs users to export their components in those index files. Once we remove them, that message is no longer valid. It should instead instruct users to export their components in the main index file. |
Do you guys see anything wrong with doing this in a lib/stardust file in our project? export { default as Button } from 'stardust/dist/commonjs/elements/Button/Button'; Then when required, we can just do import { Button } from 'lib/stardust'; This works for our needs but I wasn't sure if there were any issues we might encounter doing this (other than breaking changes as you guys make updates)? |
PropTypesAs we decided in #684:
I've sketched some code there, if we approve it I'll open new PR for this. Stateless componentfunction SUIComponent () {}
SUIComponent._meta = {
// ...
props: [
'as',
'children',
'size',
// etc.
]
}
if (process.env.NODE_ENV !== 'production') {
SUIComponent.propValues = {
size: SUI.SIZES,
}
SUIComponent.propTypes = {
as: customProptypes.as,
size: PropTypes.oneOf(SUIComponent.propValues.size),
}
}
|
To leave room for future expansion of our prop definition (component explorer), we can use an object for each prop. I've also renamed it from function SUIComponent() {}
SUIComponent._meta = {
props: ['as', 'children', 'size']
}
if (process.env.NODE_ENV !== 'production') {
SUIComponent.props = {
size: {
values: SUI.SIZES,
},
}
SUIComponent.propTypes = {
as: customProptypes.as,
size: PropTypes.oneOf(SUIComponent.props.size.values),
}
} It is worth noting that we'll need to pull class SUIComponent extends Component {
_meta = {
props: ['as', 'children', 'size']
}
}
if (process.env.NODE_ENV !== 'production') {
SUIComponent.props = {
size: {
values: SUI.SIZES,
},
}
SUIComponent.propTypes = {
as: customProptypes.as,
size: PropTypes.oneOf(SUIComponent.props.size.values),
}
} Lastly, for the first PR can we update the tests, utilities, contributing guide, and one component only? This way it is a smaller PR that we can review quickly. |
Okay, all components where updated 🖖 Also, @levithomason I think that we need to add page called
|
Regarding the docs page, I completely agree. I'd like to have some docs on basic setup as well. This has been discussed in another issue that I cannot find ATM. Starting build/optimize docs anywhere we can for now is good by me. We can iterate afterward. |
I've played with rollup, treeshaking doesn't work there. |
Same problem with webpack 😕 |
Depends on how they are being imported as well. Could you open a PR and add your setup to the repo for review? I'd like to start some minimal project setup examples in our repo anyhow. Let's put them in |
Appreciate the efforts to reduce build sizes. |
@pke - See this comment: #830 (comment)
|
@jcarbo Ah I see. The bundle is still a heavy 500kb. I am afraid to use it in my app which is already over 1MB. And with webpack 1 there is no tree shaking. |
@pke - Despite the name, you can actually use the It will essentially transform: // from
import { Button } from 'semantic-ui-react'
// to
import Button from 'semantic-ui-react/dist/commonjs/elements/Button' Bundle size is definitely something we're trying to solve with issues/PRs like these. |
The full library in UMD format is only You should have slightly smaller builds assuming you aren't building to UMD and likely do not need to include the UMD checks for all environments.
To clarify, the full list of lodash methods currently used is quite large. It also spans
|
Wow, thanks for the the thorough responses, guys. But minified might help to decrease load time and parsing. The additional transformation @jcarbo mentioned might also help. I just wish that we would be able to |
You certainly can if you compile it yourself, just pull it form our import Button from 'semantic-ui-react/src/elements/Button' Or, you can use the precompiled commonjs module: import Button from 'semantic-ui-react/dist/commonjs/elements/Button' Or, you can use the precompiled ES build, which preserves import statements for tree shaking: import Button from 'semantic-ui-react/dist/es/elements/Button' |
@layershifter is this issue actually complete now? The last check list item is:
However, we offer several ways to do this now with Let me know if you had any other needs or ideas in mind for this. |
No, I want to check this TODO (#524 (comment)) before we finally close this. |
Sounds good, although, it is not clear to me what other ways of removing unused components we could offer, short of #1443. |
Tree-shaking with webpack2 doesn't work for me. |
You do not. Are you importing from the ES build target? import { Button} from 'semantic-ui-react/dist/es' Tree shaking can only work with ES import statements, the default import location provides commonjs modules. |
No from semantic-ui-react. |
We're building through a webpack 2 and tree example. Let's address any issues there, #1497. |
We have separate issues for webpack 2 and rollup, so I'm closing this issue for housekeeping because technically we reached its goal. |
I've builded
stardust
with webpack in my project.There are two problems:
PropTypes
are in production bundle, too.bundlers TODO
propTypes
from production build, also checkSUI.js
usagepropTypes update
The text was updated successfully, but these errors were encountered: