{"id":4531,"url":"https://github.com/inokawa/react-native-react-bridge","last_synced_at":"2025-05-15T12:05:23.126Z","repository":{"id":39582054,"uuid":"311012657","full_name":"inokawa/react-native-react-bridge","owner":"inokawa","description":"An easy way to integrate your React (or Preact/React Native Web) app into React Native app with WebView.","archived":false,"fork":false,"pushed_at":"2025-05-01T19:33:42.000Z","size":12515,"stargazers_count":279,"open_issues_count":20,"forks_count":24,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-01T20:32:46.781Z","etag":null,"topics":["expo","metro","preact","react","react-dom","react-hooks","react-native","react-native-web","webassembly","webview"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/react-native-react-bridge","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/inokawa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["inokawa"]}},"created_at":"2020-11-08T07:57:31.000Z","updated_at":"2025-04-17T02:42:09.000Z","dependencies_parsed_at":"2024-01-08T01:03:35.690Z","dependency_job_id":"3d51babf-cae4-499a-bd09-f04cb71b60d0","html_url":"https://github.com/inokawa/react-native-react-bridge","commit_stats":{"total_commits":352,"total_committers":6,"mean_commits":"58.666666666666664","dds":"0.31818181818181823","last_synced_commit":"6f0f25466901df9b12976dfdb70936edebe52435"},"previous_names":[],"tags_count":40,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inokawa%2Freact-native-react-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inokawa%2Freact-native-react-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inokawa%2Freact-native-react-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/inokawa%2Freact-native-react-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/inokawa","download_url":"https://codeload.github.com/inokawa/react-native-react-bridge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254337613,"owners_count":22054253,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["expo","metro","preact","react","react-dom","react-hooks","react-native","react-native-web","webassembly","webview"],"created_at":"2024-01-05T20:17:15.413Z","updated_at":"2025-05-15T12:05:18.112Z","avatar_url":"https://github.com/inokawa.png","language":"TypeScript","readme":"# react-native-react-bridge\n\n![npm](https://img.shields.io/npm/v/react-native-react-bridge) ![npm](https://img.shields.io/npm/dw/react-native-react-bridge) ![check](https://github.com/inokawa/react-native-react-bridge/workflows/check/badge.svg)\n\nAn easy way to integrate your [React](https://github.com/facebook/react) (or [Preact](https://github.com/preactjs/preact)/[React Native Web](https://github.com/necolas/react-native-web)) app into [React Native](https://github.com/facebook/react-native) app with WebView.\n\n\u003e [!NOTE]\n\u003e You may also like [Expo DOM components](https://docs.expo.dev/guides/dom-components/)\n\n## Why?\n\nIf you'd like to run your React web app in React Native, rewriting it for React Native or using [react-native-web](https://github.com/necolas/react-native-web) is preferred way in most cases.\nBut sometimes rewriting is overkill, when you are just prototyping, or when the app includes something not available on React Native, like rich text editor with contenteditable or complicated logic with WebAssembly.\n\nSo how we run React app in React Native app as it is? It's logically possible if you run your web code in WebView using [react-native-webview](https://github.com/react-native-webview/react-native-webview).\nHowever bundling React code with React Native is troublesome and implementing communication between React Native and WebView is so hard.\n\nThis library gives a bridge to make it easy.\nThis will bundle the whole React app by some additional codes and it will be automatically re-compiled if you edit it.\nYou rarely need to think which code you are editing for React or React Native, like isomorphic.\nThe communication between React app and React Native app will be also simplified by this.\n\n\u003cimg src=\"./examples/ios.gif\" height=\"500px\" /\u003e \u003cimg src=\"./examples/android.gif\" height=\"500px\" /\u003e\n\n## Features\n\n- Create React (or Preact/React Native Web) app bundle for WebView automatically in build process of React Native\n  - All JS modules (with or without JSX/TypeScript) will be bundled with [esbuild](https://github.com/evanw/esbuild).\n  - **NOTE: Only the edits in the entry file of web will invoke rebuild because of the limitation of [metro](https://github.com/facebook/metro)'s build process.**\n- Handle communication between React Native and WebView with React hook style\n  - With `useWebViewMessage` hook, you can subscribe messages from WebView.\n  - With `useNativeMessage` hook, you can subscribe messages from React Native.\n  - `emit` function sends message.\n- Support bundling some assets in web side with [ES6 import syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)\n  - `.json` is imported as an object, like require in Node.js.\n  - `.txt` and `.md` are imported as string, like [raw-loader](https://github.com/webpack-contrib/raw-loader).\n  - `.css` is injected to the HTML head of WebView, like [css-loader](https://github.com/webpack-contrib/css-loader) with [style-loader](https://github.com/webpack-contrib/style-loader).\n  - `.bmp`, `.gif`, `.png`, `.jpg`, `.jpeg`, `.webp` and `.svg` are loaded as base64 encoded url, like [url-loader](https://github.com/webpack-contrib/url-loader).\n  - `.htm` and `.html` are loaded as string, which can be rendered with React's [dangerouslySetInnerHTML](https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml).\n  - `.wasm` is imported like [Node.js](https://nodejs.org/api/esm.html#esm_wasm_modules), which is compatible with [ES Module Integration Proposal for WebAssembly](https://github.com/WebAssembly/esm-integration).\n\nIf you have some feature requests or improvements, please create a [issue](https://github.com/inokawa/react-native-react-bridge/issues) or [PR](https://github.com/inokawa/react-native-react-bridge/pulls).\n\n## Install\n\n```sh\nnpm install react-native-react-bridge react-native-webview\n\n# Necessary only if you render React app in WebView\nnpm install react-dom\n\n# Necessary only if you render Preact app in WebView\n# preact \u003e= 10.0\nnpm install preact\n\n# Necessary only if you render React Native Web app in WebView\nnpm install react-dom react-native-web\n```\n\n### Requirements\n\n- react \u003e= 16.14\n- react-native \u003e= 0.60\n\n## Usage\n\n### 1. Fix `metro.config.js` to use babelTransformer from this library.\n\n#### React Native\n\n```javascript\nmodule.exports = {\n  transformer: {\n    // This detects entry points of React app and transforms them\n    // For the other files this will switch to use default `metro-react-native-babel-transformer` for transforming\n    babelTransformerPath: require.resolve('react-native-react-bridge/lib/plugin'),\n    ...\n  },\n/*\n  // optional config\n  rnrb: {\n    // Set `true` if you use Preact in web side.\n    // This will alias imports from `react` and `react-dom` to `preact/compat` automatically.\n    preact: true,\n    // Set `true` if you use react-native-web in web side.\n    // This will alias imports from `react-native` to `react-native-web` automatically.\n    web: true\n  },\n*/\n  ...\n};\n```\n\n#### Expo\n\n```javascript\nconst { getDefaultConfig } = require(\"expo/metro-config\");\n\nconst config = getDefaultConfig(__dirname);\n\nconfig.transformer.babelTransformerPath = require.resolve(\n  \"react-native-react-bridge/lib/plugin\"\n);\n\nmodule.exports = config;\n```\n\n#### Projects with Multiple Transformers\n\nIf your project at some point requires a metro configuration with additional transformers, consider making a separate `customTransformer.js` file in the project root with logic for delegating files types to the appropriate transformer, and modifying `metro.config.js` file to reference the customer transformer file. For example, if you are using `react-native-svg-transformer`, this would be your custom transformer file:\n\n```js\n// root/customTransformer.js\nconst reactNativeReactBridgeTransformer = require(\"react-native-react-bridge/lib/plugin\");\nconst svgTransformer = require(\"react-native-svg-transformer\");\n\nmodule.exports.transform = function ({ src, filename, options }) {\n  if (filename.endsWith(\".svg\")) {\n    return svgTransformer.transform({ src, filename, options });\n  } else {\n    return reactNativeReactBridgeTransformer.transform({\n      src,\n      filename,\n      options,\n    });\n  }\n};\n```\n\nAnd this would be your metro config:\n\n```js\n// root/metro.config.js\nconst { getDefaultConfig } = require(\"metro-config\");\n\nmodule.exports = (async () =\u003e {\n  const {\n    resolver: { sourceExts, assetExts },\n  } = await getDefaultConfig();\n  return {\n    transformer: {\n      babelTransformerPath: require.resolve(\"./customTransformer.js\"),\n    },\n    resolver: {\n      assetExts: assetExts.filter((ext) =\u003e ext !== \"svg\"),\n      sourceExts: [...sourceExts, \"svg\"],\n    },\n  };\n})();\n```\n\n#### Custom Esbuild options\n\nTo support custom Esbuild options, we can use Multiple Transformers method and replace the customTransformer.js file with the following code:\n\n```tsx\n// root/customTransformer.js\nconst reactNativeReactBridgeTransformer = require(\"react-native-react-bridge/lib/plugin\");\n\nconst esbuildOptions = {\n  pluglins: [],\n};\nconst transform =\n  reactNativeReactBridgeTransformer.createTransformer(esbuildOptions);\n\nmodule.exports.transform = function ({ src, filename, options }) {\n  return transform({ src, filename, options });\n};\n```\n\n### 2. Make entry file for web app.\n\n- If you use React, React Native Web or Preact with React alias, import modules `react-native-react-bridge/lib/web`.\n- If you use Preact, import modules from `react-native-react-bridge/lib/web/preact`.\n\n```jsx\n// WebApp.js\n\nimport React, { useState } from \"react\";\nimport {\n  webViewRender,\n  emit,\n  useNativeMessage,\n} from \"react-native-react-bridge/lib/web\";\n// Importing css is supported\nimport \"./example.css\";\n// Images are loaded as base64 encoded string\nimport image from \"./foo.png\";\n\nconst Root = () =\u003e {\n  const [data, setData] = useState(\"\");\n  // useNativeMessage hook receives message from React Native\n  useNativeMessage((message) =\u003e {\n    if (message.type === \"success\") {\n      setData(message.data);\n    }\n  });\n  return (\n    \u003cdiv\u003e\n      \u003cimg src={image} /\u003e\n      \u003cdiv\u003e{data}\u003c/div\u003e\n      \u003cbutton\n        onClick={() =\u003e {\n          // emit sends message to React Native\n          //   type: event name\n          //   data: some data which will be serialized by JSON.stringify\n          emit({ type: \"hello\", data: 123 });\n        }}\n      /\u003e\n    \u003c/div\u003e\n  );\n};\n\n// This statement is detected by babelTransformer as an entry point\n// All dependencies are resolved, compressed and stringified into one file\nexport default webViewRender(\u003cRoot /\u003e);\n```\n\n### 3. Use the entry file in your React Native app with WebView.\n\n```jsx\n// App.js\n\nimport React from \"react\";\nimport WebView from \"react-native-webview\";\nimport { useWebViewMessage } from \"react-native-react-bridge\";\nimport webApp from \"./WebApp\";\n\nconst App = () =\u003e {\n  // useWebViewMessage hook create props for WebView and handle communication\n  // The argument is callback to receive message from React\n  const { ref, onMessage, emit } = useWebViewMessage((message) =\u003e {\n    // emit sends message to React\n    //   type: event name\n    //   data: some data which will be serialized by JSON.stringify\n    if (message.type === \"hello\" \u0026\u0026 message.data === 123) {\n      emit({ type: \"success\", data: \"succeeded!\" });\n    }\n  });\n\n  return (\n    \u003cWebView\n      // ref, source and onMessage must be passed to react-native-webview\n      ref={ref}\n      // Pass the source code of React app\n      source={{ html: webApp }}\n      onMessage={onMessage}\n    /\u003e\n  );\n};\n```\n\n### 4. Start your React Native app!\n\n## Documentation\n\n- [API reference](./docs/API.md)\n\n### FAQs\n\n#### My webview displays a blank page.\n\nreact-native-webview has some ways to show errors occurred in webview. This may be helpful to troubleshoot it.\n\nhttps://github.com/react-native-webview/react-native-webview/blob/master/docs/Reference.md#onerror\n\n## Demo\n\nThis repository includes demo app.\n\n```sh\ngit clone git@github.com:inokawa/react-native-react-bridge.git\ncd examples/DemoApp\nnpm install\nnpm run ios # or npm run android\n```\n\n## Contribute\n\nAll contributions are welcome.\nIf you find a problem, feel free to create an [issue](https://github.com/inokawa/react-native-react-bridge/issues) or a [PR](https://github.com/inokawa/react-native-react-bridge/pulls).\n\n### Making a Pull Request\n\n1. Fork this repo.\n2. Run `npm install`.\n3. Commit your fix.\n4. Add tests to cover the fix.\n5. Make a PR and confirm all the CI checks passed.\n","funding_links":["https://github.com/sponsors/inokawa"],"categories":["Components","Packages","Uncategorized","React Native [🔝](#readme)"],"sub_categories":["Build \u0026 Development","Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finokawa%2Freact-native-react-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finokawa%2Freact-native-react-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finokawa%2Freact-native-react-bridge/lists"}