Babel Plugin to Remove React PropTypes
This Babel plugin, currently at version `0.4.24`, is designed to optimize React applications by effectively removing `propTypes` definitions from the production build. `propTypes` are primarily utilized for development-time type checking and debugging, and thus represent unnecessary overhead in production bundles, contributing to larger file sizes and increased load times. The plugin offers distinct `mode` options: `remove` (the default for most applications), `wrap`, and `unsafe-wrap`. The `wrap` and `unsafe-wrap` modes are specifically tailored for React library authors, enabling them to retain some `propTypes` behavior in development while ensuring optimization for production scenarios. The `remove` mode is generally recommended for direct application authors seeking maximum bundle size reduction. The project exhibits a consistent, albeit at times gradual, release cadence, with recent patches focusing on improved type checking logic, custom `createReactClass` function support, and more robust handling of unused identifier removal. It integrates seamlessly into the Babel ecosystem, typically configured via standard Babel configuration files such as `.babelrc` or `babel.config.js`.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'className') (or similar property access errors) in production builds.
cause This typically occurs when `mode: 'unsafe-wrap'` is used, and some part of your application or a third-party library attempts to access `Component.propTypes` at runtime in production.fixSwitch to `mode: 'remove'` (default) or `mode: 'wrap'`. `mode: 'wrap'` sets `propTypes` to an empty object `{}` in production, preventing runtime errors from undefined access, though it results in a slightly larger bundle than `remove`. -
PropTypes are still present in my production bundle!
cause The plugin is likely not being applied correctly in your production build environment. Common causes include not setting `process.env.NODE_ENV = 'production'` or misconfiguring your Babel `env` block.fixEnsure your Babel configuration includes the plugin within an `env.production` block (e.g., in `.babelrc` or `babel.config.js`) and that your build process correctly sets `NODE_ENV=production` when bundling for production. -
The `prop-types` import statement (e.g., `import PropTypes from 'prop-types';`) is still in my production bundle, even though the definitions are gone.
cause By default, the plugin removes the `propTypes` declarations but leaves the `import` statement. This can also happen if your bundler globally includes `prop-types` or if you have other references.fixAdd the `removeImport: true` option to the plugin configuration, for example: `['babel-plugin-transform-react-remove-prop-types', { removeImport: true }]`. Ensure this is only used with `mode: 'remove'` for full effect.
Warnings
- gotcha The `mode: 'wrap'` and `mode: 'unsafe-wrap'` options are specifically designed for React library authors, not general application development. Using them in applications can lead to larger bundle sizes than `mode: 'remove'` or unexpected runtime behavior, as `propTypes` might still be present as an empty object or conditionally defined.
- breaking As of v0.4.16, the plugin explicitly updated to support Babel 7. While designed for forward compatibility, users on very old Babel versions (Babel 6 or earlier) might encounter compatibility issues or require a Babel upgrade to fully utilize the latest features and fixes.
- gotcha For React components utilizing Higher-Order Components (HOCs) or certain inheritance patterns, `propTypes` might not be correctly identified and removed by default. A special comment annotation is required to force removal in such complex cases.
- gotcha The `removeImport: true` option will remove the `import PropTypes from 'prop-types';` statement. This option only works reliably with `mode: 'remove'`. If not handled correctly (e.g., if the `prop-types` package is still referenced by your bundler's globals), it might lead to residual `prop-types` code in the bundle or build errors.
- gotcha The plugin's documentation advises *not* parsing `node_modules` with this plugin, especially in `remove` or `unsafe-wrap` modes. Some third-party React libraries might unexpectedly depend on `propTypes` being present at runtime, leading to breakage if they are removed.
Install
-
npm install babel-plugin-transform-react-remove-prop-types -
yarn add babel-plugin-transform-react-remove-prop-types -
pnpm add babel-plugin-transform-react-remove-prop-types
Imports
- "transform-react-remove-prop-types"
import removePropTypes from 'babel-plugin-transform-react-remove-prop-types';
{ "plugins": ["transform-react-remove-prop-types"] } - babelPluginTransformReactRemovePropTypes
import { transformReactRemovePropTypes } from 'babel-plugin-transform-react-remove-prop-types';const plugin = require('babel-plugin-transform-react-remove-prop-types'); // Then use `plugin` in Babel's Node API configuration.
Quickstart
const babel = require('@babel/core');
const code = `
import PropTypes from 'prop-types';
const MyComponent = ({ value }) => <div>{value}</div>;
MyComponent.propTypes = {
value: PropTypes.string.isRequired
};
`;
// Simulate a production environment for the plugin to activate
process.env.NODE_ENV = 'production';
const result = babel.transformSync(code, {
filename: 'my-component.js',
plugins: [
// Required for Babel to parse JSX and ES modules before this plugin runs
['@babel/plugin-transform-react-jsx', { pragma: 'React.createElement' }],
['@babel/plugin-transform-modules-commonjs', { loose: true }],
// The plugin itself, configured for removal
['babel-plugin-transform-react-remove-prop-types', {
mode: 'remove', // Default is 'remove', can also be 'wrap' or 'unsafe-wrap'
ignoreFilenames: ['node_modules'], // Example option: ignore files in node_modules
removeImport: true // Also remove the 'import PropTypes from "prop-types"' statement
}]
]
});
console.log('Transformed Code (Production):\n', result.code);
// Reset NODE_ENV to avoid affecting other tests or processes
process.env.NODE_ENV = 'test';