Proiectarea formularelor pentru performanță în aplicații proiectate pe bază de model

Crearea de experiențe în care sarcinile pot fi îndeplinite rapid și eficient este crucială pentru satisfacția utilizatorului. Aplicațiile proiectate pe bază de model pot fi foarte particularizate pentru a crea experiențe care să răspundă nevoilor utilizatorilor dvs., dar este important să știți cum să codificați, să creați și să rulați în mod eficient aplicații proiectate pe bază de model care se încarcă rapid atunci când un utilizator deschide și navighează în aplicația dvs. în timp ce lucrați la sarcinile zilnice. Performanța s-a dovedit a fi un factor cheie de nemulțumire față de o aplicație atunci când nu este optimizată pentru performanță.

Particularizările inteligente și formularele performante sunt aspecte importante pentru construirea unor formulare extrem de eficiente și productive. De asemenea, este important să vă asigurați că creați formulare extrem de productive cu cele mai bune practici pentru proiectarea și aspectul interfeței cu utilizatorul. Pentru informații despre proiectarea formularelor pentru a obține eficiență și productivitate, consultați Proiectarea formularelor principale productive în aplicații proiectate pe bază de model.

De asemenea, este important să vă asigurați că utilizatorii lucrează cu dispozitive recomandate și acceptate și specificațiile minime necesare. Mai multe informații: Browsere web și dispozitive mobile acceptate

Lucrul cu date și file

Această secțiune prezintă modul în care comenzile care afișează date și file influențează performanța formularului.

Semnificația filei implicite

Fila implicită este prima filă extinsă dintr-un formular. Acesta joacă un rol special în încărcarea unei pagini de formular. Prin proiectare, comenzile filei implicite sunt întotdeauna redate la deschiderea unei înregistrări. În mod specific, logica de inițializare a comenzii, cum ar fi recuperarea datelor, este invocată pentru fiecare comandă din filă.

În schimb, o filă secundară nu efectuează această inițializare pe comenzile sale atunci când formularul este încărcat inițial. În schimb, inițializarea comenzii are loc în momentul în care fila secundară este deschisă fie prin interacțiunea utilizatorului, fie prin accesarea metodei API client setFocus. Aceasta oferă o oportunitate de a proteja încărcarea inițială a formularului de procesarea excesivă a comenzii prin plasarea anumitor comenzi în file secundare, în loc de fila implicită. Astfel, strategia de plasare a comenzii poate avea un efect semnificativ asupra capacității de răspuns a încărcării inițiale a formularului. O filă implicită mai receptivă oferă o experiență generală mai bună pentru modificarea câmpurilor importante, prin interacțiunea cu bara de comenzi și explorarea altor file și secțiuni.

Puneți întotdeauna comenzile care sunt cele mai utilizate în partea de sus a filei implicite. Aspectul și arhitectura informațiilor nu sunt importante doar pentru performanță, ci și pentru a îmbunătăți productivitatea atunci când utilizatorii interacționează cu datele din formular. Mai multe informații: Proiectați formulare principale productive în aplicațiile proiectate pe bază de model

Comenzi bazate pe date

Comenzile care necesită date suplimentare dincolo de înregistrarea principală produc cea mai mare presiune asupra reacției la formular și a vitezei de încărcare. Aceste comenzi preiau date prin rețea și implică adesea o perioadă de așteptare (văzută ca indicatori de progres), deoarece poate dura ceva timp pentru a transmite datele.

Unele dintre comenzile bazate pe date includ:

Păstrați numai cele mai frecvent utilizate dintre aceste comenzi în fila implicită. Restul comenzilor bazate pe date trebuie distribuite în file secundare pentru a permite ca fila implicită să se încarce rapid. În plus, această strategie de aspect reduce riscul de a prelua date care ajung să fie neutilizate.

Există alte comenzi care au un impact mai redus decât comenzile bazate pe date, dar care pot totuși participa la strategia de aspect de mai sus pentru a obține cele mai bune performanțe. Aceste comenzi includ:

Browser web

Această secțiune acoperă bunele practici de utilizat cu browserele web.

Nu deschideți ferestre noi

Metoda API client openForm permite unei opțiuni de parametru să afișeze un formular într-o fereastră nouă. Nu utilizați acest parametru sau setați-l pe fals. Dacă îl setați la fals, vă veți asigura că metoda openForm efectuează comportamentul implicit de afișare a formularului utilizând fereastra existentă. De asemenea, este posibil să accesați direct funcția window.open JavaScript dintr-un script particularizat sau altă aplicație; cu toate acestea, acest lucru ar trebui evitat. Deschiderea unei noi ferestre înseamnă că toate resursele paginii trebuie preluate și încărcate de la zero deoarece pagina nu este capabilă să valorifice capacitățile de memorare în cache a datelor din memorie între un formular încărcat anterior și formularul dintr-o fereastră nouă. Ca alternativă la deschiderea de noi ferestre, luați în considerare utilizarea experienței multisesiune, care permite deschiderea înregistrărilor în mai multe file, maximizând în același timp beneficiile de performanță ale memorării în cache a clientului.

Folosiți browsere moderne

Folosirea celui mai actualizat browser web este esențială pentru a vă asigura că aplicația dvs.proiectată pe bază de model rulează cât mai rapid posibil. Motivul este că multe dintre îmbunătățirile de performanță pot fi utilizate doar în browserele moderne mai noi.

De exemplu, dacă organizația dvs. are versiuni mai vechi de browsere Firefox, care nu sunt bazate pe Chromium și așa mai departe, multe dintre câștigurile la nivel de performanță care sunt încorporate într-o aplicație proiectată pe bază de model nu vor fi disponibile în versiunile mai vechi de browser deoarece nu acceptă funcții de care depinde aplicația pentru a rula rapid și fără probleme.

În majoritatea cazurilor, vă puteți aștepta să vedeți îmbunătățiri ale încărcării paginii doar trecând la Microsoft Edge, actualizând la cea mai recentă versiune curentă de browser dintr-o versiune mai veche sau trecând la un browser modern bazat pe Chromium.

Particularizare JavaScript

Această secțiune prezintă modul de realizare a particularizărilor inteligente atunci când utilizați JavaScript care vă ajută să creați formulare și pagini performante într-o aplicație proiectată pe bază de model.

Utilizarea JavaScript cu formulare

Posibilitatea particularizării formularelor de JavaScript oferă dezvoltatorilor profesioniști o mare flexibilitate cu privire la aspectul și comportamentul unui formular. Utilizarea necorespunzătoare a acestei flexibilități poate avea un impact negativ asupra performanței formularului. Dezvoltatorii ar trebui să utilizeze următoarele strategii pentru a maximiza performanța formularului atunci când implementează particularizări JavaScript.

Folosiți cereri de rețea asincrone atunci când solicitați date

Solicitați date asincron, mai degrabă decât sincron, atunci când sunt necesare date suplimentare pentru particularizări. Pentru evenimente care acceptă așteptarea unui cod asincron, cum ar fi evenimente formular OnLoad și formular OnSave, rutinele de tratare a evenimentelor ar trebui să returneze un Promise pentru ca platforma să aștepte până când Promise este stabilit. Platforma va afișa o interfață de utilizare adecvată în timp ce utilizatorul așteaptă finalizarea evenimentului.

Pentru evenimente care nu acceptă așteptarea codului asincron, cum ar fi evenimentul formular OnChange, puteți utiliza o soluție temporară pentru a opri interacțiunea cu un formular în timp ce codul face o cerere asincronă folosind showProgressIndicator. Acest lucru este mai bun decât utilizarea solicitărilor sincrone deoarece utilizatorii vor putea în continuare să interacționeze cu alte părți ale aplicației pe măsură ce este afișat un indicator de progres.

Iată un exemplu de utilizare a codului asincron în punctele de extensie sincrone.

//Only do this if an extension point does not yet support asynchronous code
try {
    await Xrm.WebApi.retrieveRecord("settings_entity", "7333e80e-9b0f-49b5-92c8-9b48d621c37c");
    //do other logic with data here
} catch (error) {
    //do other logic with error here
} finally {
    Xrm.Utility.closeProgressIndicator();
}

// Or using .then/.finally
Xrm.Utility.showProgressIndicator("Checking settings...");
Xrm.WebApi.retrieveRecord("settings_entity", "7333e80e-9b0f-49b5-92c8-9b48d621c37c")
    .then(
        (data) => {
            //do other logic with data here
        },
        (error) => {
            //do other logic with error here
        }
    )
    .finally(Xrm.Utility.closeProgressIndicator);

Ar trebui să aveți grijă atunci când utilizați cod asincron într-un gestionar de evenimente care nu acceptă așteptarea codului asincron. Acest lucru este valabil în special pentru codul care necesită o acțiune care trebuie întreprinsă sau gestionată cu privire la rezoluția codului asincron. Codul asincron poate provoca probleme dacă rutina de soluționare se așteaptă ca contextul aplicației să rămână același ca atunci când a fost pornit codul asincron. Codul dvs. ar trebui să verifice dacă utilizatorul se află în același context după fiecare punct de continuare asincron.

De exemplu, poate exista un cod într-o rutină de evenimente pentru a face o cerere de rețea și pentru a schimba o comandă care să fie dezactivată pe baza datelor de răspuns. Înainte de a primi răspunsul la cerere, este posibil ca utilizatorul să fi interacționat cu comanda sau să fi navigat către o altă pagină. Deoarece utilizatorul se află pe o altă pagină, este posibil ca contextul formularului să nu fie disponibil, ceea ce ar putea duce la erori sau ar putea exista un alt comportament nedorit.

Asistență asincronă în evenimentele de formular OnLoad și OnSave

Evenimentele de formular OnLoad și OnSave susțin rutinele care returnează promisiuni. Evenimentele vor aștepta ca orice promisiuni returnate de o rutină să fie rezolvate, până la o perioadă de expirare. Acest suport poate fi activat prin setările aplicației.

Informații suplimentare:

Limitați cantitatea de date solicitate în timpul încărcării formularului

Solicitați doar cantitatea minimă de date care este necesară pentru a realiza logica de business pe un formular. Memorați în cache datele solicitate cât mai mult posibil, în special datele care nu se schimbă des sau nu trebuie să fie noi. De exemplu, imaginați-vă că există un formular care solicită date de la un tabel de setări. Pe baza datelor din tabelul de setări, formularul poate alege să ascundă o secțiune a formularului. În acest caz, JavaScript poate memora în memoria cache date în sessionStorage astfel încât datele să fie solicitate o singură dată pe sesiune (onLoad1). O strategie învechită în timp ce se revalidează poate fi utilizată și în cazul în care JavaScript folosește datele din sessionStorage în timp ce solicitați date pentru următoarea navigare către formular (onLoad2). În cele din urmă, ar putea fi utilizată o strategie de deduplicare în cazul în care o rutină este accesată de mai multe ori la rând (onLoad3).

const SETTING_ENTITY_NAME = "settings_entity";
const SETTING_FIELD_NAME = "settingField1";
const SETTING_VALUE_SESSION_STORAGE_KEY = `${SETTING_ENTITY_NAME}_${SETTING_FIELD_NAME}`;

// Retrieve setting value once per session
async function onLoad1(executionContext) {
    let settingValue = sessionStorage.getItem(SETTING_VALUE_SESSION_STORAGE_KEY);

    // Ensure there is a stored setting value to use
    if (settingValue === null || settingValue === undefined) {
        settingValue = await requestSettingValue();
    }

    // Do logic with setting value here
}

// Retrieve setting value with stale-while-revalidate strategy
async function onLoad2(executionContext) {
    let settingValue = sessionStorage.getItem(SETTING_VALUE_SESSION_STORAGE_KEY);

    // Revalidate, but only await if session storage value is not present
    const requestPromise = requestSettingValue();

    // Ensure there is a stored setting value to use the first time in a session
    if (settingValue === null || settingValue === undefined) {
        settingValue = await requestPromise;
    }
    
    // Do logic with setting value here
}

// Retrieve setting value with stale-while-revalidate and deduplication strategy
let requestPromise;
async function onLoad3(executionContext) {
    let settingValue = sessionStorage.getItem(SETTING_VALUE_SESSION_STORAGE_KEY);

    // Request setting value again but don't wait on it
    // In case this handler fires twice, don’t make the same request again if it is already in flight
    // Additional logic can be added so that this is done less than once per page
    if (!requestPromise) {
        requestPromise = requestSettingValue().finally(() => {
            requestPromise = undefined;
        });
    }

    // Ensure there is a stored setting value to use the first time in a session
    if (settingValue === null || settingValue === undefined) {
        settingValue = await requestPromise;
    }
    
    // Do logic with setting value here
}

async function requestSettingValue() {
    try {
        const data = await Xrm.WebApi.retrieveRecord(
            SETTING_ENTITY_NAME,
            "7333e80e-9b0f-49b5-92c8-9b48d621c37c",
            `?$select=${SETTING_FIELD_NAME}`);
        try {
            sessionStorage.setItem(SETTING_VALUE_SESSION_STORAGE_KEY, data[SETTING_FIELD_NAME]);
        } catch (error) {
            // Handle sessionStorage error
        } finally {
            return data[SETTING_FIELD_NAME];
        }
    } catch (error) {
        // Handle retrieveRecord error   
    }
}

Folosiți informațiile disponibile în API-ul clientului în loc să faceți cereri. De exemplu, în loc să solicitați rolurile de securitate ale unui utilizator la încărcarea formularului, puteți utiliza getGlobalContext.userSettings.roles.

Încărcați codul numai atunci când este necesar

Încărcați cât de mult cod este necesar pentru evenimente pentru un anumit formular. Dacă aveți cod care este numai pentru formularul A și formularul B, nu ar trebui să fie inclus într-o bibliotecă pentru care este încărcată pentru formularul C. Ar trebui să fie în propria sa bibliotecă.

Evitați încărcarea bibliotecilor în evenimentul OnLoad dacă sunt utilizate numai pentru evenimentele OnChange sau OnSave. În schimb, încărcați-le în acele evenimente. Astfel, platforma poate amâna încărcarea acestora până după încărcarea formularului. Mai multe informații: Optimizați performanța formularului

Eliminați utilizarea API-urilor consolei în codul de producție

Nu folosiți metodele API-ului consolei cum ar fi console.log în codul de producție. Înregistrarea datelor în consolă poate crește semnificativ cererea de memorie și poate împiedica astfel curățarea datelor în memorie. Acest lucru poate face ca aplicația să devină mai lentă în timp și, în cele din urmă, să se blocheze.

Evitați scurgerile de memorie

Scurgerile de memorie din codul dvs. pot duce la o performanță mai lentă în timp și, în cele din urmă, pot duce la blocarea aplicației. Scurgerile de memorie apar atunci când aplicația nu reușește să elibereze memorie, atunci când nu mai este necesară. Cu toate particularizările și componentele de cod din formularul dvs., ar trebui să:

  • Luați în considerare și testați cu atenție scenariile pentru orice este responsabil pentru curățarea memoriei, cum ar fi clasele responsabile pentru gestionarea ciclului de viață al obiectelor.
  • Curățați toate codurile de ascultare a evenimentelor și abonamentele, mai ales dacă sunt pe obiectul window.
  • Curățați toate temporizatoarele, cum ar fi setInterval.
  • Evitați, limitați și curățați referințele la obiecte globale sau statice.

Pentru componentele de control particularizate, curățarea se poate face cu metoda distrugerii.

Pentru mai multe informații despre remedierea problemelor de memorie, accesați această documentație pentru dezvoltatori Edge.

Instrumente pe care le puteți utiliza pentru a face aplicațiile performante

Această secțiune descrie instrumentele care vă pot ajuta să înțelegeți problemele de performanță și oferă recomandări despre cum să vă optimizați particularizările în aplicațiile proiectate pe bază de model.

Detalii despre performanță

Detaliile de performanță sunt un instrument de autoservire pentru producătorii de aplicații de întreprindere, care analizează datele de telemetrie runtime și oferă o listă prioritară de recomandări pentru a ajuta la îmbunătățirea performanței aplicațiilor proiectate pe bază de model. Această caracteristică oferă un set zilnic de informații analitice legate de performanța unui aplicații Power Apps proiectată pe bază de model sau de implicare a clienților, precum Dynamics 365 Sales sau Dynamics 365 Service, cu recomandări și articole care pot fi acționate. Producătorii de aplicații pentru întreprinderi pot vizualiza detalii amănunțite despre performanță la nivel de aplicație în Power Apps. Mai multe informații: Ce sunt detaliile despre performanță? (versiune preliminară)

Verificator de soluții

Solution Checker este un instrument puternic care poate analiza particularizările clientului și serverului pentru probleme de performanță sau fiabilitate. Poate analiza JavaScript din partea clientului, formularul XML și plug-in-urile de pe server .NET și poate oferi detalii vizate despre ceea ce poate încetini utilizatorii finali. Vă recomandăm să rulați Solution Checker de fiecare dată când publicați modificări într-un mediu de dezvoltare, astfel încât să apară orice probleme de performanță înainte de a ajunge la utilizatorii finali. Informații suplimentare: Utilizați verificatorul de soluții pentru a valida aplicațiile pe bază de model în Power Apps

Câteva exemple de probleme legate de performanță găsite cu Solution Checker:

Verificator de obiecte

Verificatorul de obiecte execută diagnosticarea în timp real pe obiectele de componente din soluția dvs. Dacă sunt detectate probleme, se returnează o recomandare care descrie cum să remediați problema. Mai multe informații: Folosiți verificatorul de obiecte pentru a diagnostica o componentă a soluției (versiune preliminară)

Pașii următori

Proiectați formulare principale productive în aplicații proiectate pe bază de model