vite-plugin-react-native 0.0.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,94 +1,166 @@
1
1
  # vite-plugin-react-native
2
2
 
3
- Vite 插件,用于在 Web 环境中使用 React Native 代码,提供 React Native 到 Web 的兼容性支持。
3
+ **让 React Native Vite 上完美跑 Web** —— 一套插件搞定 RN 到 Web 的别名、虚拟模块、构建与依赖优化,无需 Rolldown,兼容 Vite 4~7。
4
4
 
5
- ## 功能特性
5
+ ## 定位
6
6
 
7
- - 自动将 `react-native` 替换为 `react-native-web`
8
- - 支持 React Native 扩展名解析(`.web.js`, `.native.js` 等)
9
- - 提供 React Native 库的 Web 兼容实现:
10
- - `react-native-safe-area-context` - SafeArea 组件和 Hooks
11
- - `react-native-screens` - Screen 组件
12
- - `use-latest-callback` - 回调 Hook
13
- - 支持 ESM 和 CommonJS 双模式
14
- - ✅ 自动配置 Vite 优化选项
7
+ - 同一套 RN 代码,用 **Vite** 构建 Web 端,开发体验与构建速度兼顾。
8
+ - 自动处理 `react-native` `react-native-web`、常用 RN 库的 Web 占位实现、以及 Reanimated / Expo / CSS Interop 等兼容。
9
+ - 可选集成 [react-native-router-dom](https://www.npmjs.com/package/react-native-router-dom),未安装时不影响使用。
10
+
11
+ ## 功能概览
12
+
13
+ | 能力 | 说明 |
14
+ |------|------|
15
+ | **react-native → react-native-web** | 别名 + 扩展名 `.web.*` 优先解析 |
16
+ | **react-native-safe-area-context** | 虚拟模块,Web 下 SafeAreaProvider / useSafeAreaInsets 等 |
17
+ | **react-native-screens** | 虚拟模块,Screen / ScreenContainer / enableScreens 等 |
18
+ | **react-native-gesture-handler** | 虚拟模块,GestureHandlerRootView / GestureDetector 等占位,避免 Web 报错 |
19
+ | **react-native-router-dom** | 可选:安装则自动解析并参与预构建 |
20
+ | **react-native-css-interop** | 自动修补 doctor 检查,保证 Vite 下可构建 |
21
+ | **define** | `__DEV__`、`process.env.NODE_ENV`、`EXPO_OS`、`_WORKLET` 等 |
22
+ | **optimizeDeps** | 预置 RN 生态常用包,并与用户配置合并 |
15
23
 
16
24
  ## 安装
17
25
 
18
26
  ```bash
19
- npm install vite-plugin-react-native
27
+ npm install vite-plugin-react-native react-native-web react react-dom
20
28
  # 或
21
- yarn add vite-plugin-react-native
22
- # 或
23
- pnpm add vite-plugin-react-native
29
+ pnpm add vite-plugin-react-native react-native-web react react-dom
24
30
  ```
25
31
 
26
- ## 使用方法
32
+ 可选(按需):
33
+
34
+ - 路由:`react-native-router-dom`
35
+ - 动画:`react-native-reanimated`
36
+ - 样式:`react-native-css-interop`、NativeWind 等
27
37
 
28
- ### ESM 模式(推荐)
38
+ ## 使用
29
39
 
30
- ```javascript
31
- // vite.config.js 或 vite.config.ts
40
+ ### 最简配置
41
+
42
+ ```ts
43
+ // vite.config.ts
32
44
  import { defineConfig } from 'vite';
33
45
  import { reactNative } from 'vite-plugin-react-native';
34
46
 
35
47
  export default defineConfig({
36
- plugins: [
37
- reactNative(),
38
- ],
48
+ plugins: [reactNative()],
39
49
  });
40
50
  ```
41
51
 
42
- ### CommonJS 模式
52
+ ### 推荐:配合 React 插件(Fast Refresh)
43
53
 
44
- ```javascript
45
- // vite.config.js
46
- const { defineConfig } = require('vite');
47
- const { reactNative } = require('vite-plugin-react-native');
54
+ ```ts
55
+ import { defineConfig } from 'vite';
56
+ import react from '@vitejs/plugin-react';
57
+ import { reactNative } from 'vite-plugin-react-native';
48
58
 
49
- module.exports = defineConfig({
50
- plugins: [
51
- reactNative(),
52
- ],
59
+ export default defineConfig({
60
+ plugins: [react(), reactNative()],
53
61
  });
54
62
  ```
55
63
 
56
- ## 支持情况
64
+ ## 兼容的 React Native 库
65
+
66
+ - `react-native` → 自动替换为 `react-native-web`
67
+ - `react-native-safe-area-context` → 虚拟 Web 实现
68
+ - `react-native-screens` → 虚拟 Web 实现
69
+ - `react-native-gesture-handler` → 虚拟 Web 占位(手势在 Web 上为透传)
70
+ - `react-native-router-dom` → 可选,安装后自动解析
71
+ - 其他通过 `optimizeDeps` 与别名支持的库:reanimated、css-interop、inline-style-prefixer 等
72
+
73
+ ## 与社区插件能力对比
74
+
75
+ 与 [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 生态兼容上更完整。**
76
+
77
+ | 能力 | rnw-web | rnw | 本插件 |
78
+ |------|---------|-----|--------|
79
+ | **react-native → react-native-web** | ✅ alias | ✅ alias | ✅ 虚拟模块(含 ReactNativeVersion) |
80
+ | **resolve 扩展名 .web.* 优先** | ✅ | ✅ | ✅ |
81
+ | **define(__DEV__、EXPO_OS、_WORKLET 等)** | ✅ | ✅ 更全(global.Error 等) | ✅ |
82
+ | **Vite 8 rolldownOptions** | ✅ 仅 rolldown | ✅ 按版本分支 | ✅ 按版本分支(≥8 用 rolldown) |
83
+ | **Vite 4~7 esbuildOptions** | ❌ | ✅ | ✅ |
84
+ | **Flow 剥离** | ✅ Rolldown 插件(code 含 @flow) | ✅ Vite 插件 + esbuild/rolldown 插件 | ✅ Rolldown 插件 + transform 对 node_modules |
85
+ | **treeshake 修复(css-interop / expo)** | ✅ expo-modules-core | ✅ css-interop / expo | ✅ 同左 |
86
+ | **css-interop doctor 替换** | ❌ | ✅ | ✅ |
87
+ | **Reanimated webUtils ESM 转换** | ❌ | ✅(export let + require → ESM) | ✅ 仅 production 构建时转换 |
88
+ | **.js 当 JSX 处理** | ✅ moduleTypes | ✅ 独立插件 treat-js-as-jsx(oxc/esbuild) | ✅ 仅对 @react-native 的 .js 做 esbuild JSX |
89
+ | **虚拟模块** | ❌ | ❌ | ✅ safe-area / screens / gesture-handler / openURLInBrowser |
90
+ | **react-native 补 ReactNativeVersion** | ❌ | ❌ | ✅ |
91
+ | **optimizeDeps.include** | ✅ 固定 ['react-native-web'] | ✅ 未显式列 | ✅ **按项目 package.json 动态**,避免未安装包报错 |
92
+ | **resolve 别名** | ✅ 仅 react-native | ✅ 仅 react-native | ✅ react-native 子路径、router-dom、inline-style-prefixer、css-in-js-utils、Libraries/EventEmitter |
93
+ | **require(./assets/...) → import** | ❌ | ❌ | ✅ 对 @react-native 等 |
94
+ | **内置 @vitejs/plugin-react** | ❌ | ✅ 一并返回 | ❌ 用户自加,更灵活 |
95
+ | **commonjs 插件** | ❌ | ✅ | ❌ |
96
+ | **可选 react-native-router-dom** | ❌ | ❌ | ✅ 安装则解析并参与预构建 |
97
+
98
+ **结论**:本插件在「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 行为一致。
99
+
100
+ ## 业界方案与兼容性说明
101
+
102
+ ### 有没有「完美方案」?
103
+
104
+ - **官方路线**:Expo 当前推荐用 **Metro** 打 Web(`npx expo export --platform web`),与 RN 同一套构建,兼容性最好、踩坑最少。
105
+ - **Vite 路线**:社区方案(本插件、vite-plugin-react-native-web、vite-plugin-rnw 等),优势是 Vite 的 dev/构建速度和生态,代价是 RN 生态里 CJS/Flow/require 等需要逐类兼容,**没有一家能保证「所有 RN 库零配置」**。
106
+ - 本插件的策略:在参考上述社区插件的基础上,对**已遇到的**问题做虚拟模块、resolve 别名、transform 三类修补;新引入的库若报错,可按同一套路扩展(见下方兼容表与「新库报错怎么办」)。
107
+
108
+ ### 常见库兼容情况(你可能会用到的)
109
+
110
+ | 库 | 本插件支持 | 说明 |
111
+ |----|------------|------|
112
+ | react-native-safe-area-context | ✅ 虚拟模块 | Web 下提供 SafeAreaProvider / useSafeAreaInsets 等占位 |
113
+ | react-native-screens | ✅ 虚拟模块 | Web 下 Screen / ScreenContainer 等占位 |
114
+ | react-native-gesture-handler | ✅ 虚拟模块 | Web 下 GestureHandlerRootView / GestureDetector 占位 |
115
+ | react-native-router-dom | ✅ 别名 + 预构建 | 安装后自动解析,可选 |
116
+ | react-native-reanimated | ✅ 已处理 | 有 Web 版;production 构建时自动转换 webUtils 的 export let + require 为 ESM |
117
+ | react-native-svg | ✅ 一般可用 | 官方有 Web 支持,多数情况直接用;遇错再 resolve / transpile |
118
+ | react-native-fetch-xhr / react-native-hox / react-native-i18njs / react-native-system-ui | ✅ 一般可用 | 纯 JS 或 polyfill,无内置专门处理也多能跑;遇错按下方「新库报错怎么办」补 |
119
+ | react-native-localize | ⚠️ 需自建占位 | Web 无原生 API,需自建虚拟模块或 stub(插件未内置) |
120
+ | @react-native/new-app-screen 等 | ✅ 已处理 | Flow/JSX/require(assets)/openURLInBrowser 等已做兼容 |
121
+
122
+ - **✅**:插件内已有专门处理,或该库在 Web 上多数情况可直接用;遇错按「新库报错怎么办」三类套路补即可。
123
+ - **⚠️**:仅 react-native-localize 等依赖原生能力的库需在 Web 上自建占位,其余均属「已覆盖」。
124
+
125
+ **Demo 验证**:仓库内 `demo/` 已引入上表所列库(含 new-app-screen、safe-area、screens、gesture-handler、router-dom、reanimated、svg、localize、fetch-xhr、hox、i18njs、system-ui),并参与构建。在项目根目录执行:
57
126
 
58
- ### 兼容的 React Native 库
127
+ ```bash
128
+ cd demo && npm install && npm run build
129
+ ```
130
+
131
+ 通过即表示上述库在当前插件下可正常打包;开发态可用 `npm run dev` 验证。
132
+
133
+ **Demo 运行时的控制台告警说明**(不影响功能,可忽略或按下方在依赖库中修复):
59
134
 
60
- - `react-native` 自动替换为 `react-native-web`
61
- - ✅ `react-native-safe-area-context` → Web 兼容实现
62
- - `react-native-screens` Web 兼容实现
63
- - `use-latest-callback` Web 兼容实现
135
+ | 告警 | 原因 | 处理方式 |
136
+ |------|------|----------|
137
+ | `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'`(或任意大写开头的名字)后重新构建即可消除。 |
138
+ | `props.pointerEvents is deprecated. Use style.pointerEvents` | 来自 React Navigation 或 react-native 的弃用提示,某处把 `pointerEvents` 作为 prop 传递而非放在 `style` 里。 | 需在 **@react-navigation** 或 **react-native** 依赖中按官方迁移方式改为 `style.pointerEvents`,或等待依赖库发版修复。 |
64
139
 
65
- ### Vite 版本支持
140
+ ### 新库报错怎么办?
66
141
 
67
- - Vite 4.x
68
- - Vite 5.x
69
- - Vite 6.x
70
- - Vite 7.x
142
+ 1. **缺导出 / 找不到模块** → 在 `src/virtuals.ts` 为该模块或路径做虚拟实现(参考 `openURLInBrowser`、`ReactNativeVersion`)。
143
+ 2. **CJS default 报错(xxx.default is not a function)** → 在 `src/config.ts` 的 `buildResolveAlias` 里为该包的 `lib/` 或具体路径做别名到 `es/`(参考 inline-style-prefixer、css-in-js-utils)。
144
+ 3. **Flow / JSX 在 .js 里 / require is not defined** → 在 `src/index.ts` 的 transform 里扩展:Flow 剥离、对含 JSX 的 .js 用 esbuild 编译、`require('./assets/...')` 转 import(参考 @react-native/new-app-screen)。
71
145
 
72
- ## 工作原理
146
+ 按上述三类处理,大部分 RN 库在 Web 上的报错都能系统性地修掉,而不是「永远在救火」。
73
147
 
74
- 该插件会:
148
+ ## Vite 版本
75
149
 
76
- 1. **别名替换**:将 `react-native` 自动替换为 `react-native-web`
77
- 2. **虚拟模块**:为 React Native 特定库提供 Web 兼容的虚拟实现
78
- 3. **扩展名解析**:支持 React Native 的文件扩展名约定(`.web.js`, `.native.js` 等)
79
- 4. **依赖优化**:自动配置 Vite 的依赖预构建选项
150
+ - Vite 4.x / 5.x / 6.x / 7.x
151
+
152
+ ## 工作原理简述
153
+
154
+ 1. **别名**:`react-native` → `react-native-web`,以及 EventEmitter、inline-style-prefixer 等路径。
155
+ 2. **虚拟模块**:对 safe-area-context、screens、gesture-handler 提供 Web 实现或占位,无需安装对应 native 包即可跑 Web。
156
+ 3. **扩展名**:优先解析 `.web.mjs`、`.web.js`、`.web.ts`、`.web.tsx`、`.web.jsx`。
157
+ 4. **构建与预构建**:commonjs 兼容、依赖预构建列表与用户配置合并;可选路由包仅在已安装时加入。
80
158
 
81
159
  ## 开发
82
160
 
83
161
  ```bash
84
- # 安装依赖
85
162
  npm install
86
-
87
- # 构建
88
163
  npm run build
89
-
90
- # 发布前会自动构建
91
- npm publish
92
164
  ```
93
165
 
94
166
  ## 许可证
@@ -97,7 +169,6 @@ ISC
97
169
 
98
170
  ## 参与贡献
99
171
 
100
- 1. Fork 本仓库
101
- 2. 新建 Feat_xxx 分支
102
- 3. 提交代码
103
- 4. 新建 Pull Request
172
+ 1. Fork 本仓库
173
+ 2. 新建 `Feat_xxx` 分支
174
+ 3. 提交代码并新建 Pull Request