Share via


Formulieren ontwerpen voor prestaties in modelgestuurde apps

Het bouwen van ervaringen waarbij taken snel en efficiënt kunnen worden voltooid, is cruciaal voor de tevredenheid van gebruikers. Modelgestuurde apps kunnen sterk worden aangepast om ervaringen te creëren die voldoen aan de behoeften van uw gebruikers, maar het is belangrijk om te weten hoe u op effectieve wijze modelgestuurde apps codeert, bouwt en uitvoert die snel worden geladen wanneer een gebruiker uw app opent en navigeert tijdens het werken aan dagelijkse taken. Het is aangetoond dat prestaties een belangrijke oorzaak zijn van ontevredenheid over een app wanneer deze niet is geoptimaliseerd voor prestaties.

Intelligente aanpassingen en goed werkende formulieren zijn belangrijke aspecten voor het bouwen van zeer efficiënte en productieve formulieren. Het is ook belangrijk om ervoor te zorgen dat u zeer productieve formulieren bouwt met de aanbevolen procedures bij het ontwerp en de lay-out van de gebruikersinterface. Zie voor informatie over het ontwerpen van formulieren voor efficiëntie en productiviteit Productieve hoofdformulieren in modelgestuurde apps ontwerpen.

Het is ook belangrijk om ervoor te zorgen dat gebruikers werken met aanbevolen en ondersteunde apparaten en minimaal vereiste specificaties. Meer informatie: Ondersteunde webbrowsers en mobiele apparaten

Werken met numerieke gegevens en tabbladen

In deze sectie wordt beschreven hoe besturingselementen die gegevens en tabbladen weergeven van invloed zijn op de prestaties van formulieren.

Betekenis van het standaardtabblad

Het standaardtabblad is het eerste uitgevouwen tabblad op een formulier. Het speelt een speciale rol bij het laden van een formulierpagina. Door het ontwerp worden de besturingselementen van het standaardtabblad altijd weergegeven bij het openen van een record. In het bijzonder wordt de besturingsinitialisatielogica, zoals het ophalen van gegevens, aangeroepen voor elk besturingselement op het tabblad.

Een secundair tabblad voert deze initialisatie daarentegen niet uit op zijn besturingselementen uit wanneer het formulier voor het eerst wordt geladen. In plaats daarvan vindt de besturingselementeninitialisatie plaats op het moment dat het secundaire tabblad wordt geopend, hetzij door gebruikersinteractie of door het aanroepen van de API-methode setFocus-client. Dit biedt de mogelijkheid om het initiële laden van het formulier te beschermen tegen overmatige besturingsverwerking door bepaalde besturingselementen op secundaire tabbladen te plaatsen in plaats van op het standaardtabblad. De plaatsingsstrategie van het besturingselement kan dus een significant effect hebben op het reactievermogen van het initiële laden van het formulier. Een meer responsief standaardtabblad biedt een betere algehele ervaring voor het wijzigen van belangrijke velden, interactie met de opdrachtbalk en het verkennen van andere tabbladen en secties.

Zet besturingselementen die het meest worden gebruikt altijd boven aan uw standaardtabblad. Lay-out en informatiearchitectuur zijn niet alleen belangrijk voor de prestaties, maar ook voor het verbeteren van de productiviteit wanneer gebruikers interactie hebben met gegevens op het formulier. Meer informatie: Productieve hoofdformulieren in modelgestuurde apps ontwerpen

Gegevensgestuurde bedieningselementen

Besturingselementen die extra gegevens nodig hebben buiten de primaire record, veroorzaken de meeste druk op de reactiesnelheid en laadsnelheid van formulieren. Deze besturingselementen halen gegevens op via het netwerk en brengen vaak een wachttijd met zich mee (gezien als voortgangsindicatoren) omdat het enige tijd kan duren om de gegevens te verzenden.

Enkele van de gegevensgestuurde besturingselementen zijn:

Bewaar alleen de meest gebruikte van deze besturingselementen op het standaardtabblad. De overige gegevensgestuurde besturingselementen moeten worden verdeeld over secundaire tabbladen zodat het standaardtabblad snel kan worden geladen. Bovendien verkleint deze lay-outstrategie de kans op het ophalen van gegevens die uiteindelijk ongebruikt blijven.

Er zijn andere besturingselementen die minder impact hebben dan de gegevensgestuurde besturingselementen, maar toch kunnen deelnemen aan de bovenstaande lay-outstrategie om de beste prestaties te bereiken. Deze besturingselementen omvatten:

Webbrowser

In dit gedeelte worden de juiste methoden beschreven voor gebruik met webbrowsers.

Open geen nieuwe vensters

De API-methode openForm-client staat een parameteroptie toe om een formulier in een nieuw venster weer te geven. Gebruik deze parameter niet en stel deze in op false. Als u dit op false instelt, zorgt u ervoor dat de openForm-methode het standaardgedrag uit van het weergeven van het formulier met behulp van het bestaande venster. Het is ook mogelijk om direct de JavaScript-functie window.open aan te roepen vanuit een aangepast script of een andere toepassing, maar ook dit moet worden vermeden. Het openen van een nieuw venster betekent dat alle paginabronnen moeten worden opgehaald en helemaal opnieuw moeten worden geladen, aangezien de pagina niet in staat is om de mogelijkheden voor in-memory gegevens-caching tussen een eerder geladen formulier en het formulier in een nieuw venster te benutten. Als alternatief voor het openen van nieuwe vensters kunt u overwegen de multisessie-ervaring te gebruiken waarmee records op meerdere tabbladen kunnen worden geopend, terwijl u toch de prestatievoordelen van clientcaching kunt maximaliseren.

Gebruik moderne browsers

Het gebruik van de meest actuele webbrowser is essentieel om ervoor te zorgen dat uw modelgestuurde app zo snel mogelijk werkt. De reden hiervoor is dat veel van de prestatieverbeteringen alleen in de nieuwere moderne browsers kunnen worden gebruikt.

Als uw organisatie bijvoorbeeld oudere versies van heeft van Firefox, niet op Chromiu gebaseerde browsers, enzovoort, zullen veel van de prestatieverbeteringen die zijn ingebouwd in een modelgestuurde app niet beschikbaar zijn in de oudere browserversies omdat ze geen functies ondersteunen waarvan de app afhankelijk is om snel en vlot te kunnen werken.

In de meeste gevallen kunt u verbeteringen in het laden van de pagina's verwachten door gewoon over te schakelen naar Microsoft Edge, te updaten naar de nieuwste huidige browserversie van een oudere versie of door over te stappen naar een moderne, op Chromium gebaseerde browser.

JavaScript-aanpassing

In dit gedeelte wordt beschreven hoe u intelligente aanpassingen kunt maken wanneer u JavaScript gebruikt waarmee u goed werkende formulieren en pagina's kunt bouwen in een modelgestuurde app.

JavaScript gebruiken met formulieren

De mogelijkheid om formulieren door JavaScript te laten aanpassen, biedt professionele ontwikkelaars grote flexibiliteit over hoe een formulier eruitziet en zich gedraagt. Het oneigenlijk gebruik van deze flexibiliteit kan een negatieve invloed hebben op de formulierprestaties. Ontwikkelaars moeten de volgende strategieën gebruiken om formulierprestaties te maximaliseren bij het implementeren van JavaScript-aanpassingen.

Gebruik asynchrone netwerkaanvragen bij het opvragen van gegevens

Vraag gegevens asynchroon op in plaats van synchroon wanneer extra gegevens nodig zijn voor aanpassingen. Voor gebeurtenissen die wachten op asynchrone code ondersteunen, zoals de formuliergebeurtenissen OnLoad en OnSave, moeten gebeurtenishandlers een Promise retourneren zodat het platform kan wachten tot de Promise wordt geregeld. Het platform toont een geschikte gebruikersinterface terwijl de gebruiker wacht tot de gebeurtenis is voltooid.

Voor gebeurtenissen die wachten op asynchrone code niet ondersteunen, zoals de formuliergebeurtenis OnChange, kunt u een tijdelijke oplossing gebruiken om de interactie met een formulier te stoppen terwijl de code een asynchrone aanvraag doet met behulp van showProgressIndicator. Dit is beter dan het gebruik van synchrone aanvragen, omdat gebruikers nog steeds in staat zullen zijn om met andere delen van de toepassing te communiceren terwijl er een voortgangsindicator wordt weergegeven.

Hier is een voorbeeld van het gebruik van asynchrone code in synchrone uitbreidingspunten.

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

Wees voorzichtig bij het gebruik van asynchrone code in een gebeurtenishandler die wachten op asynchrone code niet ondersteunt. Dit geldt met name voor code waarvoor een actie moet worden ondernomen of moet worden afgehandeld bij het oplossen van de asynchrone code. Asynchrone code kan problemen veroorzaken als de oplossingshandler verwacht dat de toepassingscontext hetzelfde blijft als toen de asynchrone code werd gestart. Uw code moet controleren of de gebruiker zich in dezelfde context bevindt na elk asynchroon voortzettingspunt.

Er kan bijvoorbeeld code in een gebeurtenishandler zijn om een netwerkaanvraag te doen en een besturingselement te wijzigen zodat deze is uitgeschakeld op basis van de responsgegevens. Voordat het antwoord van de aanvraag is ontvangen, kan de gebruiker interactie hebben gehad met het besturingselement of naar een andere pagina zijn genavigeerd. Omdat de gebruiker zich op een andere pagina bevindt, is de formuliercontext mogelijk niet beschikbaar. Dit kan leiden tot fouten of ander ongewenst gedrag.

Asynchrone ondersteuning in gebeurtenissen OnLoad en OnSave voor formulieren

De gebeurtenissen OnLoad en OnSave voor formulieren ondersteunen handlers die promises retourneren. De gebeurtenissen wachten tot eventuele door een handler geretourneerde promises zijn opgelost tot een time-outperiode. Deze ondersteuning kan worden ingeschakeld via app-instellingen.

Meer informatie:

Beperk de hoeveelheid gevraagde gegevens tijdens het laden van het formulier

Vraag alleen de minimale hoeveelheid gegevens op die nodig is om bedrijfslogica op een formulier uit te voeren. Cache de gegevens die worden opgevraagd zo veel mogelijk, vooral voor gegevens die niet vaak veranderen of niet vers hoeven te zijn. Stelt u zich bijvoorbeeld voor dat er een formulier is dat gegevens opvraagt van een instelling-tabel. Op basis van de gegevens in de instellingtabel kan het formulier ervoor kiezen om een gedeelte van het formulier te verbergen. In dit geval kan het JavaScript gegevens cachen in sessionStorage zodat gegevens slechts één keer per sessie worden opgevraagd (onLoad1). Er kan ook een strategie worden gebruikt om de verouderde versie opnieuw te valideren wanneer JavaScript de gegevens gebruikt van sessionStorage terwijl u gegevens opvraagt voor de volgende navigatie naar het formulier (onLoad2). Ten slotte kan een deduplicatiestrategie worden gebruikt in het geval dat een handler meerdere keren achter elkaar wordt aangeroepen (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   
    }
}

Gebruik informatie die beschikbaar is in de client-API in plaats van aanvragen te doen. In plaats van bijvoorbeeld de beveiligingsrollen van een gebruiker op te vragen bij het laden van een formulier, kunt u gebruik maken van getGlobalContext.userSettings.roles.

Laad code alleen wanneer het nodig is

Laad zoveel code als nodig is voor gebeurtenissen voor een bepaald formulier. Als u een code hebt die alleen voor formulier A en formulier B is, mage deze niet worden opgenomen in een bibliotheek die is geladen voor formulier C. De code zou in zijn eigen bibliotheek moeten staan.

Vermijd het laden van bibliotheken in de gebeurtenis OnLoad als ze alleen worden gebruikt voor de gebeurtenis OnChange ofOnSave. Laad ze in plaats daarvan in die gebeurtenissen. Op deze manier kan het platform het laden uitstellen tot nadat het formulier is geladen. Meer informatie: Formulierprestaties optimaliseren

Gebruik van console-API's in productiecode verwijderen

Gebruik niet console-API-methoden zoals console.log in productiecode. Het loggen van gegevens op de console kan de geheugenbehoefte aanzienlijk vergroten en kan voorkomen dat gegevens in het geheugen worden opgeschoond. Dit kan ertoe leiden dat de app na verloop van tijd langzamer wordt en uiteindelijk crasht.

Geheugenlekken voorkomen

Geheugenlekken in uw code kunnen na verloop van tijd leiden tot tragere prestaties tot uw app uiteindelijk vastloopt. Geheugenlekken treden op wanneer de toepassing er niet in slaagt om geheugen vrij te geven wanneer het niet langer nodig is. Voor alle aanpassingen en codecomponenten in uw formulier moet u het volgende doen:

  • Goed nadenken over en testen uitvoeren op alles wat verantwoordelijk is voor het opschonen van geheugen, zoals klassen die verantwoordelijk zijn voor het beheer van de levenscyclus van objecten.
  • Alle gebeurtenislisteners en abonnementen opschonen, met name in het object window.
  • Alle timers opschonen zoals setInterval.
  • Verwijzingen naar algemene of statische objecten vermijden, beperken en opschonen.

Voor onderdelen van aangepaste besturingselementen kan opschoning plaatsvinden in de destroy-methode.

Ga voor meer informatie over het oplossen van geheugenproblemen naar deze Edge-ontwikkelaarsdocumentatie.

Hulpprogramma's die u kunt gebruiken om apps beter te laten presteren

In dit gedeelte worden de hulpprogramma's beschreven die u kunnen helpen prestatieproblemen te begrijpen en die aanbevelingen doen voor het optimaliseren van uw aanpassingen in modelgestuurde apps.

Prestatie-inzichten

Prestatie-inzichten is een selfservice-hulpprogramma voor makers van zakelijke apps, die runtime-telemetriegegevens analyseert en een geprioriteerde lijst met aanbevelingen biedt om de prestaties van modelgestuurde apps te verbeteren. Deze functie biedt een dagelijkse reeks analytische inzichten met betrekking tot de prestaties van een Power Apps modelgestuurde of klantbetrokkenheid-app, zoals Dynamics 365 Sales of Dynamics 365 Service, met aanbevelingen en bruikbare items. Makers van zakelijke apps kunnen gedetailleerde prestatie-inzichten op app-niveau bekijken in Power Apps. Meer informatie: Wat zijn prestatie-inzichten? (preview)

Oplossingscontrole

Oplossingscontrole is een krachtig hulpmiddel dat client- en serveraanpassingen kan analyseren op prestatie- of betrouwbaarheidsproblemen. Het kan JavaScript aan clientzijde parseren, XML-formulieren en .NET-serverinvoegtoepassen aan serverzijde en gerichte inzichten geven in wat eindgebruikers kan vertragen. We raden u aan om elke keer dat u wijzigingen in een ontwikkelomgeving publiceert de oplossingscontrole uit te voeren, zodat eventuele prestatieproblemen aan het licht komen voordat de eindgebruikers worden bereikt. Meer informatie: Oplossingscontrole gebruiken om uw modelgestuurde apps te valideren in Power Apps

Enkele voorbeelden van prestatiegerelateerde problemen die zijn gevonden met de oplossingscontrole:

Objectcontrole

Tijdens een objectcontrole wordt realtime diagnostiek uitgevoerd op onderdeelobjecten in uw oplossing. Als er problemen worden gedetecteerd, wordt een aanbeveling geretourneerd waarin wordt beschreven hoe het probleem kan worden opgelost. Meer informatie: Objectcontrole gebruiken om een oplossingsonderdeel te diagnosticeren (preview)

Volgende stappen

Productieve hoofdformulieren ontwerpen in modelgestuurde apps