Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# babel-plugin-transform-react-remove-prop-types
> Remove unnecessary React propTypes from the production build.
[](https://www.npmjs.com/package/babel-plugin-transform-react-remove-prop-types)
[](https://www.npmjs.com/package/babel-plugin-transform-react-remove-prop-types)
[](https://travis-ci.org/oliviertassinari/babel-plugin-transform-react-remove-prop-types)
[](https://david-dm.org/oliviertassinari/babel-plugin-transform-react-remove-prop-types)
[](https://david-dm.org/oliviertassinari/babel-plugin-transform-react-remove-prop-types?type=dev)
## Installation
```sh
npm install --save-dev babel-plugin-transform-react-remove-prop-types
```
## The problem solved
Remove React `propTypes` from the production build, as they are only used in development.
You can **save bandwidth** by removing them.
## Example
**In**
```jsx
const Baz = (props) => (
<div {...props} />
);
Baz.propTypes = {
className: PropTypes.string
};
```
**Out**
```jsx
const Baz = (props) => (
<div {...props} />
);
```
### With comment annotation
The majority of cases should be addressed by default by this plugin.
In some cases, for example when using HOCs (High Order Components), like *react-redux*'s `connect`, or component inheritance ([although it's NOT recommended](https://facebook.github.io/react/docs/composition-vs-inheritance.html)), a comment after the `propTypes` definition may be used to force the removal:
```js
Component.propTypes /* remove-proptypes */ = {}
```
## Usage
### Via `.babelrc` (Recommended)
**.babelrc**
without options:
```json
{
"env": {
"production": {
"plugins": ["transform-react-remove-prop-types"]
}
}
}
```
with options:
```json
{
"env": {
"production": {
"plugins": [
["transform-react-remove-prop-types", {
"mode": "wrap",
"ignoreFilenames": ["node_modules"]
}]
]
}
}
}
```
### Via CLI
```sh
babel --plugins transform-react-remove-prop-types script.js
```
### Via Node API
without options:
```js
require('babel-core').transform('code', {
plugins: [
'transform-react-remove-prop-types',
],
});
```
with options:
```js
require('babel-core').transform('code', {
plugins: [
[
'transform-react-remove-prop-types',
{
mode: 'wrap',
ignoreFilenames: ['node_modules'],
},
],
],
});
```
## Options
### `mode`
- `remove` (default):
the `propTypes` definitions are removed from the source code.
- `wrap`:
the `propTypes` definitions are wrapped with the following code:
```js
Component.propTypes = process.env.NODE_ENV !== "production" ? {
// ...
} : {};
```
Accessing `Component.propTypes.className` won't throw. It's a tradeoff between the size of the output file and the likelihood libraries like [react-native-hyperlink](https://github.com/obipawan/react-native-hyperlink/pull/11) breaks.
- `unsafe-wrap`:
the `propTypes` definitions are wrapped with the following code:
```js
if (process.env.NODE_ENV !== "production") {
Component.propTypes = {
// ...
}
}
```
Accessing `Component.propTypes.className` will throw.
The *wrap* modes are targeting React libraries like [material-ui](https://github.com/callemall/material-ui) or [react-native-web](https://github.com/necolas/react-native-web).
They are not intended to be used by application authors.
### `removeImport`
- `true`: the import statements are removed as well. This option only works if `mode` is set to `remove`:
```js
import PropTypes from 'prop-types'
```
- `false` (default): does not remove the import statements.
### `ignoreFilenames`
This filter generates a regular expression.
Any filenames containing one of the array's strings will be ignored.
By **default**, we match everything.
Following the [Is it safe?](#user-content-is-it-safe) section, you might encounter a component
depending on the `propTypes` at runtime to work.
For this reason, we provide an array options to filter out some files and folders.
For instance, you can ignore all the npm modules:
```js
ignoreFilenames: ['node_modules'],
```
### `additionalLibraries`
This option gives the possibility to remove other `propTypes` in addition to the canonical `prop-types`.
For instance, by default
```js
import PropTypes from 'prop-types'
import ImmutablePropTypes from 'react-immutable-proptypes'
```
will result in the latter not to be removed, while with:
```js
additionalLibraries: ['react-immutable-proptypes'],
```
both will be removed.
#### Regular expressions
If you are using Babel 7 or newer and your config is stored in [`babel.config.js`](https://babeljs.io/docs/en/configuration#babelconfigjs), you can also use a regular expression to describe modules, which should be removed.
This would be particularly useful when using custom prop types validators, implemented as part of your own source code. For example
```js
import CustomPropTypes from '../../prop-types/my-own-validator'
import OtherCustomPropTypes from '../../prop-types/my-other-validator'
```
would be removed with the following setting
```js
additionalLibraries: [/\/prop-types\/.*$/]
```
If you use an index file
```js
import CustomPropTypes from '../../prop-types'
```
you could set it up as
```js
additionalLibraries: [/\/prop-types$/]
```
### `classNameMatchers`
Use this option to enable this plugin to run on components that extend a class different than `React.Component` or `React.PureComponent`.
Given this example:
```js
class MyComponent extends BaseComponent {
...
}
```
You would use:
```js
classNameMatchers: ["BaseComponent"]
```
### `createReactClassName`
Use this option to set a custom name for the import of the `create-react-class` package that is different than `createReactClass`.
Given this example:
```js
import createClass from 'create-react-class';
```
You would use:
```js
createReactClassName: 'createClass'
```
## Is it safe?
If you are using the `propTypes` in a conventional way,
i.e by using them to perform type checking on the properties, that plugin should be **safe to use**.
However, some libraries are accessing the `propTypes` on the component directly.
For instance [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons/blob/3d1f2a5b7175d6e4c8985676940240776543ff60/lib/icon-button.js#L59) use them to split the properties between two components:
```js
const touchableProps = pick(restProps, Object.keys(TouchableHighlight.propTypes));
```
:warning: The plugin is breaking that code if it ends up removing `TouchableHighlight.propTypes`.
Make sure you are:
- Not using that pattern in your source code.
If you do, explicitly **export** the `propTypes` to work around that limitation.
- Not parsing the `node_modules`.
If you do, test that your code is still working before shipping into production.
[eslint-plugin-react has a rule forbid-foreign-prop-types](https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/forbid-foreign-prop-types.md) that can help you make this plugin safer to use.
## License
MIT