web-dev-qa-db-fra.com

Comment rendre plus rapide React Application mobile native?

L'application mobile React Native fonctionne très lentement à chaque clic . J'utilise react native v0.40.0 et suivants sont les dépendances de mon projet.

{
    "analytics-react-native": "^1.1.0",
    "apisauce": "^0.7.0",
    "babel-preset-es2015": "^6.18.0",
    "es6-promise": "^4.0.5",
    "flow-bin": "^0.36.0",
    "geolib": "^2.0.22",
    "immutable": "^3.8.1",
    "intl": "^1.2.5",
    "isomorphic-fetch": "^2.2.1",
    "lodash": "^4.17.4",
    "lodash.range": "^3.2.0",
    "prop-types": "^15.5.10",
    "raven-js": "^3.13.1",
    "react": "^15.4.2",
    "react-native": "^0.40.0",
    "react-native-Apple-healthkit-rn0.40": "^0.3.2",
    "react-native-blur": "^2.0.0",
    "react-native-button": "^1.7.1",
    "react-native-checkbox": "^2.0.0",
    "react-native-code-Push": "^1.17.3-beta",
    "react-native-datepicker": "^1.4.4",
    "react-native-device-info": "^0.10.1",
    "react-native-easy-toast": "^1.0.6",
    "react-native-fbsdk": "^0.5.0",
    "react-native-geocoder": "^0.4.5",
    "react-native-gifted-chat": "^0.1.3",
    "react-native-global-props": "^1.1.1",
    "react-native-image-crop-picker": "^0.15.1",
    "react-native-image-picker": "^0.25.1",
    "react-native-image-slider": "^1.1.5",
    "react-native-keyboard-aware-scroll-view": "^0.2.7",
    "react-native-maps": "0.15.2",
    "react-native-modal-dropdown": "^0.4.4",
    "react-native-popup-menu": "^0.7.2",
    "react-native-Push-notification": "^2.2.1",
    "react-native-radio-buttons": "^0.14.0",
    "react-native-router-flux": "3.38.0",
    "react-native-segmented-Android": "^1.0.4",
    "react-native-snap-carousel": "2.1.4",
    "react-native-stars": "^1.1.0",
    "react-native-swipeout": "^2.2.2",
    "react-native-swiper": "^1.5.4",
    "react-native-tableview-simple": "0.16.5",
    "react-native-vector-icons": "^4.0.0",
    "react-native-video": "^1.0.0",
    "react-native-zendesk-chat": "^0.2.1",
    "react-redux": "^4.4.6",
    "recompose": "^0.20.2",
    "redux": "^3.5.2",
    "redux-thunk": "^2.0.1"
  }

J'ai fait du profilage avec stacktrace dans Android studios, et j'ai trouvé que mqt_js est l'une des raisons qui prend plus de temps à chaque clic sur l'interface utilisateur. Vous pouvez vérifier le rapport stacktrace ici

Quelqu'un peut-il m'aider à résoudre ce problème de performances.?

14
Kishan Vaghela

Tout d'abord, vous devez exécuter votre application en dehors de [~ # ~] déboguer [~ # ~] . Sur Android cela se fait en changeant la méthode MainApplication:

@Override
public boolean getUseDeveloperSupport() {
  return false; // BuildConfig.DEBUG;
}

et faire un bundle:

react-native bundle --platform Android --dev false --entry-file ./index.js --bundle-output ./Android/app/src/main/assets/index.Android.bundle --assets-dest ./Android/app/src/main/res/ --sourcemap-output ./Android/app/src/main/assets/index.Android.map

Quant au code, voici quelques conseils pour l'optimisation react-native:

  1. L'analyse et la sérialisation (telles que response.json() ou JSON.stringify) Bloquent le thread js, donc toutes les animations et tous les gestionnaires JS (tels que onScroll et onPress, et de cours render méthode) en souffrent. Essayez de charger uniquement ce que vous devez montrer.
  2. Utilisez des animations natives (paramètre useNativeDriver: true) Là où c'est possible, et essayez de ne pas utiliser onScroll.
  3. Enregistrez toutes vos méthodes render et essayez de rendre l'appel de ces méthodes aussi rare que possible. Il est appelé lorsque les accessoires ou l'état du composant changent.
  4. Comprenez comment PureComponent fonctionne et essayez de l'utiliser si nécessaire. Mais gardez à l'esprit qu'il peut également ralentir l'application si elle n'est pas utilisée correctement.
  5. Utilisez toujours StyleSheet pour les styles, il les encapsule et les remplace par style id (entier).

Mauvais:

// style object is created on every render
render() {
    return <View style={{flex:1}}/>
}

Bien:

render() {
    <View style={styles.flex}/>
}

// style is created once
const styles = StyleSheet.create({
    flex: { flex: 1 }
});
  1. Idem pour les fonctions.

Mauvais:

// onPress handler is created on every render
render() {
    <TouchableOpacity onPress={() => this.props.navigator.navigate('SignIn')}/>
}

Bien:

render() {
    <TouchableOpacity onPress={this.onPressSignIn}/>
}

// onPressSignIn is created once
onPressSignIn = () => {
    this.props.navigator.navigate('SignIn');
}
  1. Big O de toutes les opérations sur le client doit être constant. Énumérer les tableaux aussi peu que possible. Utilisez toujours Object et Set au lieu de Array là où c'est possible. Utilisez la pagination lorsque vous devez charger de grandes quantités de données à partir du serveur/base de données, laisser le tri et d'autres calculs lourds pour le serveur.

Par exemple, si vous avez souvent besoin d'obtenir des objets par id, il est préférable d'utiliser:

let items = {
    "123": { id: "123", ... },
    "224": { id: "224", ... }
};

let item = items["123"];

au lieu du tableau habituel:

let items = [
    0: { id: "123", ... },
    1: { id: "224", ... }
];

let item = items.find(x => x.id === "123");
8

Ceci est une question très très large et basée sur l'opinion , mais je vais essayez de mettre en évidence le most common points et des suggestions basées sur le profiler que vous avez répertorié.

En regardant votre trace de pile, le principal problème réside dans le UI Thread à l'intérieur du nom de votre package, c'est-à-dire com.fitspot.app.debug.

Comme mentionné ici .

afin d'afficher un cadre, tout notre travail d'interface utilisateur doit être effectué à la fin de cette période de 16 ms.

Une fois l'intervalle limite défini sur 16ms, vous pouvez voir que le mqt_js ou la JS Thread prend beaucoup plus de temps que 16ms pour un cycle, ce qui signifie que votre JS Thread fonctionne en permanence.

Dans le profiler actuel, il est difficile de savoir quels processus sont exécutés dans votre JS Thread, il est donc clair que le problème réside principalement dans votre JS Code et non le UI Thread.

Il existe plusieurs façons de rendre le react-native application plus rapide qui est bien documentée dans ce page . Voici un Gist de base à la même chose.

  • Les messages d'erreur et d'avertissement sont fournis en mode dev=true, vous pouvez les désactiver dans l'application pour de meilleures performances.
  • Supprimez tous les console.log instructions de votre application, car cela provoque un bottleneck sur le thread JS. Vous pouvez utiliser ce plugin pour supprimer tous les console* instructions comme mentionné ici , dans vos fichiers .babelrc comme

    {
      "env": {
      "production": {
      "plugins": ["transform-remove-console"]
      }
     }
    }
    
  • Vous devez componentize la structure de votre projet et utiliser Pure Components, pour utiliser uniquement props et state, utilisez immutable data structures pour des comparaisons plus rapides.

  • Pour le slower navigation transitions, vous voudrez peut-être vérifier le navigation library code, car la plupart du temps, ils ont un timeout pour default transitions. Comme solution de contournement, vous pouvez envisager de créer votre propre transitioner.

  • Si vous utilisez Animations dans votre base de code, vous pouvez envisager de définir nativeDriver=true, ce qui réduirait la charge sur votre JS thread. Voici un bien expliqué exemple .

  • Vous pouvez également vouloir vérifier le profilage , pour vérifier le JS Thead et le Main Thread opérations, bien expliquées sur cette page.

  • D'autres choses incluent, pas requiring/importing le module, qui n'est pas nécessaire, n'important que classes requis, et non le whole component.

  • De plus, vous n'avez pas besoin de external libraries faire simple UI components, car leurs performances sont beaucoup plus lentes que les éléments natifs de react-native. Vous pouvez envisager d'utiliser styled-components pour composant votre UI

4
Pritish Vaidya
  1. Utilisez Flatlist sur Scrollview:

    • ajouter initialNumToRender={number} prop à Flatlist, car il n'affichera que les composants visibles à l'écran et détachera les autres composants
  2. Utilisez PureComponent dans Flatlist renderItem (dans votre cas, il s'agira de chaque carte), afin qu'ils ne s'affichent que lorsque leurs accessoires sont modifiés.

  3. Vérifiez si votre composant est restitué encore et encore afin de tester la console de mise soit dans render () ou dans ComponentWillRecieveProps et si cela se produit, utilisez ShouldComponentUpdate.

  4. Supprimez console.log de render () et ComponentWillRecieveProps.

Apportez ces modifications et vous voyez que vos performances sont bien meilleures qu'auparavant.

3
Rajat Gupta

Plusieurs raisons peuvent ralentir l'application native de react. Je suggère les points clés suivants qui peuvent aider:

  1. Préférer dumb components plus de class components la mesure du possible.
  2. Essayez d'utiliser redux, c'est un puissant outil de gestion d'état qui peut vous fournir le meilleur code, s'il est correctement implémenté.
  3. Utilisez des outils comme react-monocole et appr. Guide de react-monocole .
  4. Générez l'apk signé, l'application native native réactivée a des fonctionnalités supplémentaires. Voici un guide pour générer un apk signé .
2
madhav gaba

Si mqt_js est la principale cause de problème de performances, ce qui signifie qu'à chaque clic, le thread JS de votre application a trop de choses à faire à la fois. La communication entre la logique métier JS et le domaine natif sous-jacent se fait de manière asynchrone, plus le nombre d'actions doit être terminé côté JS lorsqu'un bouton est enfoncé, plus l'application sera lente.

Réponse donné par Pritish Vaidya frappe déjà le clou sur la tête. Je veux juste inclure 1 point de plus sur l'utilisation de redux dans votre application. Si le flux de données de votre application se fait principalement à l'aide de redux, vous pouvez vérifier les éléments suivants:

  • S'il y a trop d'actions redux se produisant à chaque événement de clic, essayez de supprimer celles inutiles ou de prioriser les actions déclenchant d'abord des animations importantes, puis de déclencher d'autres actions une fois que les nouveaux composants RN ont terminé le rendu. Vous pouvez voir quelles actions sont des actions à col bas par redux-logger.

  • Divisez les composants écoutant le magasin de redux en plus petits, chacun écoutant une partie différente du magasin. Donc, si le magasin de redux est mis à jour, seul un petit groupe de composants doit être rendu à la place de tout.

  • Utilisez des sélecteurs mémorisés pour traiter les données fréquemment mises à jour. resélectionnez peut vous aider dans ce cas.

1
blaz