oliviertassinari / babel-plugin-transform-react-remove-prop-types Goto Github PK
View Code? Open in Web Editor NEWRemove unnecessary React propTypes from the production build. :balloon:
License: MIT License
Remove unnecessary React propTypes from the production build. :balloon:
License: MIT License
For example, my own code may be safe to prune propTypes, but react-router
isn't, because they do some checks involving them at runtime in production mode: https://github.com/ReactTraining/react-router/blob/389df9c0ba603b758de4a979a34ee10276f9a8d0/modules/Router.js#L135
Hi. As I see your fork is much popular, than original project. Maybe we can join forces to make this plugin better?
I recently tried integrating this plugin with react-virtualized. (I prefer declaring propTypes
inside of the class body rather than at the footer so I was excited about the "wrap" mode.)
Running with mode: "remove"
(the default) worked fine for me but when I tried running with mode: "wrap"
I got the following error:
Error: source/ArrowKeyStepper/ArrowKeyStepper.js: We don't know what to do with this node type. We were previously a Statement but we can't fit in here?
at NodePath.insertAfter (../node_modules/babel-core/node_modules/babel-traverse/lib/path/modification.js:175:13)
at remove (../node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:185:30)
at ClassProperty (../node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:58:17)
at NodePath._call (../node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call (../node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:48:17)
at NodePath.visit (../node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:105:12)
at TraversalContext.visitQueue (../node_modules/babel-core/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitMultiple (../node_modules/babel-core/node_modules/babel-traverse/lib/context.js:103:17)
at TraversalContext.visit (../node_modules/babel-core/node_modules/babel-traverse/lib/context.js:190:19)
at Function.traverse.node (../node_modules/babel-core/node_modules/babel-traverse/lib/index.js:114:17)
FWIW, the container
in question is of type: "ExportDefaultDeclaration"
and the node
is of type: "ClassDeclaration"
.
For what it's worth, I tried patching the change from your PR #45 onto my local version of babel-plugin-transform-react-remove-prop-types but it didn't seem to resolve the issue.
You can reproduce this issue (if you're interested) by checking out the propTypes
branch of react-virtualized and then running:
npm i
npm run build
We have a codebase based on react-boilerplate v3.4. I've been looking at the main.js
that gets built and it includes references such as "./node_modules/prop-types/factoryWithThrowingShims.js"
and var n=o("./node_modules/prop-types/node_modules/fbjs/lib/emptyFunction.js"),
. Am I right in thinking that prop-types are not being removed in the build?
The .babelrc
used is:
"presets": [
[
"latest",
{
"es2015": {
"modules": false
}
}
],
"react",
"stage-0"
],
"env": {
"production": {
"only": [
"app"
],
"plugins": [
"transform-react-remove-prop-types",
"transform-react-inline-elements",
"transform-react-constant-elements"
]
},
"analyze": {
"only": [
"app"
],
"plugins": [
"transform-react-remove-prop-types",
"transform-react-inline-elements",
"transform-react-constant-elements"
]
},
"test": {
"plugins": [
"transform-es2015-modules-commonjs",
"dynamic-import-node"
]
}
}
}
and we most definitely pass the production flag with cross-env NODE_ENV=production webpack ...
in our package.json
scripts. All the code lives under the /app
directory.
When a component extends from parent and the properties are extended, they are not removed.
Sample Code:
export default class ComponentB extends ComponentA {
static propTypes = Object.assign({}, {
stringKey: PropTypes.string.isRequired,
}, ComponentA.propTypes)
}
Stateless function component that use React.cloneElement
aren't supported:
// @flow weak
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import warning from 'warning';
import { createStyleSheet } from 'jss-theme-reactor';
import customPropTypes from '../utils/customPropTypes';
export const styleSheet = createStyleSheet('MuiListItemAvatar', () => {
return {
denseAvatar: {
width: 36,
height: 36,
fontSize: 18,
marginRight: 4,
},
denseAvatarIcon: {
width: 20,
height: 20,
},
};
});
/**
* `<ListItemAvatar>` is a simple wrapper to apply the `dense` mode styles to `Avatar`.
*
* ```
* <ListItemAvatar>
* <Avatar>
* </ListItemAvatar>
* ```
*/
export default function ListItemAvatar(props, context) {
if (context.dense === undefined) {
warning(false, `Material-UI: <ListItemAvatar> is a simple wrapper to apply the dense styles
to <Avatar>. You do not need it unless you are controlling the <List> dense property.`);
return props.children;
}
const {
children,
className: classNameProp,
...other
} = props;
const classes = context.styleManager.render(styleSheet);
return React.cloneElement(children, {
className: classNames(
{ [classes.denseAvatar]: context.dense },
classNameProp,
children.props.className,
),
childrenClassName: classNames(
{ [classes.denseAvatarIcon]: context.dense },
children.props.childrenClassName,
),
...other,
});
}
ListItemAvatar.propTypes = {
/**
* The content of the component, normally `Avatar`.
*/
children: PropTypes.element.isRequired,
/**
* The CSS class name of the root element.
*/
className: PropTypes.string,
};
ListItemAvatar.contextTypes = {
dense: PropTypes.bool,
styleManager: customPropTypes.muiRequired,
};
Take a look at Parent
class [1] and Child
class [2] that extends Parent
.
Once it's compiled with babel with babel-plugin-transform-react-remove-prop-types
plugin, PropTypes are removed from Parent
[3] class, but not from Child
[4].
The test case repo contains gulpfile and .babelrc as well, @oliviertassinari.
Thanks!
[1] https://github.com/azasypkin/issues/blob/master/babel-plugin-transform-react-remove-prop-types/parent.jsx#L9-L11
[2] https://github.com/azasypkin/issues/blob/master/babel-plugin-transform-react-remove-prop-types/child.jsx#L10-L13
[3] https://github.com/azasypkin/issues/blob/master/babel-plugin-transform-react-remove-prop-types/dist/parent.js
[4] https://github.com/azasypkin/issues/blob/master/babel-plugin-transform-react-remove-prop-types/dist/child.js
This is a question.
Say I have a .babelrc
file like this:
{
"presets": ["react", "es2015", "stage-1"],
"env" : {
"development" : {
"presets" : ["react-hmre"]
},
"production" : {
"plugins" : ["transform-react-remove-prop-types"]
}
}
}
And I'm building my project with webpack, so my JS loader looks like this:
{
test : /\.jsx?$/,
exclude : /(?:node_modules)/,
loaders : [ 'babel', 'eslint' ],
},
As you can see node_modules
are excluded, because running the transformer on npm code would be excessive / expensive. However, doing so means propType definitions from packages such as react-datepicker and react-autosuggest will remain in the final build.
So my question is, what would be the smartest strategy for removing propTypes from external packages in a setup like this?
Should we be convincing package authors to add this plugin to their builds with the wrap
mode on?
P.S., I've tried just running the babel
cli tool to strip propTypes from the compiled build, but that doesn't work (I guess, due to safeguards within your package to validate variables named propTypes
are actually React related).
Would it be feasible to wrap propType
definitions in a if (process.env.NODE_ENV !== 'production')
check (extracting them out first if they're part of a React.createClass()
) instead of removing them completely?
This plugin is great and solves the problem of removing my own redundant propTypes
for production, but it would be cool if it could also be adopted by authors transpiling reusable components to publish to npm, so your dependencies' propTypes
could be available in development and test as normal, but automatically removed for production via the usual dead-code elimination process.
Could that be made an option into this plugin? Remove vs. move/wrap?
After reading your medium post, I decided to actually write the babel preset that I've wanted for a little while.
A while back I wrote a transform for Facebook for transforming pure class components into plain functions: https://github.com/thejameskyle/babel-plugin-react-pure-components
I'm taking that and a few other ideas I have and putting them into the same kind of monorepo that we use for Babel projects: https://github.com/thejameskyle/babel-react-optimize
Since you are doing very similar checks for pure components, I thought we could abstract that logic into babel-helpers and share it between plugins.
Would you be interested in taking this code and putting it in a shared repo?
Not sure if this is a bug or an issue on my side.
I have a pure react component that returns a lodash map over a list
return map(mapList, (index) => {
when I build and run in production mode, I get an exception. I did some investigation and I concluded this line is the source of the issue
if (node.callee && node.callee.object.name === 'React' && node.callee.property.name === 'createElement')
you assume that the callee always has an object and property which in this specific case is not.
I can only fix this by not returning map directly but rather assign it to a variable and at the end return it
const mapper = map(mapList, (index) => {
...
return mapper
Now not sure if you still need to guard that the callee has an object and property before carrying on the rest of the test. otherwise just return false.
if (node.callee && node.callee.object && node.callee.object.name === 'React' && node.callee.property.name === 'createElement'
Issue: Please support new React es6/7 syntax.
class comp extends Compoent{
static propTypes = {
prop1: PropTypes.string
};
}
:)
Thanks
React v15.3.0 was just shipped.
They have introduced a new component PureComponent
. We should make sure we support it.
I have a context decorator that looks like this
export function context(contextTypes, passedContext) {
return (DecoratedComponent) => {
return class extends React.Component {
static propTypes = DecoratedComponent.propTypes;
static childContextTypes = contextTypes;
getChildContext() {
if (typeof passedContext === 'function') {
return passedContext.bind(this)();
} else {
return passedContext;
}
}
render() {
return (
<DecoratedComponent {...this.props} />
);
}
};
};
}
When compiling for production I get the following error:
Module build failed: TypeError: /.../index.js: Cannot read property 'name' of null
Seems to be related to #7 (#8). Any ideas on how to stop the removal of props when using a HOC?
It would be nice if the plugin searched up the inheritance chain for the base Component class.
node_modules/babel-plugin-transform-react-remove-prop-types/src/index.js:83
83: const plugin = require(pluginName);
^^^^^^^^^^^^^^^^^^^ The parameter passed to require() must be a literal string.
Found 1 error
Removing propTypes entirely is causing issues with third party dependencies that need them to be defined. This was causing issues when using react-native-web.
It was brought up that replacing propTypes with an empty object would have the effects of not needing those definitions, while allowing libraries to reference undefined properties on propTypes and prevent cannot read [name] of undefined
errors.
what's the difference?
Excuse me if I'm completely missing the point here, but, this seems like a bit of an after the fact solution.
In one way you could almost says it promotes not cleaning up your code.
If your declare a propType and then don't use it in your compoment, essentially it's an unused param, and it should be highlighted or removed from the code trough eslint.
If I use this syntax, it works perfectly:
import React from 'react';
export default class MyComp extends React.Component {
render() {
//...
}
}
MyComp.propTypes = {
name: React.PropTypes.object
}
however, it does not work like this:
import React, { Component } from 'react';
export default class MyComp extends Component {
render() {
//...
}
}
MyComp.propTypes = {
name: React.PropTypes.object
}
I think I just ran into the error situation mentioned here while using this plugin in my React Native app.
I accidentally wrote this code in my .babelrc
:
...
"plugins": [
...
"transform-react-remove-prop-types"
...
]
...
Note that I did NOT put it under the production
environment. Now in development, a bunch of my imported RN components from node_modules are complaining about not having prop types defined:
I have tried resetting the yarn cache, uninstalling and re-installing node modules, all to no avail. Is there a solution to basically undo the work this package has done and restore my project to where it was to begin with? I don't understand why a refresh of node_modules
isn't solving the problem.
Please see a cross-post I made on the RN repo for additional info: facebook/react-native#14338
Thanks!
Could 775ebea be publish as 0.2.6
or 0.3.0
. Was running into the same issue when directly inheriting from Component
. Would be nice to be able to remove propTypes.
Could this transform also do something with contextTypes
and childContextTypes
?
They're the only other places PropTypes
are used AFAIK, so handling them too would allow complete removal of PropTypes
from an app's own production built code. This would also be useful for slimming down the production build of libraries which use context while still allowing PropTypes to be validated in development.
React doesn't care which values they have in production, but uses their property names to validate that only expected child context is provided and to mask context properties which are made available to a child, so they should be wrapped by default rather than removed (although you might still want to be able remove them if doing a cross-compatible build for something like Preact, which implements context without contextTypes
and childContextTypes
).
Example input and expected output:
class Foo1 extends React.Component {
static contextTypes = {
bar1: React.PropTypes.string,
};
render() {}
}
class Foo1 extends React.Component {
render() {}
}
process.env.NODE_ENV !== "production" ? Foo1.contextTypes = {
bar1: React.PropTypes.string
} : {
bar1: 1
};
This plugin removes the assignment of propTypes
on react component, but it doesn't affect the referenced variable.
This means that the definition of the propTypes
isn't removed.
For example:
const propTypes = {
value: PropTypes.string,
};
export default function MyComponent() {
return <div />;
}
MyComponent.propTypes = propTypes;
Becomes:
{
value: PropTypes.string,
};
export default function MyComponent() {
return <div />;
}
This is fine, except when referencing the propTypes
from another component.
import MyComponent from './MyComponent';
const propTypes = {
value: MyComponent.propTypes.value,
};
export default MyOtherComponent(props) {
return <MyComponent value={props.value} />;
}
MyOtherComponent.propTypes = propTypes;
After processing this becomes:
import MyComponent from './MyComponent';
{
value: MyComponent.propTypes.value, // MyComponent.propTypes === undefined
};
export default MyOtherComponent(props) {
return <MyComponent value={props.value} />;
}
This is a common use case, as this is the recommended way to define propTypes
by the airbnb style guide (https://github.com/airbnb/javascript/tree/master/react#ordering)
I suggest to remove (or add an option to remove) the node that creates the propTypes
object. So the latter example would simply become:
import MyComponent from './MyComponent';
export default MyOtherComponent(props) {
return <MyComponent value={props.value} />;
}
When using wrap
mode, the indirect assignment should be turned into a direct assignment. So the first example would be transformed into:
export default function MyComponent() {
return <div />;
}
if (process.env.NODE_ENV !== 'production') {
MyComponent.propTypes = {
value: PropTypes.string,
};
}
As a side effect, the bundle will become even smaller. ๐
Reproduction example using the wrap
option:
// @flow weak
import { PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import { createSwitch } from '../internal/SwitchBase';
import withSwitchLabel from '../internal/withSwitchLabel';
export const styleSheet = createStyleSheet('MuiCheckbox', (theme) => {
return {
default: {
color: theme.palette.text.secondary,
},
checked: {
color: theme.palette.accent[500],
},
disabled: {
color: theme.palette.action.disabled,
},
};
});
const Checkbox = createSwitch({ styleSheet });
Checkbox.displayName = 'Checkbox';
export default Checkbox;
const LabelCheckbox = withSwitchLabel(Checkbox);
export { LabelCheckbox };
/**
* [Checkboxes](https://material.io/guidelines/components/selection-controls.html#selection-controls-checkbox)
* allow the user to select multiple options from a set.
*/
export class CheckboxDocs {
render() {}
static propTypes = {
/**
* If `true`, the component is checked.
*/
checked: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
/**
* The CSS class name of the root element when checked.
*/
checkedClassName: PropTypes.string,
/**
* The icon to display when the component is checked.
*/
checkedIcon: PropTypes.node,
/**
* The CSS class name of the root element.
*/
className: PropTypes.string,
/**
* @ignore
*/
defaultChecked: PropTypes.bool,
/**
* If `true`, the switch will be disabled.
*/
disabled: PropTypes.bool,
/**
* The CSS class name of the root element when disabled.
*/
disabledClassName: PropTypes.string,
/**
* The icon to display when the component is unchecked.
* If a string is provided, it will be used as a font ligature.
*/
icon: PropTypes.node,
/*
* @ignore
*/
name: PropTypes.string,
/**
* Callback fired when the state is changed.
*
* @param {object} event `change` event
* @param {boolean} checked The `checked` value of the switch
*/
onChange: PropTypes.func,
/**
* If `false`, the ripple effect will be disabled.
*/
ripple: PropTypes.bool,
/**
* @ignore
*/
tabIndex: PropTypes.string,
/**
* The value of the component.
*/
value: PropTypes.string,
};
}
TypeError: src/components/button/index.js: Cannot read property 'name' of undefined
at ClassProperty (/Users/neoziro/projects/xxx/node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:55:84)
import React, {PropTypes} from 'react';
import styles from './button.scss';
import BaseComponent from 'components/base';
import classnames from 'classnames';
export default class Button extends BaseComponent {
static propTypes = {
block: PropTypes.bool,
large: PropTypes.bool
};
styles = styles;
render() {
const {className: propClassName, children, block, large, ...props} = this.props;
const className = classnames(styles.btn, {
[styles.btnBlock]: block,
[styles.btnLarge]: large
}, propClassName);
return <button {...{className}} {...props}>{children}</button>;
}
}
Does this plugin need babel-core
in its dependencies
? It doesn't seem to depend on it at runtime.
Context for my question: I'm hoping to include this plugin in a Babel presets module which manually deduplicates dependencies to make Babel 6 presets less painful for people still on npm2.
Looking forward to the added support for createReactClass
: a8530e3
Remove unnecessary React propTypes from the production build. You can save bandwidth by removing them.
I think it is ambiguous as to why exactly they are unnecessary. ( and also caused my initial confusion )
I would propose this:
Remove React propTypes from the production build, as they are unnecessary in production. You can save bandwidth by removing them.
Following facebook/react-native#6750,
It seems that we have a false positive:
import {View} from 'react-native';
class CustomView extends React.Component {
static propTypes = {
style: View.propTypes.style
};
render() {
return (
<View style={this.props.style}>..</View>
);
}
}
SyntaxError: src/SwipeableViews.animated.js: You are accessing the propTypes from an imported Identifier.
It's likely to break at runtime. Instead, import the propTypes.
For more details, have a look at this issue: https://goo.gl/sHDdUk.
115 | * on the slide component.
116 | */
> 117 | slideStyle: View.propTypes.style,
| ^
118 | /**
119 | * This is the config given to Animated for the spring.
120 | * This is useful to change the dynamic of the transition.
First all @oliviertassinari thank you for maintaining this package and repo!
I wanted to ask about the previously supported React.createClass
. Was there a specific reason for dropping this support from the previous fork? Was there a specific issue in supporting or did you simply want to concentrate support for es6 class style.
I searched but I couldn't find any more info on this.
My current use case is a codebase that uses React.createClass
across. Without doing a codemod I wanted to see if there was an alternative to take advantage of fully removing propTypes
in production.
Thanks!
Peter
./components/Parent.jsx
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
export default class Parent extends PureComponent {
static propTypes = {
parentProp: PropTypes.string.isRequired,
}
}
./components/Child.jsx
import PropTypes from 'prop-types';
import React, { PureComponent } from 'react';
import Parent from './Parent';
export default class Child extends Parent {
static propTypes = {
childProp: PropTypes.string.isRequired,
}
}
Flow 0.48.0 outputs the following warning:
node_modules/babel-plugin-transform-react-remove-prop-types/src/index.js:81
81: const plugin = require(pluginName);
^^^^^^^^^^^^^^^^^^^ The parameter passed to require() must be a literal string.
Hi,
thank you for the plugin. It works well. I noticed though that some of the RN 3rd party modules rely on propTypes
property. See for example react-native-vector-icons\lib\icon-button.js
. Removing propTypes
then results in
AndroidRuntime: com.facebook.react.common.JavascriptException:
Requested keys of a value that is not an object., stack:
I modified my version of the plugin, so that only files not residing in node_modules
are cleaned up preventing this type of crashes. In a function like isModule
below I check if it's my own file or not and only then remove propTypes
:
function isModule(scope) {
if (!scope.hub.file.opts) {
return true;
}
var filename = scope.hub.file.opts.filename;
if (!filename) {
return true;
}
return filename.indexOf("node_modules") !== -1;
}
I thought maybe it's worth adding an extra option to the plugin that would allow to skip 3rd party modules modification if needed.
We have a file containing several stateless function components, and one of those components is not having its PropTypes removed. I can't see why, since you have test cases for similar situations. This is what the file roughly looks like:
import CustomPropTypes from 'custom-prop-types';
import React from 'react';
export const Message = ({ className, isSent }) => {
return (
<div className={className} />
);
};
Message.propTypes = {
className: PropTypes.string,
isSent: PropTypes.bool
};
/* โฆ4 more components */
const FullMessage = ({ className, entry, isSent }) => {
return (
<div className={className} />
);
};
// these PropTypes are never removed
FullMessage.propTypes = {
className: PropTypes.string,
entry: CustomPropTypes.entry.isRequired,
isSent: PropTypes.bool
};
export default FullMessage;
There are the babel dependencies
"babel-plugin-transform-react-remove-prop-types": "0.2.10"
"babel-plugin-transform-runtime": "6.15.0"
"babel-preset-es2015": "6.18.0"
"babel-preset-react": "6.16.0"
"babel-preset-stage-1": "6.16.0"
"babel-core": "6.13.2" // because in versions >6.13.2 we can't set breakpoints in dev tools
"babel-runtime": "6.11.6"
Today's announcement includes a deprecation of React.PropTypes
and an introduction of a new package prop-types
. I expect not a whole lot of code will need to be added to support this. I'm happy to do it with a little direction.
Would be nice if this could remove .displayName
as well
With 15.5+ we are advising people who used to use React.createClass
to switch to using ES2015 classes or the create-react-class
package on NPM. Looking through the source, it appears that only React.createClass
instances are being handled (I may be wrong though):
Would it be possible to check for create-react-class
too? Thank you.
CC/ @gaearon
Never had to write AST transforms, so its quite hard to deduce this from the source code.
Is it removing both versions of PropTypes? From what I understand its also working by default for whole node_modules
.
Another questions is - what exactly is stopping this transform to work? From my observations - PropTypes cannot use imported definitions, is that right?
Libraries I have problem with - react-textarea-autosize, react-visibility-sensor, react-linkify, react-transition-group
I'm assuming something like this:
var RemovePropTypesPlugin = require('babel-plugin-transform-react-remove-prop-types');
plugins: [
new RemovePropTypesPlugin(),
]
Looks like propTypes aren't removed from a component created with createClass
in some situations. I've only quickly looked into it, but these are examples of code that still contains propTypes (and throws errors in production because the View
propTypes don't exist anymore):
import View from 'View';
const ScrollView = React.createClass({
propTypes: {
children: View.propTypes.children
}
});
and
import View from 'View';
const ScrollView = React.createClass({
propTypes: {
...View.propTypes,
onScroll: PropTypes.func
}
});
When trying to run with webpack 2.2.1, I'm getting the following error:
ERROR in ./~/react-intl/lib/index.es.js
Module build failed: TypeError: [redacted]/node_modules/react-intl/lib/index.es.js: Property consequent of ConditionalExpression expected node to be of a type ["Expression"] but instead got null
Module build failed: TypeError: [redacted]/node_modules/react-intl/lib/index.es.js: Property consequent of ConditionalExpression expected node to be of a type ["Expression"] but instead got null
at Object.validate ([redacted]/node_modules/babel-types/lib/definitions/index.js:109:13)
at Object.validate ([redacted]/node_modules/babel-types/lib/index.js:511:9)
at NodePath._replaceWith ([redacted]/node_modules/babel-traverse/lib/path/replacement.js:176:7)
at NodePath._remove ([redacted]/node_modules/babel-traverse/lib/path/removal.js:58:10)
at NodePath.remove ([redacted]/node_modules/babel-traverse/lib/path/removal.js:30:8)
at remove ([redacted]/node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:157:10)
at AssignmentExpression ([redacted]/node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:97:15)
at NodePath._call ([redacted]/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call ([redacted]/node_modules/babel-traverse/lib/path/context.js:48:17)
at NodePath.visit ([redacted]/node_modules/babel-traverse/lib/path/context.js:105:12)
at TraversalContext.visitQueue ([redacted]/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitSingle ([redacted]/node_modules/babel-traverse/lib/context.js:108:19)
at TraversalContext.visit ([redacted]/node_modules/babel-traverse/lib/context.js:192:19)
at Function.traverse.node ([redacted]/node_modules/babel-traverse/lib/index.js:114:17)
at NodePath.visit ([redacted]/node_modules/babel-traverse/lib/path/context.js:115:19)
at TraversalContext.visitQueue ([redacted]/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitSingle ([redacted]/node_modules/babel-traverse/lib/context.js:108:19)
at TraversalContext.visit ([redacted]/node_modules/babel-traverse/lib/context.js:192:19)
at Function.traverse.node ([redacted]/node_modules/babel-traverse/lib/index.js:114:17)
at NodePath.visit ([redacted]/node_modules/babel-traverse/lib/path/context.js:115:19)
at TraversalContext.visitQueue ([redacted]/node_modules/babel-traverse/lib/context.js:150:16)
at TraversalContext.visitMultiple ([redacted]/node_modules/babel-traverse/lib/context.js:103:17)
at TraversalContext.visit ([redacted]/node_modules/babel-traverse/lib/context.js:190:19)
at Function.traverse.node ([redacted]/node_modules/babel-traverse/lib/index.js:114:17)
at traverse ([redacted]/node_modules/babel-traverse/lib/index.js:79:12)
at NodePath.traverse ([redacted]/node_modules/babel-traverse/lib/path/index.js:144:25)
at PluginPass.Program ([redacted]/node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:21:21)
at newFn ([redacted]/node_modules/babel-traverse/lib/visitors.js:276:21)
at NodePath._call ([redacted]/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call ([redacted]/node_modules/babel-traverse/lib/path/context.js:48:17)
@ ./src/containers/MatchCenterScores.js 31:17-38
@ ./src/containers/index.js
@ ./src/app.js
Here is my .babelrc:
{
"presets": ["es2015", "react"],
"plugins": [
["transform-object-rest-spread", {useBuiltIns: true}],
"transform-es2015-destructuring",
"transform-class-properties",
"transform-export-extensions",
"lodash",
"react-intl",
"transform-node-env-inline",
//"transform-inline-environment-variables",
"transform-react-remove-prop-types"
]
}
Here is my webpack config:
module.exports = {
entry: './src/app.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build')
},
module: {
rules: [
{test: /\.(js|jsx)$/, use: 'babel-loader'}
]
},
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules']
}
}
The following fails once I try to add an option to babel-plugin-flow-react-proptypes
:
["transform-react-remove-prop-types", {
"mode": "wrap",
"plugins": [
["babel-plugin-flow-react-proptypes", {"omitRuntimeTypeExport": true}],
"babel-plugin-transform-flow-strip-types"
]
}]
AssertionError [ERR_ASSERTION]: path must be a string
at Module.require (module.js:512:3)
at require (internal/module.js:11:18)
at /Users/kross/projects/material-ui/node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:35:26
at Array.map (native)
at PluginPass.Program (/Users/kross/projects/material-ui/node_modules/babel-plugin-transform-react-remove-prop-types/lib/index.js:34:52)
at newFn (/Users/kross/projects/material-ui/node_modules/babel-traverse/lib/visitors.js:276:21)
at NodePath._call (/Users/kross/projects/material-ui/node_modules/babel-traverse/lib/path/context.js:76:18)
at NodePath.call (/Users/kross/projects/material-ui/node_modules/babel-traverse/lib/path/context.js:48:17)
at NodePath.visit (/Users/kross/projects/material-ui/node_modules/babel-traverse/lib/path/context.js:105:12)
at TraversalContext.visitQueue (/Users/kross/projects/material-ui/node_modules/babel-traverse/lib/context.js:150:16)
The following component returns an error when compiled with this plugin:
import React, { PropTypes } from 'react';
var Message = ({isFetching, isSuccess, isFailure, errorMsg}) => {
let messageType;
let messageTxt;
if (isFetching) {
messageType = 'warning';
messageTxt = 'Pending call...';
} else if (isSuccess) {
messageType = 'success';
messageTxt = 'Repo pushed successfully';
} else if (isFailure) {
messageType = 'danger';
messageTxt = 'Something wrong occured';
}
if (messageTxt === null) {
return;
}
return <div className={'alert alert-' + messageType} role='alert'>{messageTxt}</div>;
};
Message.propTypes = {
isFetching: PropTypes.bool.isRequired,
isSuccess: PropTypes.bool.isRequired,
isFailure: PropTypes.bool.isRequired,
errorMsg: PropTypes.string.isRequired
};
export default Message;
The error is the following:
Module build failed: TypeError: /Users/harijoe/Projects/perso/src/components/Message.js: Cannot read property 'type' of null
This plugin has been focusing on doing a single task so far: removing the propTypes
.
However, we could be smarter. As raised by @kentcdodds, removing the prop types is one thing, we also have the import to take care of:
import PropTypes from 'prop-types';
I'm wondering if UglifyJS2 and other dead code eliminator tools are smart enough to take care of it, otherwise, we would have to implement it.
Hello,
I've just installed this and it seems that for my edge cases this is not working.
The following propTypes are not removed from the build. While all the others declared in the standard way are correctly removed.
CASE 1:
const myPropName = 'whatever';
BaseLink.propTypes = {
prop1: PropTypes.string
prop2: PropTypes.node
};
BaseLink.propTypes[myPropName] = PropTypes.object; //<== This is not removed
CASE 2:
const myPropName = 'whatever';
// Both are not removed
MyComp.wrappedComponent.propTypes = {};
MyComp.wrappedComponent.propTypes[myPropName] = PropTypes.object.isRequired;
Here I used wrappedComponents, because I'm decorating my original component MyComp
with mobx-react @observer that will indeed create a new wrapper. So the original component is available as MyComp.wrappedComponent
.
CASE 3:
This applies to both cases above.
I'm importing my PropTypes from the new separate packages
import PropTypes from 'prop-types';
It seems the import is never removed from the build using the default config (supposed to be remove
mode).
I'm not sure if this is due to the 2 cases above (still having some propTypes
in the build would not allow to remove the import?) or because I import them from the separate package and not from the React core... ๐ค
Hi!
Thanks for this plugin, just what I was looking for!
However, this plugin doesn't remove propTypes from stateless components. That is, it doesn't remove this:
const MyComponent = (props) => (
<div></div>
);
MyComponent.propTypes = {
someProp: React.PropTypes.string
};
Isn't this something that should be considered? I think stripping the propTypes
should be okey in this case:
propTypes
is assigned to is a function in the same module.This doesn't work if you're not using JSX, so I could see it also removing the propTypes
if:
props
or destructuring is used on that single argument and it destructures it to variable names which also exists in the propTypes
object.An even simpler way of detecting it would be to always strip the propTypes
if the object it's assigned to is a function. It would be simpler to implement, but with the risk of false positives. Although I can't think of a use case where you use this plugin but you have propTypes
that you don't want to remove.
With 0.4.4 version.
if (state.opts.plugins) {
const pluginsVisitors = state.opts.plugins.map((pluginName) => {
const plugin = require(pluginName);
return plugin({ template, types }).visitor;
});
programPath.traverse(visitors.merge(pluginsVisitors));
}
require("babel-core").transform("code", {
plugins: [require('babel-plugin-transform-react-remove-prop-types')]
});
error info:
Error: Plugin 1 specified in "base.env.production" provided an invalid property of "default" while parsing file: /home/development/Projects/project/js/main.js
at Plugin.init (/home/development/Projects/project/node_modules/babel-core/lib/transformation/plugin.js:115:13)
at Function.normalisePlugin (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/options/option-manager.js:149:12)
at /home/development/Projects/project/node_modules/babel-core/lib/transformation/file/options/option-manager.js:183:30
at Array.map (native)
at Function.normalisePlugins (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/options/option-manager.js:155:20)
at OptionManager.mergeOptions (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/options/option-manager.js:277:36)
at OptionManager.mergeOptions (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/options/option-manager.js:330:10)
at OptionManager.init (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/options/option-manager.js:465:10)
at File.initOptions (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/index.js:194:75)
at new File (/home/development/Projects/project/node_modules/babel-core/lib/transformation/file/index.js:123:22)
I've built the code as a gist, which I'm using as a custom babel plugin in my own projects. I'd be happy to create a PR to incorporate this feature, if it's of interest.
Do you have docs on how your tests are structured?
https://gist.github.com/jbellsey/0fef4c161ec324fce1015d0f4f47fe21
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.