使用 react-native-web 在 create-react-app 中处理第三方
Dealing with 3rd parties in create-react-app with react-native-web
我们正在尝试在移动设备 (react-native) 和网络 (create-react-app) 中使用相同的 React 组件。
由于 react-native-web(下面的配置),到目前为止它运行良好。
然而,我们在 react-native 项目中广泛使用的 react-native-vector-icons 无法与 react-native-web 一起编译。这意味着任何使用带有矢量图标的组件的组件也需要特定的网络版本。拥有特定于 Web 的组件版本会影响维护。
是否有一种已知的方法,无需弹出 create-react-app 配置,即可处理 3rd 方,例如网络中的 react-native-vector-icons?
import {createIconSetFromIcoMoon} from "react-native-vector-icons";
import Font from './Font.json';
export default createIconSetFromIcoMoon(UbeyaFont);
目前我们想到的事情:
我们目前正在研究两个想法:
基于环境的导入:
# Pseudo code:
# if mobile import this, otherwise import that.
我们不确定这种动态导入是否可行
Webpack 配置注入node_modules/react-scripts。不优雅,但我们有一个 gulp 手表,我们可以确保配置始终存在。
如有任何想法或想法,我们将不胜感激。
配置:
我们已经构建了一个新的私有 NPM 包,它包含所有 React 组件,并通过使用 gulp watch 将包复制到移动和 Web 项目,我们省去了在开发过程中不断 npm publishing 和 yarning(Webstorm 索引过程的唯一缺点)。
我们最终使用 gulp 脚本来覆盖 webpack。阶段是:
1) 构建替换包
我们为 each React Native 第 3 方构建了一个网络版本。对于 react-native-vector-icons 结果很简单:
import React from 'react';
export const Icon = (props) => <div className="material-icons"
style={{color:props.color}}>
{props.name}
</div>;
export default Icon;
2) 调整Webpack配置
我们使用 gulp 覆盖 create-react-app webpack 配置:
resolve: {
modules: ...
alias: {
"babel-runtime": path.dirname(
require.resolve("babel-runtime/package.json")
),
"react-native": "@ourcompany/react-native-web",
"react-native-vector-icons": "@ourcompany/react-native-vector-icons",
...
gulp任务脚本:
gulp.task("copyWebpack", function() {
return gulp
.src(["package.json", "src/_webpack/*.js"])
.pipe(
gulp.dest(
path.resolve(pathWeb + "/node_modules/react-scripts/config")
)
);
});
注:
- Ejecting create-react-app's configuration 更干净,但这意味着您需要维护配置,我们更喜欢保持配置不变并在构建过程中覆盖它。
- 您会注意到我们已经覆盖了 react-native-web 本身。在下一个可选步骤中详细介绍。
3) 扩展 react-native-web(可选)
如果您正在使用 react-native-web 尚不支持的组件,您需要为它们构建包并扩展 react-native-web 以便您的网络版本将工作。只需创建一个新包 @yourcompany/react-native-web 并生成一个 index.js,其中导入确实存在于 react-native-web 并引用你构建的那些。请注意,当我们构建项目时 react-native-web 没有 FlatList 或 SectionList,现在(2018 年 10 月)它同时拥有(Modal 仍然缺失 :-))。
import {
StyleSheet as _StyleSheet,
View as _View,
Text as _Text,
Image as _Image,
I18nManager as _I18nManager,
AsyncStorage as _AsyncStorage,
Platform as _Platform,
Linking as _Linking,
ActivityIndicator as _ActivityIndicator,
ListView as _ListView,
Modal as _Modal,
Picker as _Picker,
RefreshControl as _RefreshControl,
TextInput as _TextInput,
Touchable as _Touchable,
TouchableHighlight as _TouchableHighlight,
TouchableNativeFeedback as _TouchableNativeFeedback,
TouchableOpacity as _TouchableOpacity,
TouchableWithoutFeedback as _TouchableWithoutFeedback,
Dimensions as _Dimensions,
Animated as _Animated,
ScrollView as _ScrollView,
SafeAreaView as _SafeAreaView,
BackHandler as _BackHandler,
Switch as _Switch,
NetInfo as _NetInfo,
AppState as _AppState,
ColorPropType as _ColorPropType,
} from 'react-native-web';
import {SectionList as _SectionList} from './SectionList';
import {FlatList as _FlatList} from './FlatList';
import {Alert as _Alert} from './Alert';
import {WebView as _WebView} from './WebView';
import {Share as _Share} from './Share';
import {PermissionsAndroid as _PermissionsAndroid} from './PermissionsAndroid';
import {ActionSheetIOS as _ActionSheetIOS} from './ActionSheetIOS';
import {ToastAndroid as _ToastAndroid} from './ToastAndroid';
export const StyleSheet = _StyleSheet;
export const View = _View;
export const Text = _Text;
export const Image = _Image;
export const I18nManager = _I18nManager;
export const AsyncStorage = _AsyncStorage;
export const Platform = _Platform;
export const Linking = _Linking;
export const ActivityIndicator = _ActivityIndicator;
export const ListView = _ListView;
export const Modal = _Modal;
export const Picker = _Picker;
export const RefreshControl = _RefreshControl;
export const TextInput = _TextInput;
export const Touchable = _Touchable;
export const TouchableHighlight = _TouchableHighlight;
export const TouchableNativeFeedback = _TouchableNativeFeedback;
export const TouchableOpacity = _TouchableOpacity;
export const TouchableWithoutFeedback = _TouchableWithoutFeedback;
export const Dimensions = _Dimensions;
export const Animated = _Animated;
export const ScrollView = _ScrollView;
export const SafeAreaView = _SafeAreaView;
export const BackHandler = _BackHandler;
export const Switch = _Switch;
export const NetInfo = _NetInfo;
export const AppState = _AppState;
export const Alert = _Alert;
export const Share = _Share;
export const WebView = _WebView;
export const PermissionsAndroid = _PermissionsAndroid;
export const ActionSheetIOS = _ActionSheetIOS;
export const ToastAndroid = _ToastAndroid;
export const SectionList = _SectionList;
export const FlatList = _FlatList;
export const ColorPropType = _ColorPropType;
我们正在尝试在移动设备 (react-native) 和网络 (create-react-app) 中使用相同的 React 组件。
由于 react-native-web(下面的配置),到目前为止它运行良好。
然而,我们在 react-native 项目中广泛使用的 react-native-vector-icons 无法与 react-native-web 一起编译。这意味着任何使用带有矢量图标的组件的组件也需要特定的网络版本。拥有特定于 Web 的组件版本会影响维护。
是否有一种已知的方法,无需弹出 create-react-app 配置,即可处理 3rd 方,例如网络中的 react-native-vector-icons?
import {createIconSetFromIcoMoon} from "react-native-vector-icons";
import Font from './Font.json';
export default createIconSetFromIcoMoon(UbeyaFont);
目前我们想到的事情: 我们目前正在研究两个想法:
基于环境的导入:
# Pseudo code: # if mobile import this, otherwise import that.
我们不确定这种动态导入是否可行
Webpack 配置注入node_modules/react-scripts。不优雅,但我们有一个 gulp 手表,我们可以确保配置始终存在。
如有任何想法或想法,我们将不胜感激。
配置: 我们已经构建了一个新的私有 NPM 包,它包含所有 React 组件,并通过使用 gulp watch 将包复制到移动和 Web 项目,我们省去了在开发过程中不断 npm publishing 和 yarning(Webstorm 索引过程的唯一缺点)。
我们最终使用 gulp 脚本来覆盖 webpack。阶段是:
1) 构建替换包
我们为 each React Native 第 3 方构建了一个网络版本。对于 react-native-vector-icons 结果很简单:
import React from 'react';
export const Icon = (props) => <div className="material-icons"
style={{color:props.color}}>
{props.name}
</div>;
export default Icon;
2) 调整Webpack配置
我们使用 gulp 覆盖 create-react-app webpack 配置:
resolve: {
modules: ...
alias: {
"babel-runtime": path.dirname(
require.resolve("babel-runtime/package.json")
),
"react-native": "@ourcompany/react-native-web",
"react-native-vector-icons": "@ourcompany/react-native-vector-icons",
...
gulp任务脚本:
gulp.task("copyWebpack", function() {
return gulp
.src(["package.json", "src/_webpack/*.js"])
.pipe(
gulp.dest(
path.resolve(pathWeb + "/node_modules/react-scripts/config")
)
);
});
注:
- Ejecting create-react-app's configuration 更干净,但这意味着您需要维护配置,我们更喜欢保持配置不变并在构建过程中覆盖它。
- 您会注意到我们已经覆盖了 react-native-web 本身。在下一个可选步骤中详细介绍。
3) 扩展 react-native-web(可选)
如果您正在使用 react-native-web 尚不支持的组件,您需要为它们构建包并扩展 react-native-web 以便您的网络版本将工作。只需创建一个新包 @yourcompany/react-native-web 并生成一个 index.js,其中导入确实存在于 react-native-web 并引用你构建的那些。请注意,当我们构建项目时 react-native-web 没有 FlatList 或 SectionList,现在(2018 年 10 月)它同时拥有(Modal 仍然缺失 :-))。
import {
StyleSheet as _StyleSheet,
View as _View,
Text as _Text,
Image as _Image,
I18nManager as _I18nManager,
AsyncStorage as _AsyncStorage,
Platform as _Platform,
Linking as _Linking,
ActivityIndicator as _ActivityIndicator,
ListView as _ListView,
Modal as _Modal,
Picker as _Picker,
RefreshControl as _RefreshControl,
TextInput as _TextInput,
Touchable as _Touchable,
TouchableHighlight as _TouchableHighlight,
TouchableNativeFeedback as _TouchableNativeFeedback,
TouchableOpacity as _TouchableOpacity,
TouchableWithoutFeedback as _TouchableWithoutFeedback,
Dimensions as _Dimensions,
Animated as _Animated,
ScrollView as _ScrollView,
SafeAreaView as _SafeAreaView,
BackHandler as _BackHandler,
Switch as _Switch,
NetInfo as _NetInfo,
AppState as _AppState,
ColorPropType as _ColorPropType,
} from 'react-native-web';
import {SectionList as _SectionList} from './SectionList';
import {FlatList as _FlatList} from './FlatList';
import {Alert as _Alert} from './Alert';
import {WebView as _WebView} from './WebView';
import {Share as _Share} from './Share';
import {PermissionsAndroid as _PermissionsAndroid} from './PermissionsAndroid';
import {ActionSheetIOS as _ActionSheetIOS} from './ActionSheetIOS';
import {ToastAndroid as _ToastAndroid} from './ToastAndroid';
export const StyleSheet = _StyleSheet;
export const View = _View;
export const Text = _Text;
export const Image = _Image;
export const I18nManager = _I18nManager;
export const AsyncStorage = _AsyncStorage;
export const Platform = _Platform;
export const Linking = _Linking;
export const ActivityIndicator = _ActivityIndicator;
export const ListView = _ListView;
export const Modal = _Modal;
export const Picker = _Picker;
export const RefreshControl = _RefreshControl;
export const TextInput = _TextInput;
export const Touchable = _Touchable;
export const TouchableHighlight = _TouchableHighlight;
export const TouchableNativeFeedback = _TouchableNativeFeedback;
export const TouchableOpacity = _TouchableOpacity;
export const TouchableWithoutFeedback = _TouchableWithoutFeedback;
export const Dimensions = _Dimensions;
export const Animated = _Animated;
export const ScrollView = _ScrollView;
export const SafeAreaView = _SafeAreaView;
export const BackHandler = _BackHandler;
export const Switch = _Switch;
export const NetInfo = _NetInfo;
export const AppState = _AppState;
export const Alert = _Alert;
export const Share = _Share;
export const WebView = _WebView;
export const PermissionsAndroid = _PermissionsAndroid;
export const ActionSheetIOS = _ActionSheetIOS;
export const ToastAndroid = _ToastAndroid;
export const SectionList = _SectionList;
export const FlatList = _FlatList;
export const ColorPropType = _ColorPropType;