Paolo Dell'Aguzzo
  • Chi sono
  • Cosa offro
  • Portfolio e Carriera
    • Carriera
    • Portfolio
  • PRESS e Guest Post
  • Contatti
  • Blog
Paolo Dell'Aguzzo
  • Chi sono
  • Cosa offro
  • Portfolio e Carriera
    • Carriera
    • Portfolio
  • PRESS e Guest Post
  • Contatti
  • Blog
Giu 20
come migliorare le performance di un'app React Native

React Native: come migliorare le performance di un’app React Native

  • 20/06/2018
  • Paolo Dell'Aguzzo
  • No Comments
  • Programmazione
  • performance react, performance react native, react native, reactjs

La tua app è sempre più grande e fa sempre più cose. Su iOS l’app è molto veloce mentre su Android l’app è molto lenta ed a volte si blocca. In questo articolo scopriamo come migliorare le performance di un’app React Native facendo in modo che non si blocchi e che risponda sempre velocemente al tocco dell’utente.

Come migliorare le performance di un’app React Native

Non conosci React Native o hai bisogno di un ripasso? Inizia da questa guida.

Per prima cosa è molto importante ricordarsi che per testare le performance di un’app bisognerebbe seguire questi accorgimenti:

  • Provare l’app in release (su Android basta seguire questa guida) o almeno disabilitare il flag __DEV__ (su Android basta fare il run dell’app, far comparire il menù, selezionare “Dev Settings” e togliere il flag da “JS Dev Mode”)
  • Per quanto riguarda iOS è sufficiente utilizzare il simulatore, davvero molto performante
  • Con Android è meglio invece usare un dispositivo fisico poiché gli emulatori stressano molto il PC ed eventuali rallentamenti potrebbero essere dovuti non dall’app, bensì dal processore occupato in altre operazioni o da un utilizzo eccessivo della CPU

Se la tua app è ancora lenta, specialmente su Android, e risponde lentamente ai tocchi dell’utente è possibile che stai facendo troppe operazioni e che il thread JavaScript sia in sovraccarico.

Tra i problemi di performance riconosciuti ci sono senza dubbio quelli relativi all’utilizzo di react-navigation. Bisogna ricordarsi infatti che React Native esegue tutte le operazioni logiche, ma anche quelle grafiche come le animazioni, sul thread JavaScript e quindi quando si vuole navigare in una nuova voce di menù il thread è occupato nel:

  • Mostrare l’animazione di cambio pagina
  • Renderizzare i vari componenti
  • Eseguire la logica definita in fase di ComponentWillMount e ComponentDidMount

Fin quando i componenti da renderizzare non sono pronti React Navigation (così come altre librerie) rimane in stallo dando la sensazione di avere un’app bloccata e dando la possibilità all’utente di provare più volte a premere un pulsante o una voce di menù per “cambiare route”.

Development Category (English)728x90

Nota bene: In questa guida impari come migliorare le performance di un’app React Native, quindi non parliamo approfonditamente di React Navigation. Lo stesso discorso infatti si applica ad animazioni lente, frame che saltano, modali che si aprono a scatto, ecc.

Come risolvere il problema?

Dando per scontato che vogliamo certamente mostrare l’animazione di React Navigation (e simili) per il cambio pagina e dicendo che questa operazione non dovrebbe occupare troppo il thread JavaScript, ci concentriamo invece sui componenti da renderizzare e sulla logica definita in fase di mounting.

Le pagine più lente da aprire sono:

Deep Learning Specialization on Coursera
  • Quelle che eseguono tante operazioni in fase di mounting: chiamano endpoint, leggono dal database, elaborano dati
  • Quelle che sono composte da componenti che renderizzano una grande quantità di elementi
  • Le pagine che renderizzano un componente che viene renderizzato nuovamente non appena le operazioni in componentDidMount sono andate a buon fine (vedi per esempio il render di una lista di profili che viene mostrata prima vuota con scritto “Non ci sono profili da mostrare” e poi, una volta eseguito il fetch dei dati, viene popolata con i profili)

Per capire come migliorare le performance di un’app React Native puoi seguire i consigli che vengono dati direttamente dal team a questo indirizzo ed anche ascoltare quanto ho io da consigliarti basandomi sull’esperienza personale:

  • Esegui il render di un componente solo quando i dati sono pronti (mostra per esempio l’header della tua pagina e un overlay con un ActivityIndicator, vedi questo componente. Quando i dati sono pronti esegui il render del component che li sa mostrare. Il problema maggiore è dovuto a componenti che sono a loro volta composti da tanti altri componenti. In alcuni casi il render di uno potrebbe scatenare un nuovo render di tutti gli altri)
  • Importa solo le dipendenze necessarie e cerca di fare pulizia del tuo codice rimuovendo tutto ciò che è superfluo o rappresenta un refuso
  • Aiuta il thread JavaScript ad eseguire tutte le operazione correttamente senza sovraccaricarlo

Aiuta il thread JavaScript ad eseguire tutte le operazione correttamente senza sovraccaricarlo, ma come faccio?

Per prima cosa crea un file threadHelper.js e metti al suo interno questo codice:

import {InteractionManager} from 'react-native';


export default class ThreadHelper {

    /**
     * Viene risolta la promise non appena il prossimo frame è disponibile
     */
    nextFrame() {
        return new Promise((resolve, reject) => {
            requestAnimationFrame(() => {
                resolve();
            });
        })
    }

    /**
     * Invece di andare a riempire la coda del thread JS cerchiamo di non sovracaricarlo eseguendo la callback dopo le interactions, dunque quando l'Animation Frame ha fatto il suo dovere
     * @param {function} callback - codice da eseguire quando il JS thread è libero
     */
    runWhenThreadIsReady(callback) {
        InteractionManager.runAfterInteractions(async () => {
            await this.nextFrame();
            callback();
        });
    }
}

Da adesso in poi tutte le operazioni pesanti e, specialmente, tutte quelle operazioni che un componente esegue al componentDidMount falle eseguire passando una funzione a runWhenThreadIsReady. Un esempio? Eccolo quì:

componentDidMount() {

    this.setupData();
}

setupData() {
    this.threadHelper.runWhenThreadIsReady(() => {
        //Operazioni varie
        var cars = this.service.getCars(...);

        cars.forEach((car) => {
            //elabora cars..
        });

        this.setState({
            cars: cars,
            isLoading: false
        });
    });
}

Il componente appena visto deve effettuare un setup dei dati nel componentDidMount (per esempio recuperare delle auto, elaborare i vari oggetti, dunque impostare lo state). Essendo delle operazioni pesanti (magari il service legge dal database locale migliaia di righe che poi vengono elaborate, ecc., ecc.) eseguiamo il tutto solo quando il thread JavaScript è pronto.

Passiamo infatti le operazioni da svolgere come funzione a runWhenThreadIsReady di threadHelper. Questa funzione viene eseguita solo quando:

  • InteractionManager.runAfterInteractions risponde
  • requestAnimationFrame viene risolto

Cosa sono InteractionManager.runAfterInteractions e requestAnimationFrame?

L’interactionManager permette di eseguire lunghe operazioni dopo che animazioni ed interazioni dell’utente vengono completate (vedi quì). Ciò sta ad indicare che quando entriamo in una pagina viene rispettato il touch dell’utente e qualsiasi altra interazione e dunque anche le animazioni (pagina che si apre, una modale che deve comparire, ecc.). Una volta eseguite interazioni ed animazioni il thread JavaScript si occupa delle operazioni che gli abbiamo chiesto di eseguire.

Le operazioni che nel nostro caso chiediamo di eseguire sono requestAnimationFrame e l’esecuzione della callback passata come parametro. RequestAnimationFrame(fn), da non confondere con setTimeout, prende come parametro una funzione che viene eseguita non appena tutti i frame dell’app sono stati eseguiti (vedi a questo indirizzo e quì).

Ciò vuol dire che nel nostro caso il setup dei dati avverrà solo quando il thread JavaScript è in grado di non bloccare l’applicazione (interazioni e animazioni rispettate) e di non tagliare i frame (quindi animazioni ben visibili, ActivityIndicator che si muovono in maniera lineare).

Come migliorare le performance di un’app React Native

Direi che per questa volta è tutto. Leggiti bene la guida sulle performance di React Native e cerca di scrivere un codice pulito. Ci sono accorgimenti che dovrebbero essere presi sempre, anche se stai utilizzando ReactJS. Cerca di non far rimanere mai l’utente fermo nell’osservare una pagina (web o di un’app) che rimane bianca o bloccata. Piuttosto mostra un caricamento o cerca di suddividere la pagina in blocchi che vengono caricati di volta in volta.

Nei riguardi di React Native utilizza liste virtuali, come la FlatList, e cerca sempre di far sì che l’interazione dell’utente non risulti mai macchinosa.

Se ti è piaciuto questo articolo ed hai imparato come migliorare le performance di un’app React Native potrebbe interessarti anche:

  • La guida per imparare React Native
  • La guida per imparare ReactJS

Infine non ti dimenticare alcune risorse importanti:

  • Il libro Learning React Native 2nd Edition (O’Reilly)
  • Il corso Udemy: The Complete React Native and Redux Course
  • Il corso Udemy: React Native: The Practical Guide

Se vuoi rimanere aggiornato sugli articoli del blog ti consiglio di iscriverti alla newsletter. Mando da 1 a 4 mail al mese e normalmente invio risorse gratuite e riservate solo agli iscritti. Invio anche la lista degli articoli di maggiore impatto, come questo. Se non troverai gli articoli potrai recuperarli dalla mail in questo modo ?

Per dubbi o domande non esitare a scrivermi nei commenti ?

Se ti è piaciuto l’articolo seguimi su Facebook e Twitter oppure rimani sempre aggiornato con la newsletter (da 1 a 4 mail al mese!).

 

Commenti

Condividi:

  • Fai clic qui per condividere su Twitter (Si apre in una nuova finestra)
  • Fai clic per condividere su Facebook (Si apre in una nuova finestra)
  • Fai clic qui per condividere su Tumblr (Si apre in una nuova finestra)
  • Fai clic qui per condividere su LinkedIn (Si apre in una nuova finestra)
  • Fai clic qui per condividere su Pinterest (Si apre in una nuova finestra)
  • Fai clic per condividere su WhatsApp (Si apre in una nuova finestra)
  • Fai clic per condividere su Telegram (Si apre in una nuova finestra)
  • Clicca per condividere su Skype (Si apre in una nuova finestra)
  • Fai clic qui per stampare (Si apre in una nuova finestra)

Correlati

  • Facebook
  • Twitter
  • Tumblr
  • Pinterest
  • Google+
  • LinkedIn
  • E-Mail
Paolo Dell'Aguzzo

About The Author

Sono sempre stato affascinato dal marketing e dall'informatica a tal punto di unire le due passioni :) Se ti piace l'articolo fammelo sapere in un commento :)

Related Posts

    Fammi sapere cosa ne pensi :) Annulla risposta

    Impara ReactJS imparare react
    I 10 + 1 Libri che Dovrebbe Leggere Ogni Programmatore libri programmatore
    Newsletter

    Seguimi su Facebook :)

    Facebook Pagelike Widget
    Impara React Native imparare react native
    10 Cose per Stare Più Comodo in Ufficio stare più comodo in ufficio
    Impara a Creare un Tema Wordpress imparare creare tema wordpress
    Udemy I Migliori Corsi per Programmatori udemy corsi programmatori
    UX: Perché la User Experience è Importante UX importante e cos'è
    Metodologie Agili e Lean: Come migliorare la tua azienda metodologie agili
    Libri per Imparare JavaScript Imparare JavaScript libri

    Articoli recenti

    • I principali engine utilizzati per lo sviluppo di videogiochi
    • Dalla visione alla realtà: Lo sviluppo di videogiochi dal punto di vista di un programmatore
    • 8 consigli per migliorare la tua SEO Locale

    Categorie

    • CSS
    • Interviste
    • Java
    • Lavoro
    • Normative
    • Personale
    • Programmazione
    • Strategia & Marketing
    • Tech
    • Web Design
    • Wordpress
    Paolo Dell'Aguzzo
    Programmatore Software - Marotta di Mondolfo, Pesaro e Urbino
    P. IVA: IT02758450429
    Mail: info@paolodellaguzzo.com
    Via Litoranea, 284/C - Marotta (PU)
    Privacy Policy
    Cookie Policy
    In qualità di Affiliato Amazon, ricevo un guadagno per ciascun acquisto idoneo
    Amazon e il logo Amazon sono marchi registrati di Amazon.com, Inc. o delle sue affiliate
    Programmatore Senigallia, Ancona - Siti web, app iOS e Android, gestionali ReactJS, React Native, Java, SQL, PL/SQL, Heroku