Suorituskykyisten lomakkeiden suunnittelu mallipohjaisissa sovelluksissa

Käyttäjätyytyväisyyden kannalta on ratkaisevaa, että tehtävien suorittaminen onnistuu luotavissa kokemuksissa nopeasti ja tehokkaasti. Mallipohjaisia sovelluksia voidaan mukauttaa merkittävästi siten, että niillä luodaan käyttäjien tarpeita vastaavia kokemuksia. On kuitenkin tärkeää tietää, miten koodataan, muodostetaan ja suoritetaan tehokkaasti mallipohjaisia sovelluksia, jotka latautuvat nopeasti, kun käyttäjä avaa ja siirtyy sovelluksessa päivittäisten tehtäviensä osana. Suorituskyvyn on osoitettu olevan keskeisin tekijä, joka vaikuttaa siihen, että sovellukseen ei olla tyytyväisiä. Näin tapahtuu, kun sovellusta ei optimoitua suorituskykyä ajatellen.

Älykkäät mukautukset ja tehokkaat lomakkeet ovat tärkeitä tekijäitä muodostettaessa erittäin tehokkaita ja tuottavia lomakkeita. On myös tärkeää varmistaa, että tehokkaita lomakkeita muodostettaessa noudatetaan käyttöliittymän suunnittelua ja asettelua koskevia parhaita käytäntöjä. Lisätietoja tehokkaiden ja tuottavien lomakkeiden suunnittelemisesta on kohdassa Tehokkaiden päälomakkeiden suunnitteleminen mallipohjaisissa sovelluksissa.

On myös tärkeää varmistaa, että käyttäjät käyttävät suositeltuja ja tuettuja laitteita ja että vähimmäisvaatimukset toteutuvat. Lisätietoja: Tuetut selaimet ja mobiililaitteet

Tietojen ja välilehtien käyttäminen

Tässä osassa käsitellään sitä, miten tiedot ja välilehdet näyttävät ohjausobjektit vaikuttavat lomakkeen suorituskykyyn.

Oletusvälilehden merkitys

Oletusvälilehti on lomakkeen ensimmäinen laajennettu välilehti. Se vaikuttaa merkittävästi lomakesivun latautumiseen. Oletusvälilehden ohjausobjektit on suunniteltu hahmonnettaviksi aina, kun tietue avataan. Tarkemmin sanottuna ohjausobjektin valmistelulogiikka, kuten tietojen noutaminen, käynnistyy välilehden jokaisen ohjausobjektin osalta.

Toissijainen välilehti ei sen sijaan suorita tätä ohjausobjektien valmistelua, kun lomake ladataan ensimmäisen kerran. Ohjausobjektin valmistelu tapahtuu sen sijaan silloin, kun toissijainen välilehti avataan joko käyttäjän toimenpiteellä tai setFocus-asiakasohjelmointirajapinnan kutsumenetelmällä. Tämä antaa mahdollisuuden suojata lomakkeen alkuperäistä latautumista liialliselta ohjausobjektikäsittelyltä, sillä tietyt ohjausobjektit voidaan sijoittaa toissijaiseen välilehtiin oletusvälilehden sijasta. Niinpä ohjausobjektin sijoitusstrategialla on merkittävä vaikutus siihen, kuinka herkästi lomake aluksi latautuu. Kun oletusvälilehti reagoi herkästi, kokonaiskokemus on parempi, olipa kyse sitten tärkeiden kenttien muokkaamisesta, komentopalkin käyttämisestä tai muihin välilehtiin ja osiin tutustumisesta.

Oletusvälilehden yläosaan kannattaa aina asettaa ne ohjausobjektit, joita käytetään eniten. Asettelu ja tietoarkkitehtuuri ei ole tärkeää ainoastaan suorituskyvyn kannalta, vaan niiden avulla voidaan parantaa tuottavuutta, kun käyttäjät käyttävät lomakkeen tietoja. Lisätietoja: Tehokkaiden päälomakkeiden suunnitteleminen mallipohjaisissa sovelluksissa

Tietopohjaiset ohjausobjektit

Ohjausobjektit, jotka tarvitsevat muitakin tietoja kuin ensisijaisen tietueen, vaikuttavat eniten lomakkeen responsiivisuuteen ja latausnopeuteen. Nämä ohjausobjektit noutavat tietoja verkosta ja niihin liittyy usein odotusaika (minkä tilanneilmaisimet osoittavat), koska tietojen siirtäminen voi viedä aikaa.

Tietopohjaisia ohjausobjekteja ovat esimerkiksi seuraavat:

Oletusvälilehteen kannattaa sisällyttää vain ne ohjausobjektit, joita käytetään eniten. Loput tietopohjaiset ohjausobjektit kannattaa jakaa toissijaisiin välilehtiin, sillä tällä tavoin oletusvälilehti latautuu nopeasti. Tämä asettelustrategia vähentää myös todennäköisyyttä sille, että noudettuja tietoja ei loppujen lopuksi käytetä.

Vaikka joidenkin muiden ohjausobjektien merkitys ei ole yhtä suuri tietopohjaisilla ohjausobjekteilla, niitä voi silti hyödyntää edellä mainitussa asettelustrategiassa, jonka tavoitteena on paras suorituskyky. Tällaisia ohjausobjekteja ovat esimerkiksi seuraavat:

WWW-selain

Tässä osassa käsitellään selaimien käyttöä koskevia hyviä käytäntöjä.

Älä avaa uusia ikkunoita

Asiakasohjelman ohjelmointirajapinnan openForm-menetelmä antaa parametrivaihtoehdon lomakkeen näyttämiseen uudessa ikkunassa. Älä käytä tätä parametria tai määritä sen arvoksi epätosi. Kun sen arvoksi määritetään epätosi, varmistetaan että openForm-menetelmä suorittaa oletustoiminnan eli näyttää lomakkeen nykyisessä ikkunassa. Vaikka JavaScriptin window.open-funktio on myös mahdollista kutsua suoraan mukautetusta komentosarjasta tai toisesta sovelluksesta, sitä on syytä välttää. Uuden ikkunan avaaminen tarkoittaa, että kaikki sivuresurssit on noudettava ja ladattava alusta alkaen, sillä sivu ei voi hyödyntää muistiin tallennettuja tietojen välimuistitallennusominaisuuksia aiemmin ladatun lomakkeen ja uudessa ikkunassa olevan lomakkeen kesken. Uuden ikkunan avaamisen vaihtoehtona kannattaa tarkistaa moni-istuntokokemusta, jossa tietueita voidaan avata useissa välilehdissä samalla, kun saadaan silti mahdollisimman suuri suorituskykyhyöty asiakasohjelman välimuistitallennuksesta.

Käytä moderneja selaimia

Kaikkien uusimpien selaimien käyttäminen on ratkaisevaa, kun halutaan varmistaa, että mallipohjainen sovellus suoritetaan mahdollisimman nopeasti. Tämä johtuu siitä, monia suorituskykyparannuksia voi käyttää vain uusissa moderneissa selaimissa.

Jos organisaatiossa on esimerkiksi vanhoja Firefox-versioita ja muita kuin Chromium-pohjaisia selaimia, monet mallipohjaisiin sovelluksiin sisältyvät suorituskykyhyödyt eivät ole käytettävissä vanhoissa selainversioissa, koska ne eivät tue toimintoja, joita tarvitaan sovelluksen suorittamiseen nopeasti ja sujuvasti.

Useimmissa tapauksissa on odotettavissa, että sivun latautuminen paranee pelkästään siirtymällä Microsoft Edgeen, päivittämällä nykyisen selaimen vanha versio uuteen versioon tai siirtymällä käyttämään modernia Chromium-pohjaista selainta.

JavaScript-mukauttaminen

Tässä osassa käsitellään sellaisten älykkäiden mukauttamisten tekemistä JavaScriptiä käytettäessä, jotka auttavat muodostamaan tehokkaita lomakkeita ja sivuja mallipohjaisessa sovelluksessa.

JavaScriptin käyttäminen lomakkeissa

Mahdollisuus mukauttaa lomakkeita JavaScriptin avulla antaa ammattikehittäjille joustavat mahdollisuudet hallita lomakkeen ulkoasua ja toimintaa. Tämän joustavuuden virheellinen käyttö voi vaikuttaa kielteisesti lomakkeen suorituskykyyn. Kehittäjien kannattaa käyttää seuraavia strategioita lomakkeen suorituskyvyn maksimointiin JavaScript-mukauttamisia toteutettaessa.

Asynkronisten verkkopyyntöjen käyttäminen tietojen pyytämiseen

Tietoja kannattaa pyytää asynkronisesti eikä synkronisesti, kun mukauttamisiin tarvitaan lisää tietoja. Jos kyse on tapahtumista, jotka tukevat asynkronista koodia, kuten lomakkeen OnLoad- ja OnSave-tapahtumat, tapahtumakäsittelijöiden on palautettava Promise, jotta ympäristö odottaa, kun Promise on selvitetty. Ympäristö näyttää soveltuvan käyttöliittymän, kun käyttäjä odottaa tapahtuman valmistumista.

Jos kyse on tapahtumista, jotka eivät tue asynkronisen koodin odottamista, kuten lomakkeen OnChange-tapahtumasta, vuorovaikutus lomakkeen kanssa voidaan keskeyttää muulla tavoin sen ajaksi, kun koodi tekee asynkronisen pyynnön showProgressIndicator-komentoa. Tämä on parempi vaihtoehto kuin synkronisten pyyntöjen käyttäminen, sillä käyttäjät voivat edelleen käyttää sovelluksen muita osia, kun tilanneilmaisin näytetään.

Seuraavassa esimerkissä käytetään asynkronista koodia synkronisissa laajennuspisteissä.

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

Asynkronisen koodin käyttäminen tapahtumakäsittelijässä, joka ei tue asynkronisen koodin odottamista, edellyttää varovaisuutta. Tämä koskee etenkin koodi, joka edellyttää toiminnon suorittamista tai käsittelyä asynkronisen koodin lopuksi. Asynkroninen koodi voi aiheuttaa ongelmia, jos ratkaisukäsittelijä odottaa sovelluskontekstin pysyvän samana, joka se oli asynkronisen koodin käynnistyessä. Koodin on tarkistettava jokaisen asynkronisen jatkamispisteen jälkeen, että käyttäjä on samassa kontekstissa.

Tapahtumakäsittelijässä voi esimerkiksi olla koodia, joka tekee verkkopyynnön ja muuttaa ohjausobjektin käytöstäpoistetuksi vastaustietojen perusteella. Käyttäjä on kuitenkin voinut käyttää ohjausobjektia tai siirtyä toiselle sivulle ennen pyynnön vastauksen vastaanottamista. Koska käyttäjä on eri sivulla, lomakekonteksti ei ole käytettävissä, mikä voi johtaa virheisiin tai ei-toivottuun toimintaan.

Lomakkeen OnLoad- ja OnSave-tapahtumien asynkroninen tuki

Lomakkeen OnLoad- ja OnSave-tapahtumat tukevat käsittelijöitä, jotka palauttavat lupauksia. Tapahtumat odottavat käsittelijän palauttamien lupausten ratkaisua aikakatkaisuun saakka. Tämä tuki voidaan ottaa käyttöön sovellusasetuksilla.

Lisätietoja:

Lomakkeen latauksen aikana pyydetyn tietomäärän rajoittaminen

Pyydä vain pienin tietomäärä, joka tarvitaan liiketoimintalogiikan suorittamiseen lomakkeessa. Tallenna mahdollisimman paljon pyydettyjä tietoja välimuistiin etenkin, jos kyse on tiedoista, jotka eivät muutu usein tai joita ei tarvitse päivittää. Oletetaan esimerkiksi, että lomake pyytää tietoja asetus-taulukosta. Asetustaulukon tietojen perusteella lomake saattaa valita lomakkeen osan piilottamisen. Siinä tapauksessa JavaScript voi tallentaa sessionStorage-tiedot välimuistiin, jolloin tiedot pyydetään kussakin istunnossa vain kerran (onLoad1). Lisäksi voidaan käyttää stale-while-revalidate-strategiaa, jossa JavaScript käyttää sessionStorage-tietoja samalla, kun se pyytää tietoja seuraavaan lomakkeeseen siirtymiseen (onLoad2). Myös kaksoiskappaleiden poistostrategiaa voidaan käyttää siinä tapauksessa, että käsittelijää kutsutaan useita kertoja peräkkäin (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   
    }
}

Käytä asiakasohjelmointirajapinnassa olevia tietoja pyyntöjen tekemisen sijaan. Sen sijaan että pyydettäisiin esimerkiksi käyttäjän käyttöoikeusrooleja lomaketta ladattaessa, käytössä voi olla getGlobalContext.userSettings.roles.

Koodin lataaminen vain tarvittaessa

Lataa koodia vain tietyn lomakkeen tapahtumiin tarvittava määrä. Jos koodia esimerkiksi käytetään vain lomakkeessa A ja lomakkeessa B, sen ei pitäisi sisältyä lomakkeeseen C ladattavaan kirjastoon vaan sen pitäisi olla omassa kirjastossa.

Vältä kirjastojen lataamista OnLoad-tapahtumassa, jos niitä käytetään vain OnChange- tai OnSave-tapahtumissa. Lataa ne sijaan kyseisissä tapahtumissa. Tällä tavoin ympäristö voi siirtää niiden lataamisen siihen saakka, että lomake on latautunut. Lisätietoja: Lomakkeen suorituskyvyn optimointi

Konsolin ohjelmointirajapintojen käytön poistaminen tuotantokoodista

Älä käytä konsolin ohjelmointirajapintamenetelmiä kuten console.log tuotantokoodissa. Tietojen kirjaaminen konsoliin voi lisätä merkittävästi muistin kysyntää ja estää tietojen käyttösyiden vähentämisen muistissa. Tämä voi hidastaa sovelluksen käyttöaikaa ja lopulta kaatua.

Muistivuotojen välttäminen

Koodissasi olevat muistivuodot voivat hidastaa suorituskykyä ajan mittaan ja lopulta aiheuttaa sovelluksen kaatumisen. Muistivuotoja tapahtuu, kun sovellus ei onnistu vapauttamaan tarpeetonta muistia. Kun lomake sisältää kaikki mukautukset ja koodikomponentit, sinun tulisi suorittaa seuraavat toimet:

  • Ota huomioon ja testaa perusteellisesti muistin puhdistamisesta vastaavat skenaariot, kuten objektien elinkaaren hallinnasta vastaavat luokat.
  • Puhdista kaikki tapahtumien kuuntelijat ja tilaukset, varsinkin window-objektista.
  • Puhdista kaikki ajastimet, kuten setInterval.
  • Vältä, rajoita ja puhdista globaalien tai staattisten objektien viittaukset.

Mukautettujen ohjausobjektien komponenttien puhdistaminen suorittaa destroy-menetelmällä.

Lisätietoja muistiongelmien korjaamisesta on tässä Edge-kehittäjien dokumentaatiossa.

Sovellusten suorituskykyä parantavat työkalut

Tässä osassa käsitellään työkaluja, jotka auttavat hahmottamaan suorituskykyongelmia ja tarjoavat suosituksia siitä, miten mukautuksia voi optimoida mallipohjaisissa sovelluksissa.

Suorituskyvyn merkitykselliset tiedot

Suorituskyvyn merkitykselliset tiedot itsepalvelutyökalu, jolla yritystason sovellussuunnittelijat voivat analysoida suorituksen aikaisia telemetriatietoja. Siinä on priorisoitu suositusluettelo, joka auttaa parantamaan mallipohjaisten sovellusten suorituskykyä. Tämä ominaisuus sisältää päivittäin analyysitietoja, jotka liittyvät Power Appsin mallipohjaisen tai customer engagement -sovelluksen, kuten Dynamics 365 Salesin tai Dynamics 365 Servicen, suorituskykyyn ja suosituksiin ja toimintaan liittyviin kohteisiin. Yritystason sovellussuunnittelijat voivat tarkastella yksityiskohtaisia suorituskyvyn merkityksellisiä tietoja sovellustasolla Power Appsissa. Lisätietoja: Mitä suorituskyvyn merkitykselliset tiedot ovat? (esiversio)

Ratkaisun tarkistaja

Ratkaisun tarkistus on tehokas työkalu, jolla voi analysoida asiakasohjelman ja palvelimen mukautusten suorituskyky- tai luotettavuusongelmia. Se voi jäsentää asiakaspuolen JavaScriptin, lomakkeen XML:n ja .NET-palvelinpuolen laajennukset sekä antaa tarkkoja merkityksellisiä tietoja siitä, mikä voi hidastaa loppukäyttäjiä. On suositeltavaa, että ratkaisun tarkistus suoritetaan aina, kun muutoksia julkaistaan kehitysympäristössä, sillä tavoin suorituskykyä koskevat ongelmat tulevat esiin, ennen kuin ne päätyvät loppukäyttäjille. Lisätietoja: Mallipohjaisten sovellusten tarkistaminen Power Appsissa ratkaisun tarkistustoiminnolla

Ratkaisun tarkistuksella on löydetty esimerkiksi seuraavat suorituskykyyn liittyvät ongelmat:

  • il-specify-column. Vältä kaikkien sarakkeiden valitseminen kyselyjen Dataversen API-liittymien kautta.
  • web-use-async. Käsittele HTTP- ja HTTPS-resursseja asynkronisesti.
  • web-avoid-ui-refreshribbon. Vältä refreshRibbon-käyttöä lomakkeen OnLoad- ja EnableRule-tapahtumissa.

Objektin tarkistaja

Objektin tarkistus suorittaa reaaliaikaisen vianmäärityksen ratkaisun komponenttiobjekteille. Jos ilmenee ongelmia, palautetaan suositus, joka kuvaa ongelman ratkaisemista. Lisätietoja: Ratkaisun osan diagnosointi objektin tarkistuksen avulla (esiversio)

Seuraavat vaiheet

Tuottavien päälomakkeiden suunnittelu mallipohjaisissa sovelluksissa