The purpose and significance of React Web are very clear: Let React Native code run on the Web and let a set of code run on various mobile terminals. For the front-end and business, this is a qualitative improvement in development efficiency. In the early stages of the project, we also consulted the React team with similar questions. The core classmate of their team @vjeux also thought this was a very cool thing and what they wanted to do in the future. Maybe when react Native for Android, react web may be released. (YY)
Technical Architecture
There are several adaptation solutions based on React Native:
1. Develop a Bridge standard, and RN and RW each implement this set of standards in the optimal way.
For example, based on Flex layout, we implement a consistent set of Flex Components, <Flex>, <Cell>, etc.
2. Completely align with RN, RW implements all the APIs that RN can implement.
In the discussion, the latter was finally chosen.
Because of the concept of React Web, let React Native code run on the web side, it determines that RW is just a construction and packaging tool, separated from RN, and the implementation of RW is not of much significance. Then the overall technical direction is very clear: to implement RN consistent Style, Component and API, and finally compile it into a web version through the construction tool.
Example
Let’s take a look at the creation process of React Web Project:
Step 1: Install React web and perform related configuration
This step is mainly to install react-web packages and related dependencies, and configure webpack packaging scripts.
In order to simplify this step, we have developed the command line tool react-web-cli, which only requires execution of two lines of command. At the same time, the command line tool also supports starting the debugging server, packaging and other functions, which will be introduced later.
Install cli tools:
npm install react-web-cli -g
Install and configure React web, etc.:
react-web init <current project directory>
After the execution is completed, the npm install related libraries will be created in your project directory, and the web/webpack.config.js file will be automatically created, with a written configuration in it. At this time the directory structure is:
.├── README.md├── android/├── index.android.js├── index.ios.js├── ios/├── package.json└── web/ └── webpack.config.js
Step 2: Add the entry file and make relevant configurations
Each project needs to have an entry file, which is usually used to introduce and call other components and initialize the project, such as index.ios.js represents the entry file of the project on the iOS platform. In order to comply with the React Native file naming specification, we create an index.web.js as the entry file, and we need to specify that the file is the entry file in webpack. Open the web/webpack.config.js file and modify the config variable:
var config = { paths: { src: path.join(ROOT_PATH, '.'), index: path.join(ROOT_PATH, 'index.web'), },};Then we create the index.web.js file. This file is actually very similar to index.ios.js, but is slightly different. The main difference is that iOS only needs AppRegistry.registerComponent('Awes', () => Awes); to allow Xcode's Native code to receive and process your JS code, while the web side needs to be inserted into the DOM node before it can be used. Therefore, we need to add the following code at the bottom of index.web.js:
AppRegistry.registerComponent('Awes', () => Awes);if (Platform.OS == 'web') { var app = document.createElement('div'); document.body.appendChild(app); AppRegistry.runApplication('Awes', { rootTag: app });}Then the Platform component needs to be introduced in the top require section. In this way, the configuration part has been processed. Execute the react-web start command to start the debugging server!
You can modify it at will, it is almost the same as the experience in the React Native simulator.
Step 3: Test and Package the Web Version Code
When you have finished modifying and developing and testing the web side, you can package and publish it. The commands packaged by react-web-cli tool are:
react-web bundle
After packaging, the file will be stored in the web/output/ directory. You can directly open index.html (if the app has requested operations, you need to check it from the local server), and then you can publish it after checking.
What happened during this process?
Curious students may have some questions when they see this. What did some commands of the above command line tool do? Why does React web package React Native code into a copy of code used on the web side? Is React web safe and reliable? What are the things inside?
Here I will briefly introduce the implementation principles of React web and what the steps actually did.
React Web implements React Native components on the web side
React separates the code from the platform environment, adding a layer, so that developers can do some processing at the platform environment level, so that the same code can adapt to more platform environments, etc.
For example, react-canvas writes code according to React's syntax, does some processing at the platform environment level (runs your React code and renders it with canvas), and then achieves specific goals (improving performance on the mobile side).
In React Native, the same is true for a piece of code to run on iOS and Android at the same time. The React Native team has done some processing on the Native app of the corresponding platform to enable it to parse code that executes React syntax.
There are also isomorphic applications. The server uses React + Node.js to generate HTML, and the client uses React to obtain client-related interactions and functions. The same is true.
To this end, the React v0.14.x version began with two libraries, react and react-dom, which actually stripped away the special treatment of the browser platform and turned it into the react-dom library alone.
The special thing about React Native is that the lowest level implementation of the component is the implementation of Native, so it does not support tags such as span and div. Animation, etc., also directly call Native for interface rendering. Therefore, the web side is not supported, but most components can be simulated and implemented using Web technology. Animation can be used in CSS3, basic elements can be simulated with the same HTML tag, layout and compatibility issues can be handled in CSS, so the React web only needs to re-implement the React Native components using Web technology, and with the help of React this layer, a piece of code can be implemented on multiple platforms.
To give a very simple example, the Text component:
The implementation of React Native calls a lot of the underlying code implementations of React Native.
For the web side, just use the <span> tag to output a line of text, so the implementation of React web directly creates a <span> tag, and it is OK to bind some events or something.
You can use React Native components that can run in UI Explorer demo with confidence.
webpack helps you switch packaging targets
Having made a component that is compatible with the web side, wouldn’t we need to replace all the required('react-native') in the components to be packaged with require('react-web')? Otherwise, how can I use my web components to package it?
The powerful webpack comes with alias configuration items to help you solve this problem:
resolve: { alias: { 'react-native': 'react-web', 'ReactNativeART': 'react-art', }, extensions: ['', '.js', '.jsx'],},In this way, when packaging, all places where require('react-native') are replaced with react-web package, and react-web's module.exports are consistent with react-native, so that the code can work without replacement.
In addition, another method of introduction can be implemented with the plug-in, please see below.
Introduce components through the Haste method to improve performance
webpack and other packaging tools that support CommonJS specifications will package all the components of require in the file together. For React Native, the size of the code is irrelevant, but for Mobile web, it is a little more important. Especially if your project only needs Text components, but it is sad because require('react-web') results in packing all the components in.
Based on the webpack plugin, there is another way to introduce components to solve this problem, you can call it the Haste way. This method requires loading the webpack plugin haste-resolver-webpack-plugin. The default webpack configuration has been loaded for you. You can use it directly in the component as follows:
var Text = require('ReactText');Instead of what was before:
var {Text} = require('react-native');In this way, when webpack is packaged, the former will only package the content of that component, which can reduce the size and improve performance. How is this achieved?
When the plug-in's webpack is loaded, all components will be scanned first and the information of @providesModule in the component header (such as the information of the Text component), and then when the component name is required in other files, the file will be automatically located for packaging. At the same time, you can also distinguish between platforms. Even if it is the same name, the platform will be differentiated when packaging the corresponding files (the files are determined according to the naming rules of index.xxx.js).