JavaScript的React Web庫的理念剖析及基礎(chǔ)上手指南
React Web的目的及意義非常明確: 讓React Native代碼跑在Web上 讓一套代碼運(yùn)行在各個(gè)移動(dòng)終端,對前端及業(yè)務(wù)來說,這是開發(fā)效率中一個(gè)質(zhì)的提升。在項(xiàng)目初期,我們也曾向 React團(tuán)隊(duì)咨詢過類似的問題,他們團(tuán)隊(duì)的核心同學(xué) @vjeux 也認(rèn)為這是非常酷的事情,也是他們未來想做的事情。也許在發(fā)布React Native for Android的時(shí)候,也會(huì)發(fā)布React Web也說不定。(YY一下)
技術(shù)架構(gòu)
基于React Native的適配方案,有幾個(gè):
1.制定一個(gè)Bridge標(biāo)準(zhǔn),RN與RW 各自用最優(yōu)的方式實(shí)現(xiàn)這套標(biāo)準(zhǔn)。
比如基于Flex布局,我們實(shí)現(xiàn)一套一致的 Flex Component, <Flex> 、<Cell> 等。
2.完全向RN看齊,RW實(shí)現(xiàn)RN的所有能實(shí)現(xiàn)的API。
在討論中,最終選擇了后者。
因?yàn)镽eact Web的理念,讓React Native代碼跑在Web端,那么就決定了RW只是一個(gè)構(gòu)建及打包工具,脫離RN,RW的實(shí)現(xiàn)則沒有太大的意義,那么整體的技術(shù)方向就非常明確了: 實(shí)現(xiàn)RN一致的Style、Component及API,最終通過構(gòu)建工具編譯成web版本。
示例
下面我們來看一下React Web項(xiàng)目的創(chuàng)建過程:
第一步:安裝 React web 并進(jìn)行相關(guān)配置
這一步操作主要是安裝 react-web 包以及相關(guān)依賴,并配置 webpack 打包腳本等。
為了簡化這一步操作,我們開發(fā)了命令行工具 react-web-cli 只需要執(zhí)行兩行命令即可。同時(shí)命令行工具還支持啟動(dòng)調(diào)試服務(wù)器、打包等功能,在后面介紹。
安裝 cli 工具:
npm install react-web-cli -g
安裝配置 React web 等:
react-web init <當(dāng)前項(xiàng)目目錄>
執(zhí)行完成之后,會(huì)在你項(xiàng)目目錄下面 npm install 相關(guān)庫,并自動(dòng)創(chuàng)建 web/webpack.config.js 文件,里面有一份寫好的配置。此時(shí)目錄結(jié)構(gòu)為:
. ├── README.md ├── android/ ├── index.android.js ├── index.ios.js ├── ios/ ├── package.json └── web/ └── webpack.config.js
第二步:添加入口文件并進(jìn)行相關(guān)配置
每個(gè)項(xiàng)目都需要有一個(gè)入口文件,通常用來引入調(diào)用其他組件并初始化項(xiàng)目,比如 index.ios.js 表示 iOS 平臺(tái)上的該項(xiàng)目的入口文件。為了符合 React Native 的文件命名規(guī)范,我們創(chuàng)建一個(gè) index.web.js 作為入口文件,并且需要在 webpack 中指定該文件為入口文件。打開 web/webpack.config.js 文件,修改 config 變量:
var config = { paths: { src: path.join(ROOT_PATH, '.'), index: path.join(ROOT_PATH, 'index.web'), }, };
然后我們創(chuàng)建 index.web.js 文件。這個(gè)文件其實(shí)跟 index.ios.js 非常像,只是略有不同。主要區(qū)別在于:iOS 只需要 AppRegistry.registerComponent('Awes', () => Awes); 即可讓 Xcode 的 Native 代碼接收處理你的 JS 代碼,而 Web 端是需要插入到 DOM 節(jié)點(diǎn)中才可以用。因此我們需要在 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 }); }
然后在最上面 require 部分需要引入 Platform 組件。這樣配置部分就已經(jīng)處理完成了,執(zhí)行 react-web start 命令即可啟動(dòng)調(diào)試服務(wù)器啦!
可以隨便修改試下,跟 React Native 模擬器里面的體驗(yàn)幾乎一樣。
第三步:測試并打包 Web 版本代碼
當(dāng)你修改開發(fā)完,并對 Web 端也測試好了,就可以打包發(fā)布了。react-web-cli 工具打包的命令是:
react-web bundle
打包完成后,文件會(huì)存放在 web/output/ 目錄下面,可以直接打開 index.html (如果 app 有請求操作,需要起本地服務(wù)器查看),再檢查一下就可以發(fā)布了。
這個(gè)過程中發(fā)生了什么?
好奇的同學(xué)看到這里可能會(huì)有一些疑問,上面命令行工具的一些命令做了什么事情?為什么 React web 將 React Native 代碼打包出一份用在 Web 端的代碼?React web 安全可靠嗎,里面都是什么東西?
這里簡單的介紹下 React web 的實(shí)現(xiàn)原理和上面步驟實(shí)際做的事情。
React Web 將 React Native 組件做了 Web 端的實(shí)現(xiàn)
React 將代碼與平臺(tái)環(huán)境分離,多了一層,這樣開發(fā)者可以在平臺(tái)環(huán)境層面做一些處理,使得同樣一份代碼適應(yīng)更多的平臺(tái)環(huán)境等。
比如 react-canvas 按照 React 的語法書寫代碼,在平臺(tái)環(huán)境層面做一些處理(將你 React 代碼運(yùn)行并用 canvas 渲染),然后實(shí)現(xiàn)特定目標(biāo)(在移動(dòng)端提高性能)。
React Native 中,一份代碼能同時(shí)跑在 iOS 和 Android 上面,也是一樣的道理。React Native 團(tuán)隊(duì)在對應(yīng)平臺(tái)的 Native app 上面做了一些處理,使其可以解析執(zhí)行 React 語法的代碼。
還有同構(gòu)(isomorphic)的應(yīng)用,服務(wù)器端使用 React + Node.js 生成 HTML,客戶端使用 React 獲取進(jìn)行客戶端相關(guān)交互和功能,也是一樣的道理。
為此, React v0.14.x 版本開始,專門分成兩個(gè)庫 react 和 react-dom ,其實(shí)是把對瀏覽器平臺(tái)的特殊處理剝離了出來,單獨(dú)變成了 react-dom 庫。
React Native 比較特殊的地方在于,組件最底層的實(shí)現(xiàn)是 Native 的實(shí)現(xiàn),所以就不支持 span、div 等標(biāo)簽。而動(dòng)畫等,也是直接調(diào)用 Native 進(jìn)行界面渲染。所以不支持 Web 端,但是絕大部分組件,都是可以用 Web 技術(shù)進(jìn)行模擬實(shí)現(xiàn)。動(dòng)畫可以用 CSS3 、基礎(chǔ)元素可以用同等 HTML 標(biāo)簽?zāi)M、布局以及兼容性問題可以用 CSS 來處理,所以 React web 只需要把 React Native 的組件用 Web 技術(shù)重新實(shí)現(xiàn)一遍,借助 React 這一層,即可實(shí)現(xiàn)一份代碼運(yùn)行在多個(gè)平臺(tái)上面。
舉一個(gè)非常簡單的例子,Text 組件:
React Native 的實(shí)現(xiàn) 是調(diào)用了很多 React Native 底層的代碼實(shí)現(xiàn)的。
對于 Web 端,輸出一行文本使用 <span> 標(biāo)簽即可,所以 React web 的實(shí)現(xiàn) 就直接搞一個(gè) <span> 標(biāo)簽,綁一些事件什么的就 OK 了。
在 UI Explorer demo 中能跑起來的 React Native 組件,你都可以放心的用。
webpack 幫你切換打包目標(biāo)
做出了兼容 Web 端的組件,那打包的時(shí)候豈不是要把所有要打包的組件中的 require('react-native') 全部更換成 require('react-web')?不然怎么用的我的 Web 組件打包?
強(qiáng)大的 webpack 附帶了 alias 配置項(xiàng)可以幫你解決這個(gè)問題:
resolve: { alias: { 'react-native': 'react-web', 'ReactNativeART': 'react-art', }, extensions: ['', '.js', '.jsx'], },
這樣在打包時(shí),但凡 require('react-native') 的地方全都用 react-web 包替換,而 react-web 的 module.exports 與 react-native 的保持一致即可讓代碼不替換也可以工作。
此外配合插件還可以實(shí)現(xiàn)另外一種引入方法,請看下面。
通過 Haste 方法引入組件以提高性能
webpack 以及其他的支持 CommonJS 規(guī)范的打包工具,都會(huì)把文件中 require 的所有組件都打包在一起。對于 React Native 來說代碼體積大小無關(guān)緊要,而在 Mobile web 來說,就要稍微重要一些了。特別是如果你的項(xiàng)目只需要 Text 組件,但由于 require('react-web') 結(jié)果把所有的組件全部打包進(jìn)來了,就比較傷感。
基于 webpack 插件,還可以用另一種方式引入組件以解決這個(gè)問題,你可以叫它 Haste 方式。使用這種方式需要加載 webpack 插件 haste-resolver-webpack-plugin,默認(rèn)的 webpack 配置已經(jīng)幫你加載好了,你可以直接在組件里面這樣用:
var Text = require('ReactText');
而不是以前那樣:
var {Text} = require('react-native');
這樣 webpack 打包時(shí),對于前者,只會(huì)把那一個(gè)組件內(nèi)容打包進(jìn)來,因此可以減小體積、提升性能。這是怎么實(shí)現(xiàn)的呢?
加載了插件的 webpack 打包時(shí),會(huì)先掃描所有組件并讀取組件頭部 @providesModule 的信息(比如 Text 組件的信息),然后當(dāng)其他文件中 require 了這個(gè)組件名稱,就會(huì)自動(dòng)定位到這個(gè)文件進(jìn)行打包。同時(shí)還可以區(qū)分平臺(tái),即便是同一個(gè)名字,打包時(shí)會(huì)區(qū)分平臺(tái)去打包對應(yīng)的文件(根據(jù) index.xxx.js 的命名規(guī)則確定文件)。
相關(guān)文章
React官方團(tuán)隊(duì)完善原生Hook閉包陷阱
這篇文章主要為大家介紹了React官方團(tuán)隊(duì)出手,補(bǔ)齊原生Hook短板閉包陷阱的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07React觸發(fā)render的實(shí)現(xiàn)方法
這篇文章主要介紹了React觸發(fā)render的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10React 的調(diào)和算法Diffing 算法策略詳解
React的調(diào)和算法,主要發(fā)生在render階段,調(diào)和算法并不是一個(gè)特定的算法函數(shù),而是指在調(diào)和過程中,為提高構(gòu)建workInProcess樹的性能,以及Dom樹更新的性能,而采用的一種策略,又稱diffing算法2021-12-12在Create React App中啟用Sass和Less的方法示例
這篇文章主要介紹了在Create React App中啟用Sass和Less的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01React報(bào)錯(cuò)Type '() => JSX.Element[]&apos
這篇文章主要為大家介紹了React報(bào)錯(cuò)Type '() => JSX.Element[]' is not assignable to type FunctionComponent解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12