Share via


Utforma formulär för prestanda i modellbaserade appar

Att skapa erfarenheter där uppgifter kan utföras snabbt och effektivt är en förutsättning för användarnas tillfredsställelse. Modellbaserade appar kan anpassas mycket för att skapa erfarenheter som uppfyller användarnas behov, men det är viktigt att du vet hur man kan koda, skapa och köra modellstyrda appar som kan läsas in snabbt när en användare öppnar och navigerar i appen medan de arbetar med dagliga uppgifter. Prestanda har visat sig vara en viktig faktor för ett missnöjd program när den inte är optimerad för prestanda.

Intelligenta anpassningar och avancerade formulär är viktiga aspekter när det gäller att skapa mycket effektiva och produktiva formulär. Det är också viktigt att du skapar mycket produktiva formulär med bästa arbetssätt när det gäller design och layout i användargränssnittet. Information om hur du utformar formulär för effektivitet och produktivitet finns i Utforma produktiva huvudformulär i modellbaserade appar.

Det är också viktigt att se till att användarna har de enheter som rekommenderas och stöds och att de har de specifikationer som krävs som minst. Mer information: Webbläsare och mobila enheter som stöds

Arbeta med data och tabeller

Det här avsnittet handlar om hur kontroller som visar data och flikar påverkar formulärets prestanda.

Standardflikens betydelse

Standardfliken är den första utökade fliken i ett formulär. Den har en särskild roll när en formulärsida läses in. Som standard renderas standardflikskontrollerna alltid när en post öppnas. Särskilt gäller att kontrollinitieringslogiken, till exempel hämtning av data, anropas för varje kontroll på fliken.

Initieringen utförs däremot inte på en sekundär flik på kontrollerna när formuläret läses in. Kontrollens initiering sker i stället när den sekundära fliken öppnas antingen via användarinteraktion eller anropar setFocus klientens API-metod. Detta gör det möjligt att skapa den ursprungliga formulärbelastningen från onödig kontrollbearbetning genom att placera vissa kontroller på sekundära flikar istället för standardfliken. Därför kan strategin för kontroll placering ha en stor effekt på det första formulärets belastning. Standardfliken som inte är standard fungerar bättre när du ändrar viktiga fält, interagerar med kommandofältet och utforskar andra flikar och avsnitt.

Placera alltid de kontroller som används mest överst på standardfliken. Layout och informationsarkitektur är inte bara viktigt för prestanda utan också för att förbättra produktiviteten när användare interagerar med data i formuläret. Mer information: Utforma produktiva huvudformulär i modellbaserade appar

Datastyrda kontroller

Kontroller som kräver extra data utöver den primära posten ger störst belastning på formulär och belastningshastigheten. Dessa kontroller hämtar data över nätverket och omfattar ofta en vänteperiod (ses som förloppets indikatorer) eftersom det kan ta tid att överföra data.

Några av de datadrivna kontrollerna är:

Använd bara de kontroller som används oftast på standardfliken. Återstående datastyrda kontroller bör distribueras till sekundära flikar så att standardfliken kan läsas in snabbt. Med den här layoutstrategin minskar risken för att hämta data som inte används längre.

Det finns andra kontroller som är mindre genomslagskraftiga än de datadrivna kontrollerna men som fortfarande kan delta i layoutstrategin ovan för att uppnå bästa prestanda. Dessa kontroller omfattar:

Webbläsare

Det här avsnittet innehåller metodtips för webbläsare.

Öppna inte nya fönster

Med openForm klient-API-metoden kan ett parameteralternativ visa ett formulär i ett nytt fönster. Använd inte den här parametern eller ange den som falskt. Om du anger den till falsk kommer du att säkerställa att openForm metoden utför standardbeteendet för att visa formuläret med det befintliga fönstret. Det går också att anropa window.open JavaScript-funktionen direkt från ett anpassat skript eller ett annat program, men detta bör också fungera. Om du öppnar ett nytt fönster måste alla sidresurser hämtas och läsas in från grunden eftersom sidan inte kan använda cachefunktionerna i minnet mellan ett tidigare inläst formulär och formuläret i ett nytt fönster. Som ett alternativ till att öppna nya fönster kan du överväga att använda flera sessionsupplevelsen som gör att poster kan öppnas på flera flikar samtidigt som du maximerar prestandafördelarna med klientcachelagring.

Använda modern webbläsare

Det är viktigt att du använder den allra senaste webbläsaren för att din modellbaserade app ska kunna köras så fort som möjligt. Anledningen till detta är att många av prestandaförbättringarna bara kan användas i de nyare modernare webbläsarna.

Om din organisation till exempel har äldre versioner av, Firefox icke-Chromium-baserade webbläsare och så vidare, kommer många av de prestanda som är inbyggda i en modellbaserad app inte att vara tillgängliga i de äldre webbläsarversionerna eftersom de inte stöder funktioner som appen är beroende av att de körs snabbt och smidigt.

I de flesta fall kan du förvänta dig förbättringar av sidbelastningen genom att bara växla till, Microsoft Edge uppdatera till den senaste aktuella webbläsarversionen från en äldre version eller flytta till en modern Chromium-baserad webbläsare.

JavaScript-anpassning

Det här avsnittet handlar om hur du skapar intelligenta anpassningar med JavaScript som hjälper dig att skapa formulär och sidor i en modellbaserad app.

Använda JavaScript med formulär

Möjligheten att anpassa formulär av JavaScript ger professionella utvecklare stor flexibilitet över hur ett formulär ser ut och fungerar. Om flexibiliteten används på ett negativt sätt kan det påverka formulärens prestanda. Utvecklare bör använda följande metoder för att maximera formulärprestanda när de implementerar JavaScript-anpassningar.

Använda asynkrona nätverksförfrågningar när du begär data

Begär data asynkront i stället för synkront när extra data behövs för anpassningar. För evenemang som stöder väntan på asynkron kod som formuläret OnLoad och formulär OnSave händelser, ska händelsehanterare returnera en Promise för att plattformen ska vänta tills Promise kvittas. Plattformen visar ett lämpligt användargränssnitt medan användaren väntar tills händelsen har slutförts.

För händelser som inte har stöd för att vänta på asynkron kod, till exempel OnChange formulärhändelsen, kan du använda en lösning för att stoppa interaktionen med ett formulär medan koden utför en asynkron begäran med hjälp av showProgressIndicator. Det här är bättre än att använda synkrona förfrågningar eftersom användarna fortfarande kan interagera med andra delar av programmet som en förloppssymbol.

Här är ett exempel på asynkron kod i synkrona anknytningspunkter.

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

Var försiktig när du använder asynkron kod i en händelsehanterare som inte har stöd för att vänta på asynkron kod. Detta gäller särskilt för kod som behöver en åtgärd som ska vidtas eller hanteras vid lösningen av den asynkrona koden. Asynkron kod kan orsaka problem om lösningshanteraren förväntar sig att programkontexten förblir densamma som den var när den asynkrona koden startades. Din kod bör kontrollera att användaren är i samma sammanhang efter varje asynkron felpunkt.

Det kan till exempel finnas kod i en händelsehanterare för att göra en nätverksbegäran och ändra en kontroll så att den inaktiveras utifrån svarsdata. Innan svaret från förfrågan tas emot kan användaren ha interagerat med kontrollen eller navigerat till en annan sida. Eftersom användaren finns på en annan sida kanske formulärkontexten inte är tillgänglig, vilket kan leda till fel eller leda till andra oönskade beteenden.

Async-stöd i OnLoad- och formulärhändelser för OnSave

Formulär OnLoad och OnSave evenemangssupport för hanterare som returnerar kunder. Händelserna inträffar i väntan på att en hanterare ska lösa problemet inom en tidsgräns. Supporten kan aktiveras via appinställningarna.

Mer information:

Begränsa mängden data som begärs under formulärbelastningen

Begär endast den minsta mängd data som krävs för att utföra affärslogik i ett formulär. Cachelagra data som krävs i så stor utsträckning som möjligt, särskilt för data som inte ändras ofta eller som inte behöver vara nya. Anta till exempel att det finns ett formulär som begär data från tabellen inställning. Utifrån data i inställningstabellen kan formuläret välja att dölja ett avsnitt i formuläret. I det här fallet kan JavaScript cachelagra data sessionStorage så att data endast begärs en gång per session (onLoad1). En gammal-medan-återvalideringsstrategi kan också användas där JavaScript använder data från sessionStorage medan du begär data för nästa navigering till formuläret (onLoad2). Slutligen kan du använda en dedupliceringsstrategi om en hanterare anropas flera gånger i rad (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   
    }
}

Använd information i klient-API:et i stället för att göra förfrågningar. I stället för att begära en användares säkerhetsroller vid inläsning av formulär kan du till exempel använda getGlobalContext.userSettings.roles.

Läs bara in kod när det behövs

Läs in så mycket kod som behövs för händelser för ett visst formulär. Om du har kod som endast är för formulär A och formulär B, det bör inte ingå i ett bibliotek som laddas för formulär C. Den ska finnas i ett eget bibliotek.

Undvik att läsa in bibliotek i OnLoad händelsen om de bara används för OnChange eller OnSave evenemangen. Ladda dem istället i dessa händelser. På så sätt kan plattformen vänta med att läsa in dem tills formuläret har läses in. Mer information: Optimera formulärprestanda

Ta bort användning av console API:er i produktionskoden

Använd inte konsol API-metoderna t.ex. console.log i produktionskod. Loggning av data till konsolen kan öka minnesbehovet betydligt och kan göra att data inte hamnar i minnet. Det kan leda till att appen blir för snabb med tiden och att den snabbt kraschar.

Undvik minnesförlust

Minnesfel i koden kan leda till prestanda över tid och leda till att appen kraschar. Minnesfel uppstår om programmet inte längre ger ut minne när det inte längre behövs. Med alla anpassningar och kodkomponenter i formuläret bör du:

  • Fundera på och testa olika scenarier för allt som är ansvarigt för att rensa minne, till exempel klasser som ansvarar för hantering av objekts livscykel.
  • Rensa alla händelselyssnare och prenumerationer, särskilt om de finns på window objektet.
  • Rensa alla timers som setInterval.
  • Undvik, begränsa och rensa referenser till globala eller statiska objekt.

För anpassade kontrollkomponenter kan rensning göras med metoden för förstör.

Mer information om hur du åtgärdar minnesproblem finns i Edge utvecklardokumentationen.

Verktyg som hjälper dig att utföra appar

I det här avsnittet beskrivs verktygen som kan hjälpa dig att förstå prestandaproblemen och ge rekommendationer om hur du optimerar anpassningarna i modelldrivna appar.

Prestandainsikter

Prestandainsikter är ett självbetjäningsverktyg för företagsappar som analyserar telemetridata under körning och tillhandahåller en prioriterad lista med rekommendationer som kan förbättra prestanda för modelldrivna appar. Den här funktionen ger en daglig uppsättning analytiska insikter relaterade till prestanda för en Power Apps modellbaserad eller kundengagemangsapp, till exempel Dynamics 365 Sales eller Dynamics 365 Service, med rekommendationer och handlingsbara artiklar. Beslutsfattare i företagsapp kan visa detaljerade resultatinsikter på appnivå i Power Apps. Mer information: Vad är prestandainsikter? (förhandsgranskning)

Lösningskontrollerare

Lösningskontrollen är ett kraftfullt verktyg som kan analysera klient- och serveranpassningar för prestanda- eller tillförlitlighetsproblem. Programmet kan tolka JavaScript-, formulär-XML- och .NET-plugin-program på klientsidan och ge riktade insikter om vad som kan göra slutanvändarna långsammare. Vi rekommenderar att du kör lösningskontrollen varje gång du publicerar ändringar i en utvecklingsmiljö, så att eventuella prestanda som infinna sig visas innan du når slutanvändarna. Mer information: Använd lösningskontroll för att verifiera dina modeldrivna appar i Power Apps

Några exempel på prestandarelaterade problem som hittats med lösningskontrollen:

Objektkontroll

Objektkontrollern kör diagnostik i realtid för komponentobjekt i lösningen. Om problem upptäcks returneras en rekommendation som beskriver hur du åtgärdar problemet. Mer information: Använd objektkontroll för att diagnostisera en komponent (förhandsgranskning)

Nästa steg

Designa produktiva formulär i modellbaserade appar