Share via


Designe formularer for ydeevne i modelbaserede apps

Erfaringen med at udføre opgaver hurtigt og effektivt er vigtig for at skabe brugertilfredshed. Modelbaserede apps kan tilpasses og skabe oplevelser, der opfylder dine brugeres behov, men det er vigtigt at vide, hvordan du effektivt kan kode, opbygge og køre modeldrevne apps, der indlæses hurtigt, når en bruger åbner og navigerer i appen, mens brugeren arbejder på daglige opgaver. Ydeevnen har vist sig at være en væsentlig driver for utilfredsheden i en app, når den ikke er optimeret til ydeevne.

Intelligente tilpasninger og effektive formularer er vigtige aspekter i forbindelse med opbygning af yderst effektive og produktive formularer. Det er også vigtigt at sikre, at du bygger yderst produktive formularer med de bedste fremgangsmåder i design og layout af brugergrænsefladen. Du kan finde oplysninger om design af formularer for at opnå effektivitet og produktivitet i Design af primære formularer for produktive programmer i modelbaserede apps.

Det er også vigtigt at sikre, at brugerne er på anbefalede og understøttede enheder samt minimumkrav til specifikationerne. Flere oplysninger: Understøttede webbrowsere og mobilenheder

Arbejde med data og faner

I dette afsnit vises, hvordan kontrolelementer, der viser data og faner, påvirker formularens ydeevne.

Oversigt over standardfanen

Standardfanen er den første udvidede fane i en formular. Den giver en særlig rolle ved indlæsning af en formularside. Kontrolelementerne under standardfanen gengives som design altid, når en post åbnes. Specielt initialiseringslogikken for kontrolelementet, f.eks. hentning af data, aktiveres for alle kontrolelementer under fanen.

Derimod udfører en sekundær fane ikke denne initialisering på kontrolelementerne, når formularen først indlæses. Kontrolelement initialisering sker i stedet på det tidspunkt, hvor den sekundære fane åbnes enten via brugerinteraktion eller ved at kalde setFocus-klient-API-metoden. Det giver dig mulighed for at undgå den første formularbelastning fra overdreven kontrolbehandling ved at placere bestemte kontrolelementer under sekundære faner i stedet for standardfanen. Styringsplaceringsstrategien kan derfor have en betydelig effekt på den responsivitet, der er ved den første formularbelastning. En mere responsiv standardfane giver en bedre overordnet oplevelse med hensyn til ændring af vigtige felter, interaktion med kommandolinjen og udforskning af andre faner og sektioner.

Du skal altid placere de kontrolelementer, der bruges mest, øverst på standardfanen. Layout- og informationsarkitekturen er ikke kun vigtig for ydeevnen, men også for at øge produktiviteten, når brugere kommunikerer med data i formularen. Flere oplysninger: Design produktive hovedformularer i modelbaserede apps

Databaserede kontrolelementer

Kontrolelementer, der kræver ekstra data ud over den primære post, skaber den største belastning på form responsivebelastning og indlæsningshastighed. Disse kontrolelementer henter data over netværket og involverer ofte en ventetid (opfattes som statusindikator), da det kan tage tid at overføre dataene.

Nogle af de databaserede kontrolelementer omfatter:

Bevar kun de mest anvendte af disse kontrolelementer under standardfanen. De resterende databaserede kontrolelementer skal distribueres til sekundære faner, så standardfanen kan indlæses hurtigt. Denne layoutstrategi reducerer risikoen for at hente data, der ender med at være ubrugte.

Der findes andre kontrolelementer, der er mindre indflydelsesfulde end de databaserede kontrolelementer, men som stadig kan deltage i ovenstående layoutstrategi for at opnå den bedste ydeevne. Disse kontrolelementer omfatter:

Webbrowser

I dette afsnit vises en god praksis, du kan bruge sammen med webbrowsere.

Åbn ikke nye vinduer

Ved hjælp af openForm-klient-API-metoden kan en parameterindstilling vise en formular i et nyt vindue. Brug ikke denne parameter, eller indstil den til false. Hvis den angives til false, sikres det, at openForm-metoden fungerer som standard for visning af formularen ved hjælp af det eksisterende vindue. Det er også muligt direkte at kalde window.open-JavaScript-funktionen fra et brugerdefineret script eller et andet program, men det skal også fungere som en hjælp. Hvis du åbner et nyt vindue, betyder det, at alle sideressourcer skal hentes og indlæses fra bunden, da siden ikke kan udnytte cachefunktionerne for cachelagring af data i hukommelsen mellem en tidligere indlæst formular og formularen i et nyt vindue. Som et alternativ til at åbne nye vinduer kan du overveje at bruge multisession-oplevelsen, der gør det muligt at åbne poster under flere faner, samtidig med at du stadig maksimerer ydeevnefordelene ved klientcaching.

Brug moderne browsere

Det er vigtigt at bruge den nyeste webbrowser for at sikre, at din modelbaserede app kører så hurtigt som muligt. Årsagen til dette er, at mange af de forbedrede funktioner kun kan bruges i nyere, moderne browsere.

Hvis din organisation f.eks. har ældre versioner af Firefox, ikke-Chromium-baserede browsere osv., er mange af de præstationsforbedringer, der er indbygget i en modelbaseret app, ikke tilgængelige i de ældre browserversioner, fordi de ikke understøtter funktioner, som appen er afhængige af at køre hurtigt og problemfrit.

I de fleste tilfælde kan du forvente at se forbedringer af sideindlæsningen ved blot at skifte til Microsoft Edge, opdatere til den nyeste aktuelle browserversion fra en ældre version eller flytte til en moderne Chromium-baseret browser.

Tilpasning af JavaScript

I dette afsnit kan du se, hvordan du kan foretage intelligente tilpasninger, når du bruger JavaScript, der kan hjælpe dig med at udvikle performante formularer og sider i en modelbaseret app.

Brug af JavaScript med formularer

Muligheden for, at formularer kan tilpasses af JavaScript, giver professionelle udviklere stor fleksibilitet til at se, hvordan en formular ser ud og fungerer. Den fleksible brug af denne fleksibilitet kan have en negativ indvirkning på formularydeevnen. Udviklere skal bruge følgende strategier til at maksimere formularydeevnen, når de implementerer JavaScript-tilpasninger.

Brug asynkrone netværksanmodninger, når du anmoder om data

Anmode om data asynkront i stedet for synkront, når der er brug for ekstra data i forbindelse med tilpasninger. I forbindelse med hændelser, der understøtter, at de venter på asynkron kode som f.eks. formular-OnLoad og OnSave-formularhændelser, skal hændelseshandlere returnere en Promise, så platformen kan vente, til Promise-platformen er klar til brug. På platformen vises den relevante brugergrænseflade, mens brugeren venter på, at arrangementet fuldføres.

I forbindelse med hændelser, der ikke understøtter, hvor du venter på asynkron kode, f.eks. OnChange-formularhændelsen, kan du bruge en løsning til at stoppe interaktionen med en formular, mens koden udfører en asynkron forespørgsel ved hjælp af showProgressIndicator. Det er bedre end at bruge synkrone forespørgsler, da brugere stadig kan arbejde med andre dele af programmet, mens der vises en statusindikator.

Her er et eksempel ved hjælp af asynkron kode i synkrone udvidelsespunkter.

//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);

Du skal være forsigtig, når du bruger asynkron kode i en hændelseshandler, der ikke understøtter ventetid på asynkron kode. Det gælder især for kode, der skal bruges en handling, som skal foretages eller håndteres i forbindelse med løsningen af den asynkrone kode. Asynkron kode kan give problemer, hvis løsningshåndteringen forventer, at programkonteksten forbliver den samme som den, da den asynkrone kode blev startet. Koden skal kontrollere, at brugeren er i den samme kontekst efter hvert asynkront punkt.

Der kan f.eks. være kode i en hændelseshandler til at oprette en netværksanmodning og ændre et kontrolelement, der skal deaktiveres på baggrund af responsdataene. Før svaret fra anmodningen modtages, har brugeren muligvis kommunikeret med kontrolelementet eller navigeret til en anden side. Da brugeren er på en anden side, er formularkonteksten muligvis ikke tilgængelig, hvilket kan medføre fejl, eller der kan være en anden uønsket funktionsmåde.

Understøttelse af asynkronisering i formularen OnLoad og formularhændelser på OnSave

Formularen OnLoad og hændelserne OnSave understøtter handlere, der returnerer tilsagn. Hændelserne venter på, at alle kørsler, der returneres af en handler, afsluttes op til en timeoutperiode. Denne understøttelse kan aktiveres via appindstillinger.

Flere oplysninger:

Begræns den mængde data, der anmodes om under formularindlæsning

Du skal kun anmode om den minimumantal data, der er nødvendig for at udføre forretningslogik på en formular. Cachelagre de data, der anmodes om, så meget som muligt, især for data, der ikke ændres ofte eller ikke behøver at være nye. Forestil dig f.eks., at der findes en formular, hvor der anmodes om data fra en indstillingstabel. Afhængigt af dataene i indstillingstabellen kan formularen vælge at skjule en sektion i formularen. I dette tilfælde kan JavaScript cachelagre data i sessionStorage, så der kun anmodes om data én gang pr. session (onLoad1). En forældet strategi kan også bruges, hvor JavaScript bruger dataene fra sessionStorage, mens der anmodes om data til næste navigation til formularen (onLoad2). Til sidst kan der bruges en duplikeringsstrategi, hvis en handler kaldes flere gange i en række (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   
    }
}

Brug de oplysninger, der er tilgængelige i klient-API'en, i stedet for at foretage forespørgsler. I stedet for at anmode om en brugers sikkerhedsroller i forbindelse med formularindlæsning kan du f.eks. bruge getGlosettingContext.userSettings.roles.

Indlæs kun kode, når der er behov for det

Indlæs så meget kode, der er nødvendigt for hændelser i en bestemt formular. Hvis du har kode, der kun gælder for formular A og formular B, skal den ikke inkluderes i et bibliotek, der indlæses for formular C. Det skal være i sit eget bibliotek.

Undgå at indlæse biblioteker i tilfælde af OnLoad, at de kun bruges til OnChange- eller OnSave-hændelserne. Indlæs dem i stedet i disse hændelser. På denne måde kan platformen udskyde indlæsningen af dem, indtil formularen er indlæst. Flere oplysninger: Optimering af formularens ydeevne

Fjerne brugen af konsol-API'er i produktionskoden

Brug ikke konsol-API-metoderne, f.eks. console.log i produktionskode. Logføring af data i konsollen kan øge hukommelsesefterspørgslen betydeligt og kan forhindre, at data ryddes op i hukommelsen. Det kan medføre, at appen bliver langsommere og til sidst går ned.

Undgå hukommelseshuller

Hukommelseshuller i koden kan medføre langsommere ydeevne over tid og til sidst medføre, at din app går ned. Der opstår hukommelseshuller, når programmet ikke frigiver hukommelsen, når der ikke længere er behov for den. Du skal gøre følgende ved hjælp af alle tilpasninger og kodekomponenter i formularen:

  • Nøje overveje og teste scenarier for alt, hvad der er ansvarligt for at rydde op i hukommelsen, f.eks. klasser, der er ansvarlige for administration af objekters livscyklus.
  • Ryd op i alle hændelses-lyttefunktioner og abonnementer, især hvis den findes på window-objektet.
  • Ryd op i alle timere som setInterval.
  • Undgå, begræns og ryd op i referencer til globale eller statiske objekter.

I forbindelse med brugerdefinerede kontrolkomponenter kan oprydning foretages ved hjælp af metoden ødelæg.

Du kan finde flere oplysninger om, hvordan du løser problemer med hukommelsen, i denne dokumentation til Edge-udvikler.

Værktøjer, du kan bruge til at få apps til at virke optimalt

I dette afsnit beskrives de værktøjer, der kan hjælpe dig med at forstå ydeevneproblemer og komme med anbefalinger til, hvordan du kan optimere tilpasningerne i modelbaserede apps.

Indsigt i ydeevne

Ydelsesindsigt er et selvbetjeningsværktøj for appudviklere i virksomheder, der analyserer kørselstelemetridata, og som indeholder en prioriteringsliste med anbefalinger, der kan hjælpe med at forbedre ydeevnen i modelbaserede apps. Denne funktion indeholder et dagligt sæt analytiske indsigter, der er relateret til ydeevnen for en modelbaseret Power Apps-app eller en Customer Engagement-app som f.eks. Dynamics 365 Sales eller Dynamics 365 Service, med anbefalinger og elementer, du kan handle ud fra. Enterprise-appudviklere kan se en detaljeret indsigt i ydeevnen på appniveau i Power Apps. Flere oplysninger: Hvad er indsigt i resultater? (forhåndsversion)

Løsningskontrol

Løsningskontrol er et effektivt værktøj, der kan analysere klient- og servertilpasninger for at løse problemer med ydeevne eller stabilitet. Den kan fortolke JavaScript på klientsiden, oprette XML- og .NET-plug-ins på serversiden og give en målrettet indsigt i, hvad der kan gøre slutbrugerne langsommere. Det anbefales, at du kører løsningskontrollen, hver gang du publicerer ændringer i et udviklingsmiljø, så eventuelle ydeevneproblemer bliver overfladebehandlet, inden du når ud til slutbrugerne. Flere oplysninger: Brug af løsningskontrol til at validere dine modelbaserede apps i Power Apps

Nogle eksempler på ydeevnerelaterede problemer, der blev fundet i løsningskontrollen:

Objektkontrol

Objektkontrolelementet kører diagnosticeringsværktøjet i realtid for komponentobjekter i løsningen. Hvis der registreres problemer, returneres der en anbefaling, som beskriver, hvordan problemet kan afhjælpes. Flere oplysninger: Brug objektkontrol til at diagnosticere en løsningskomponent (forhåndsversion)

Næste trin

Designproduktiv hovedformularer i modelbaserede apps