react-native-web 的基本原理,就是將 react-native 的組件,針對web的場景重新實現一遍。藉助構建工具,實現 react-native 一套代碼,多端運行(終端 + web端,實際並無那麼簡單)。javascript
不少同窗比較關心的是,對於現有的 RN 項目,如何將 react-native-web 整合進去,下文會經過簡單的例子逐步進行說明。html
文中示例代碼能夠在 這裏 找到,後面會陸續輸出同構相關的文章,敬請期待。java
下面例子來自官方文檔,通過必定程度的簡化,建議查看原文檔。node
首先安裝依賴:react
# 註釋後面的是筆者本地安裝的版本
brew install node # 10.10.0
brew install watchman # 4.9.0
npm install -g react-native # 0.61.3
複製代碼
初始化RN項目,並安裝依賴:webpack
react-native init RnWebTest
cd RnWebTest
npm install
複製代碼
在ios模擬器裏運行,搞定。ios
npx react-native run-ios
複製代碼
下面開始講解如何整合 react-native-web。git
react-native 有本身的構建打包工具,針對 react-native-web 須要本身搞一套,一樣是webpack + babel全家桶。github
首先,安裝核心依賴 react-native-web:web
npm install --save react-native-web
複製代碼
其次,安裝babel及相關 preset / plugin:
npm install --save-dev @babel/core
npm install --save-dev @babel/runtime
npm install --save-dev @babel/preset-env
npm install --save-dev @babel/preset-react
npm install --save-dev @babel/preset-flow
複製代碼
安裝webpack及相關loader:
npm install webpack webpack-cli webpack-dev-server --save-dev
npm install --save-dev babel-loader
複製代碼
.babelrc以下:
{
"presets": [
[
"@babel/preset-env", {
"modules": "commonjs"
}
],
"@babel/preset-react",
"@babel/preset-flow"
]
}
複製代碼
webpack.config.js 以下:
const path = require('path');
module.exports = {
entry: './index.web.js',
output: {
filename: 'index.web.js',
path: path.resolve(__dirname, 'build'),
},
mode: 'development',
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
// options: {
// presets: ['@babel/preset-env']
// }
}
}
]
},
resolve: {
alias: {
'react-native$': 'react-native-web'
}
},
devServer: {
contentBase: path.join(__dirname, '.'),
// compress: true,
port: 9000
}
}
複製代碼
最重要的就是這幾行:
resolve: {
alias: {
'react-native$': 'react-native-web'
}
}
複製代碼
添加以下腳本:
"scripts": {
"dev": "webpack -w",
"build": "webpack"
},
複製代碼
上述環境準備好後,直接 npm build
會報錯,須要對業務代碼進行微調,具體以下。
通過上述修改後,構建的時候會報錯,由於 App.js 中引用了 react-native 中的庫文件 NewAppScreen,而 NewAppScreen 在 react-native-web 中並不存在。
這裏圖省事,直接把不支持的代碼註釋掉,包括組件使用的地方。
// import {
// Header,
// LearnMoreLinks,
// Colors,
// DebugInstructions,
// ReloadInstructions,
// } from 'react-native/Libraries/NewAppScreen';
複製代碼
樣式的定義用到了 Colors 變量,這裏直接把定義拷貝過來:
const Colors = {
primary: '#1292B4',
white: '#FFF',
lighter: '#F3F3F3',
light: '#DAE1E7',
dark: '#444',
black: '#000',
};
複製代碼
首先,建立入口文件 index.web.js,跟 RN 的入口文件 index.js區分開。
相比 index.js,多了 AppRegistry.runApplication()
這行調用。
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
AppRegistry.registerComponent(appName, () => App);
// 多了這行
AppRegistry.runApplication(appName, {
initialProps: {},
rootTag: document.getElementById('root')
});
複製代碼
首先,啓動本地構建:
npx webpack-dev-server
複製代碼
瀏覽器中訪問 http://127.0.0.1:9000/index.html,搞定。