Babel Plugin for React Native Web Alias and Optimization
The `babel-plugin-react-native-web` package is a Babel plugin designed to optimize applications using `react-native-web`. It works by aliasing `react-native` imports to `react-native-web` and performing tree-shaking to exclude unused modules, thereby reducing bundle size. The current stable version is 0.21.2. This plugin is part of the `react-native-web` ecosystem, which generally sees frequent updates, often tied to new React and React Native versions, indicating an active development and release cadence. Its primary differentiator is enabling existing React Native codebases to run efficiently on the web without significant code changes, by providing a targeted build-time optimization layer. It's crucial for projects aiming for a single codebase across native and web platforms.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'commonjs') when configuring babel-plugin-react-native-web
cause The plugin configuration is malformed, or the options object is missing or not a plain object.fixEnsure the plugin configuration is an array with the plugin name as the first element and an options object as the second element, e.g., `['react-native-web', { commonjs: false }]`. -
Error: `react-native-web` internal paths are not stable and you must not rely on them.
cause Directly importing from `react-native-web/dist/exports/...` instead of `react-native` in your source code.fixAlways import components and APIs from `react-native` (e.g., `import { View, Text } from 'react-native';`). The Babel plugin will handle the internal path rewriting automatically and reliably.
Warnings
- breaking React 19 support was introduced in v0.20.0, which also removed `findNodeHandle` support on web. Projects updating to v0.20.0 or higher must ensure compatibility with React 19 and deprecation of `findNodeHandle`.
- breaking Browser support was reduced in v0.18.0, requiring Safari 10.1+, Edge (Chromium), and dropping support for IE and legacy Android browsers. Additionally, styles are now inserted on module eval, impacting server-side rendering.
- breaking React 18 `createRoot` support and related changes (e.g., `Animated`, `ScrollView` as Class component) were introduced in v0.19.0. Projects using React 18 must ensure their components and usages are compatible.
- breaking Unstable APIs had breaking changes in v0.17.0, specifically regarding `accessibilityRole='menuitem'` and `accessibilityRole='link'` behavior, and `unstable_createElement` inference. These changes affect accessibility and custom element creation.
- breaking `Dimensions`, `Animated`, `VirtualizedList`, and `NativeEventEmitter` had breaking changes in v0.16.0 due to updates from React Native. `NativeEventEmitter` no longer inherits `EventEmitter`.
- gotcha The `commonjs` option in the plugin configuration (e.g., `['react-native-web', { commonjs: true }]`) must match your bundler's module resolution strategy. Misconfiguration can lead to incorrect module resolution or larger bundles.
- breaking React 17 became a peer dependency in v0.15.0. Also, `I18nManager` API changed, requiring `getConstants()` to access `isRTL` and `doLeftAndRightSwapInRTL`.
Install
-
npm install babel-plugin-react-native-web -
yarn add babel-plugin-react-native-web -
pnpm add babel-plugin-react-native-web
Imports
- Babel Plugin Configuration
import plugin from 'babel-plugin-react-native-web'; // Incorrect usage pattern plugins: [plugin]
plugins: [ ["react-native-web", { commonjs: false }] ] - React Native Imports (Pre-transform)
import StyleSheet from 'react-native-web/dist/exports/StyleSheet'; // Don't manually import internal paths import View from 'react-native-web/dist/exports/View';
import { StyleSheet, View } from 'react-native';
Quickstart
// .babelrc or babel.config.js
module.exports = {
presets: ['module:metro-react-native-babel-preset'], // Or other React/TypeScript presets
plugins: [
// ... other plugins
["react-native-web", {
// Set to true if your bundler (e.g., Webpack 4 without module: false)
// resolves CommonJS modules by default. Most modern bundlers use ES modules.
commonjs: false
}]
]
};