# vite-plugin-react-native **Repository Path**: ws18250840411/vite-plugin-react-native ## Basic Information - **Project Name**: vite-plugin-react-native - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-10 - **Last Updated**: 2026-03-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # vite-plugin-react-native **让 React Native 在 Vite 上完美跑 Web** —— 一套插件搞定 RN 到 Web 的别名、虚拟模块、构建与依赖优化,无需 Rolldown,兼容 Vite 4~7。 ## 定位 - 同一套 RN 代码,用 **Vite** 构建 Web 端,开发体验与构建速度兼顾。 - 自动处理 `react-native` → `react-native-web`、常用 RN 库的 Web 占位实现、以及 Reanimated / Expo / CSS Interop 等兼容。 - 可选集成 [react-native-router-dom](https://www.npmjs.com/package/react-native-router-dom),未安装时不影响使用。 ## 功能概览 | 能力 | 说明 | |------|------| | **react-native → react-native-web** | 别名 + 扩展名 `.web.*` 优先解析 | | **react-native-safe-area-context** | 虚拟模块,Web 下 SafeAreaProvider / useSafeAreaInsets 等 | | **react-native-screens** | 虚拟模块,Screen / ScreenContainer / enableScreens 等 | | **react-native-gesture-handler** | 虚拟模块,GestureHandlerRootView / GestureDetector 等占位,避免 Web 报错 | | **react-native-router-dom** | 可选:安装则自动解析并参与预构建 | | **react-native-css-interop** | 自动修补 doctor 检查,保证 Vite 下可构建 | | **define** | `__DEV__`、`process.env.NODE_ENV`、`EXPO_OS`、`_WORKLET` 等 | | **optimizeDeps** | 预置 RN 生态常用包,并与用户配置合并 | ## 安装 ```bash npm install vite-plugin-react-native react-native-web react react-dom # 或 pnpm add vite-plugin-react-native react-native-web react react-dom ``` 可选(按需): - 路由:`react-native-router-dom` - 动画:`react-native-reanimated` - 样式:`react-native-css-interop`、NativeWind 等 ## 使用 ### 最简配置 ```ts // vite.config.ts import { defineConfig } from 'vite'; import { reactNative } from 'vite-plugin-react-native'; export default defineConfig({ plugins: [reactNative()], }); ``` ### 推荐:配合 React 插件(Fast Refresh) ```ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import { reactNative } from 'vite-plugin-react-native'; export default defineConfig({ plugins: [react(), reactNative()], }); ``` ## 兼容的 React Native 库 - `react-native` → 自动替换为 `react-native-web` - `react-native-safe-area-context` → 虚拟 Web 实现 - `react-native-screens` → 虚拟 Web 实现 - `react-native-gesture-handler` → 虚拟 Web 占位(手势在 Web 上为透传) - `react-native-router-dom` → 可选,安装后自动解析 - 其他通过 `optimizeDeps` 与别名支持的库:reanimated、css-interop、inline-style-prefixer 等 ## 与社区插件能力对比 与 [vite-plugin-react-native-web](https://github.com/Bram-dc/vite-plugin-react-native-web)(下称 **rnw-web**)、[vite-plugin-rnw](https://github.com/dannyhw/vite-plugin-rnw)(下称 **rnw**)对比如下。**我们已具备两者核心能力,并在虚拟模块、别名、动态 optimizeDeps、RN 生态兼容上更完整。** | 能力 | rnw-web | rnw | 本插件 | |------|---------|-----|--------| | **react-native → react-native-web** | ✅ alias | ✅ alias | ✅ 虚拟模块(含 ReactNativeVersion) | | **resolve 扩展名 .web.* 优先** | ✅ | ✅ | ✅ | | **define(__DEV__、EXPO_OS、_WORKLET 等)** | ✅ | ✅ 更全(global.Error 等) | ✅ | | **Vite 8 rolldownOptions** | ✅ 仅 rolldown | ✅ 按版本分支 | ✅ 按版本分支(≥8 用 rolldown) | | **Vite 4~7 esbuildOptions** | ❌ | ✅ | ✅ | | **Flow 剥离** | ✅ Rolldown 插件(code 含 @flow) | ✅ Vite 插件 + esbuild/rolldown 插件 | ✅ Rolldown 插件 + transform 对 node_modules | | **treeshake 修复(css-interop / expo)** | ✅ expo-modules-core | ✅ css-interop / expo | ✅ 同左 | | **css-interop doctor 替换** | ❌ | ✅ | ✅ | | **Reanimated webUtils ESM 转换** | ❌ | ✅(export let + require → ESM) | ✅ 仅 production 构建时转换 | | **.js 当 JSX 处理** | ✅ moduleTypes | ✅ 独立插件 treat-js-as-jsx(oxc/esbuild) | ✅ 仅对 @react-native 的 .js 做 esbuild JSX | | **虚拟模块** | ❌ | ❌ | ✅ safe-area / screens / gesture-handler / openURLInBrowser | | **react-native 补 ReactNativeVersion** | ❌ | ❌ | ✅ | | **optimizeDeps.include** | ✅ 固定 ['react-native-web'] | ✅ 未显式列 | ✅ **按项目 package.json 动态**,避免未安装包报错 | | **resolve 别名** | ✅ 仅 react-native | ✅ 仅 react-native | ✅ react-native 子路径、router-dom、inline-style-prefixer、css-in-js-utils、Libraries/EventEmitter | | **require(./assets/...) → import** | ❌ | ❌ | ✅ 对 @react-native 等 | | **内置 @vitejs/plugin-react** | ❌ | ✅ 一并返回 | ❌ 用户自加,更灵活 | | **commonjs 插件** | ❌ | ✅ | ❌ | | **可选 react-native-router-dom** | ❌ | ❌ | ✅ 安装则解析并参与预构建 | **结论**:本插件在「react-native → web」基础能力上与 rnw-web / rnw 对齐,并**额外提供**:虚拟模块、ReactNativeVersion、动态 optimizeDeps.include、更多 resolve 别名、require(assets)→import、@react-native 的 Flow+JSX 处理;**Reanimated webUtils** 在 production 构建时自动将 `export let` + try/catch + `require` 转为 ESM,与 rnw 行为一致。 ## 业界方案与兼容性说明 ### 有没有「完美方案」? - **官方路线**:Expo 当前推荐用 **Metro** 打 Web(`npx expo export --platform web`),与 RN 同一套构建,兼容性最好、踩坑最少。 - **Vite 路线**:社区方案(本插件、vite-plugin-react-native-web、vite-plugin-rnw 等),优势是 Vite 的 dev/构建速度和生态,代价是 RN 生态里 CJS/Flow/require 等需要逐类兼容,**没有一家能保证「所有 RN 库零配置」**。 - 本插件的策略:在参考上述社区插件的基础上,对**已遇到的**问题做虚拟模块、resolve 别名、transform 三类修补;新引入的库若报错,可按同一套路扩展(见下方兼容表与「新库报错怎么办」)。 ### 常见库兼容情况(你可能会用到的) | 库 | 本插件支持 | 说明 | |----|------------|------| | react-native-safe-area-context | ✅ 虚拟模块 | Web 下提供 SafeAreaProvider / useSafeAreaInsets 等占位 | | react-native-screens | ✅ 虚拟模块 | Web 下 Screen / ScreenContainer 等占位 | | react-native-gesture-handler | ✅ 虚拟模块 | Web 下 GestureHandlerRootView / GestureDetector 占位 | | react-native-router-dom | ✅ 别名 + 预构建 | 安装后自动解析,可选 | | react-native-reanimated | ✅ 已处理 | 有 Web 版;production 构建时自动转换 webUtils 的 export let + require 为 ESM | | react-native-svg | ✅ 一般可用 | 官方有 Web 支持,多数情况直接用;遇错再 resolve / transpile | | react-native-fetch-xhr / react-native-hox / react-native-i18njs / react-native-system-ui | ✅ 一般可用 | 纯 JS 或 polyfill,无内置专门处理也多能跑;遇错按下方「新库报错怎么办」补 | | react-native-localize | ⚠️ 需自建占位 | Web 无原生 API,需自建虚拟模块或 stub(插件未内置) | | @react-native/new-app-screen 等 | ✅ 已处理 | Flow/JSX/require(assets)/openURLInBrowser 等已做兼容 | - **✅**:插件内已有专门处理,或该库在 Web 上多数情况可直接用;遇错按「新库报错怎么办」三类套路补即可。 - **⚠️**:仅 react-native-localize 等依赖原生能力的库需在 Web 上自建占位,其余均属「已覆盖」。 **Demo 验证**:仓库内 `demo/` 已引入上表所列库(含 new-app-screen、safe-area、screens、gesture-handler、router-dom、reanimated、svg、localize、fetch-xhr、hox、i18njs、system-ui),并参与构建。在项目根目录执行: ```bash cd demo && npm install && npm run build ``` 通过即表示上述库在当前插件下可正常打包;开发态可用 `npm run dev` 验证。 **Demo 运行时的控制台告警说明**(不影响功能,可忽略或按下方在依赖库中修复): | 告警 | 原因 | 处理方式 | |------|------|----------| | `Got a component with the name 'le' for the screen '/'` | `react-native-router-dom` 内部传给 React Navigation 的 Screen 的渲染组件在打包后被压缩成短名 `le`,React Navigation 要求组件名首字母大写。 | 在 **react-native-router-dom** 源码中,找到传给 `Screen` 的 component(负责渲染 `route.element` 的那层包装组件),为其设置 `displayName = 'RouteScreen'`(或任意大写开头的名字)后重新构建即可消除。 | | `props.pointerEvents is deprecated. Use style.pointerEvents` | 来自 React Navigation 或 react-native 的弃用提示,某处把 `pointerEvents` 作为 prop 传递而非放在 `style` 里。 | 需在 **@react-navigation** 或 **react-native** 依赖中按官方迁移方式改为 `style.pointerEvents`,或等待依赖库发版修复。 | ### 新库报错怎么办? 1. **缺导出 / 找不到模块** → 在 `src/virtuals.ts` 为该模块或路径做虚拟实现(参考 `openURLInBrowser`、`ReactNativeVersion`)。 2. **CJS default 报错(xxx.default is not a function)** → 在 `src/config.ts` 的 `buildResolveAlias` 里为该包的 `lib/` 或具体路径做别名到 `es/`(参考 inline-style-prefixer、css-in-js-utils)。 3. **Flow / JSX 在 .js 里 / require is not defined** → 在 `src/index.ts` 的 transform 里扩展:Flow 剥离、对含 JSX 的 .js 用 esbuild 编译、`require('./assets/...')` 转 import(参考 @react-native/new-app-screen)。 按上述三类处理,大部分 RN 库在 Web 上的报错都能系统性地修掉,而不是「永远在救火」。 ## Vite 版本 - Vite 4.x / 5.x / 6.x / 7.x / 8.x - 仓库内 `demo/` 已在 **Vite 6、7、8** 下验证通过(`npm run build`);开发态 `npm run dev` 可本地自测。 ## 工作原理简述 1. **别名**:`react-native` → `react-native-web`,以及 EventEmitter、inline-style-prefixer 等路径。 2. **虚拟模块**:对 safe-area-context、screens、gesture-handler 提供 Web 实现或占位,无需安装对应 native 包即可跑 Web。 3. **扩展名**:优先解析 `.web.mjs`、`.web.js`、`.web.ts`、`.web.tsx`、`.web.jsx`。 4. **构建与预构建**:commonjs 兼容、依赖预构建列表与用户配置合并;可选路由包仅在已安装时加入。 ## 开发 ```bash npm install npm run build ``` ## 许可证 ISC ## 参与贡献 1. Fork 本仓库 2. 新建 `Feat_xxx` 分支 3. 提交代码并新建 Pull Request