Add React Native Web support to Vite by removing Flow types, aliasing react-native to react-native-web and transforming .js files as .jsx files using ESBuild.
Just install it:
npm i vite-plugin-react-native-web -Dimport reactNativeWeb from "vite-plugin-react-native-web";
export default defineConfig({
plugins: [reactNativeWeb({ ... })],
});If you are getting errors please report them in the issues section.
The following variables are defined in the transformed files: (inferred during Vite's build process)
globalasglobalThis__DEV__asprocess.env.NODE_ENV === 'development'process.env.NODE_ENVasprocess.env.NODE_ENVprocess.env.EXPO_OSas"web"
This plugin requires react-native-web as a peer dependency. You must install it in the node_modules directory of the app where you use this plugin.
Note: If you are using pnpm or a workspace setup, peer dependencies may be installed in nested
node_modulesfolders by default. To avoid issues, ensurereact-native-webis installed in the app's ownnode_modulesdirectory:
pnpm add react-native-webThe plugin resolves inline-style-prefixer through react-native-web, so it no longer has to be installed in the app.
The plugin also configures every environment that runs on the server, such as Vite's ssr environment:
react-native-weband every dependency that depends onreact-nativeorreact-native-webare bundled instead of being loaded by Node.js. Theirreact-nativeimports are aliased and compiled like in the browser. The dependencies are found by crawling yourpackage.json.- In development, JSX and Flow in those dependencies are compiled, and the CommonJS helpers of
react-native-webare pre-bundled, so Vite's module runner can execute them.
Render through AppRegistry on both sides, so the server produces the same wrapper the browser hydrates:
// server
AppRegistry.registerComponent('App', () => App)
const { element, getStyleElement } = AppRegistry.getApplication('App')
const html = renderToString(element)
const css = renderToStaticMarkup(getStyleElement())
// browser
AppRegistry.registerComponent('App', () => App)
AppRegistry.runApplication('App', { rootTag: document.getElementById('root'), hydrate: true })The SSR example shows a complete setup with React Navigation, a development server with HMR and a production server.
Dependencies that mix CommonJS files into an ES module package, such as @expo/vector-icons, cannot run in Vite's development module runner. They work in vite build. To bundle the server build completely, for example for a container without node_modules, set environments.ssr.resolve.noExternal to true for vite build.
- React + TypeScript + Vite + React Native Web Example
- React + TypeScript + Expo + Vite + React Native Web Example
- React + TypeScript + Vite + React Native Web SSR Example
Please feel free to contribute to this project. Just fork it and submit a PR.
MIT