如果你应用react native开发了app,会不会想有一个站点呢。如果你想,那么react-native-web就有用武之地了。只有不是平台相干的组件根本都能够复用,包含js款式。更不用说内置的accessibility。

react-native-web比拟偏向于举荐expo的,更多的介绍是对于create-react-app生成的代码的。然而这篇文章是对于曾经能存在的mobile的我的项目而言的。这是一种更急广泛,或者更须要这篇文章的状况。

代码在这里

增加依赖

要是应用react-native-web首先要增加必须的依赖。首先跳转到我的项目的根目录

cd path-to-your-project

先把react-native-web加上

yarn add react-native-web

而后相干依赖

yarn add -D babel-plugin-react-native-web webpack webpack-cli webpack-dev-server html-webpack-plugin react-dom babel-loader url-loader @svgr/webpack

如果你有前端的开发教训的话,看看咱们当初我的项目的构造你会发现少了很多。作为一个单页利用,单页都还没有呢。dev server和打包的老大哥webpack也没有。这些咱们也都要一一加上。
index.html

<!DOCTYPE html><html>  <!-- 略 -->  <body>    <div id="app-root"></div>  </body></html>

这个就是单页利用的那个单页。是作为整个app的承载页。所有的js都运行在这个页面里。

webpack.config.js

// ...const compileNodeModules = [  // 增加须要编译的react-native包].map((moduleName) => path.resolve(appDirectory, `node_modules/${moduleName}`));// ...

webpack是打包工具。开发的时候跑dev server,发生产的时候打生产包。这里须要制订webpack把依赖到的包都编译了。

如果你不这么做的话,大概率你会遇到这个么一个报错。比方你用了react-native-gesture-handler

ERROR in ./node_modules/react-native-gesture-handlerModule parse failed: Unexpected tokenYou may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

而后咱们也会增加所有须要编译的代码。比方index.web.jsApp.web.tsx。还有src目录下的所有代码,以及上文提到的所有的库。

// ...const babelLoaderConfiguration = {  test: /\.js$|tsx?$/,  // Add every directory that needs to be compiled by Babel during the build.  include: [    path.resolve(__dirname, 'index.web.js'), <-- Entry to web project    path.resolve(__dirname, 'App.web.tsx'), // <-- or App.js    path.resolve(__dirname, 'src'), // <-- Main source folder    ...compileNodeModules, // <-- Modules we compiles above  ],// ...

还有一个很重要的文件:index.web.js

这个文件是给上文说的index.html挂载react-native-web的组件的。就如同在index.js看到的要AppRegistry.registerComponent一样。在web开发中也须要注册组件,同时还要挂载组件。
index.web.js

import { AppRegistry } from 'react-native';import { name as appName } from './app.json';import App from './App';if (module.hot) {  module.hot.accept();}AppRegistry.registerComponent(appName, () => App); // 1AppRegistry.runApplication(appName, { // 2  initialProps: {},  rootTag: document.getElementById('app-root'),});

// 1. 和index.js一样,注册组件
// 2. 挂载组件。细节没看,预计是用来调用react-dom来实现的。

不同平台指定代码。比方这里的index.web.js。就是特指给web平台执行的代码。在ios和android也能够别离指定在某个平台执行的代码。比方只在ios执行,能够命名为SomeComp.ios.js。在android的就能够叫做SomeComp.android.js。

另外须要增加一个App.web.tsx

//...      <TouchableOpacity        onPress={() => setCount(count + 1)}        style={styles.button}>        <Text>Click me!</Text>      </TouchableOpacity>      <WebSection title="web title">        <Text>Hello Web</Text>      </WebSection>      <Text>You clicked {count} times!</Text>//...

显著能够看到解决点击的TouchableOpacity和显示文字的Text组件都能够失常应用。

复用代码

YouKnowApp/src/WebSection.tsx这个文件是间接复用的js/components/Section.tsx这个文件。间接用会出问题。

Module parse failed: Unexpected token (11:12)You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file

只有正文掉这一行就好了。

// import { Colors } from 'react-native/Libraries/NewAppScreen';

预计这行代码应用了flow导致的。

Flow是FB开发的一个js的类型加强工具。当初用的曾经很少了,次要是FB本人的很多代码还蕴含了这部分。

解决的方法可能要查阅一下是否存在一个webpack的loader能够专门解决flow代码。

配置Scripts

最初在package.json文件增加脚本执行的命令

    "build": "rm -rf dist/ && webpack --mode=production --config webpack.config.js",    "web": "webpack serve --mode=development --config webpack.config.js"

运行

yarn web

查看http://localhost:8080就能够看到成果了。

后续遇到多平台代码共享的问题再持续更新。