Diseñar formularios para rendimiento en aplicaciones basadas en modelos
Crear experiencias en las que las tareas se puedan completar de forma rápida y eficiente es fundamental para la satisfacción del usuario. Las aplicaciones basadas en modelos pueden personalizarse en gran medida para crear experiencias que satisfagan las necesidades de sus usuarios, pero es importante saber cómo codificar, crear y ejecutar de forma eficaz aplicaciones basadas en modelos que se cargan rápidamente cuando un usuario abre y navega en su aplicación mientras trabaja en tareas diarias. Se ha demostrado que el rendimiento es un factor clave de la insatisfacción con una aplicación cuando no está optimizada para el rendimiento.
Las personalizaciones inteligentes y las formas con rendimiento son aspectos importantes para construir formularios muy eficientes y productivas. También es importante asegurarse de que se están creando formularios muy con las prácticas recomendadas de diseño de interfaces de usuario. Para obtener información sobre el diseño de formularios para mejorar la eficiencia y la productividad, consulte Diseñar formularios principales productivos en aplicaciones basadas en modelos.
También es importante asegurarse de que los usuarios estén en dispositivos recomendados y compatibles, y con las especificaciones mínimas requeridas. Más información: Exploradores web y dispositivos móviles admitidos
Trabajo con datos y pestañas
Esta sección cubre cómo los controles que muestran datos y pestañas impactan en el rendimiento del formulario.
Importancia de la pestaña predeterminada
La pestaña predeterminada es la primera pestaña expandida en un formulario. Desempeña un papel especial en la carga de una página de formulario. Por diseño, los controles de la pestaña predeterminada siempre se representan al abrir un registro. Específicamente, la lógica de inicialización del control, como la recuperación de datos, se invoca para cada control en la pestaña.
Por el contrario, una pestaña secundaria no realiza esta inicialización en sus controles cuando el formulario se carga inicialmente. En cambio, la inicialización del control se produce en el momento en que se abre la pestaña secundaria, ya sea mediante la interacción del usuario o llamando al método de API de cliente setFocus
. Esto brinda la oportunidad de proteger la carga del formulario inicial del procesamiento de control excesivo, al colocar ciertos controles en pestañas secundarias en lugar de la pestaña predeterminada. Por lo tanto, la estrategia de ubicación del control puede tener un efecto significativo en la capacidad de respuesta de la carga inicial del formulario. Una pestaña predeterminada más interactiva proporciona una mejor experiencia general para modificar campos importantes, interactuar con la barra de comandos y explorar otras pestañas y secciones.
Coloque siempre los controles que más se utilizan en la parte superior de la pestaña predeterminada. La arquitectura de diseño e información no solo es importante para el rendimiento, sino también para mejorar la productividad cuando los usuarios interactúan con los datos del formulario. Más información: Diseñar formularios principales productivos en aplicaciones basadas en modelos
Controles basados en datos
Los controles que requieren datos adicionales más allá del registro primario producen la mayor tensión en la capacidad de respuesta y la velocidad de carga del formulario. Estos controles obtienen datos a través de la red y, a menudo, implican un período de espera (aparecen indicadores de progreso) porque puede llevar tiempo transmitir los datos.
Algunos de los controles basados en datos incluyen:
- Formulario de vista rápida
- Subcuadrícula
- Escala de tiempo
- Asistente (requiere Dynamics 365 Sales Insights)
Mantenga solo los controles de uso más frecuente en la pestaña predeterminada. Los controles basados en datos restantes deben distribuirse en pestañas secundarias para permitir que la pestaña predeterminada se cargue rápidamente. Además, esta estrategia de diseño reduce la posibilidad de obtener datos que no se utilizan.
Hay otros controles que tienen menos impacto que los controles basados en datos, pero que siguen pudiendo participar en la estrategia de diseño anterior para lograr el mejor rendimiento. Estos controles incluyen:
Explorador web
Esta sección cubre las prácticas recomendadas para usar con navegadores web.
No abrir nuevas ventanas
El método API del cliente openForm
permite que una opción de parámetro muestre un formulario en una nueva ventana. No use este parámetro ni lo establezca en false. Establecerlo en false asegurará que el método openForm
realice el comportamiento predeterminado de mostrar el formulario utilizando la ventana existente. También es posible llamar directamente a la función window.open
de JavaScript desde un script personalizado u otra aplicación; sin embargo, esto también debe evitarse. Abrir una nueva ventana significa que todos los recursos de la página deben recuperarse y cargarse desde cero, ya que la página no puede aprovechar las capacidades de almacenamiento en caché de datos en memoria entre un formulario previamente cargado y el formulario en una nueva ventana. Como alternativa a la apertura de nuevas ventanas, considere usar la experiencia de múltiples sesiones que permite que los registros se abran en múltiples pestañas mientras maximiza los beneficios de rendimiento del almacenamiento en caché del cliente.
Utilizar navegadores modernos
El uso del navegador web más actualizado es clave para garantizar que su aplicación basada en modelo se ejecute lo más rápido posible. La razón de esto es que muchas de las mejoras de rendimiento solo se pueden utilizar en los navegadores modernos más nuevos.
Por ejemplo, si su organización tiene versiones anteriores de Firefox, navegadores no basados en Chromium, etc., muchas de las mejoras de rendimiento que están integradas en una aplicación basada en modelos no estarán disponibles en las versiones anteriores del navegador porque no son compatibles con las funciones de las que depende la aplicación para ejecutarse rápidamente y sin problemas.
En la mayoría de los casos, puede esperar ver mejoras en la carga de la página simplemente cambiando a Microsoft Edge, actualizando a la última versión actual del navegador desde una versión anterior, o pasando a un navegador moderno basado en Chromium.
Personalización de JavaScript
Esta sección cubre cómo realizar personalizaciones inteligentes cuando usa JavaScript, que le ayudan a crear formularios y páginas eficaces en una aplicación basada en modelos.
Uso de JavaScript con formularios
La capacidad de personalizar los formularios con JavaScript proporciona a los desarrolladores profesionales una gran flexibilidad sobre cómo se ve y se comporta un formulario. El uso inadecuado de esta flexibilidad puede afectar negativamente al rendimiento del formulario. Los desarrolladores deben utilizar las siguientes estrategias para maximizar el rendimiento del formulario al implementar personalizaciones de JavaScript.
Utilizar solicitudes de red asincrónicas al solicitar datos
Solicite datos de forma asincrónica en lugar de sincrónica cuando se necesiten datos adicionales para las personalizaciones. Para eventos que admiten la espera de código asincrónico como los eventos de formulario OnLoad
y formulario OnSave
, los controladores de eventos deben devolver un Promise
para que la plataforma espere hasta que Promise
esté establecido. La plataforma mostrará una interfaz de usuario adecuada mientras el usuario espera a que se complete el evento.
Para eventos que no admiten la espera de código asincrónico, como el evento del formulario OnChange
, puede usar una solución alternativa para detener la interacción con un formulario mientras el código realiza una solicitud asincrónica mediante showProgressIndicator
. Esto es mejor que usar solicitudes sincrónicas porque los usuarios aún podrán interactuar con otras partes de la aplicación a medida que se muestra un indicador de progreso.
Aquí hay un ejemplo que usa código asincrónico en puntos de extensión sincrónicos.
//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);
Debe tener cuidado al usar código asincrónico en un controlador de eventos que no admite la espera de código asincrónico. Esto es particularmente cierto para el código que necesita que se tome o maneje una acción en la resolución del código asincrónico. El código asincrónico puede causar problemas si el controlador de resolución espera que el contexto de la aplicación permanezca igual que cuando se inició el código asincrónico. Su código debe comprobar que el usuario esté en el mismo contexto después de cada punto de continuación asincrónico.
Por ejemplo, puede haber código en un controlador de eventos para realizar una solicitud de red y cambiar un control para que se deshabilite en función de los datos de respuesta. Antes de que se reciba la respuesta de la solicitud, el usuario puede haber interactuado con el control o haber navegado a una página diferente. Debido a que el usuario está en una página diferente, es posible que el contexto del formulario no esté disponible, lo que podría generar errores o podría haber otro comportamiento no deseado.
Soporte asincrónico en el formulario OnLoad y el formulario OnSave
Los eventos OnLoad
y OnSave
del formulario admiten controladores que devuelven promesas. Los eventos esperarán a que se resuelvan las promesas devueltas por un controlador, hasta un período de tiempo de espera. Este soporte se puede habilitar a través de la configuración de la aplicación.
Más información:
Limitar la cantidad de datos solicitados durante la carga del formulario
Solicite solo la cantidad mínima de datos que sea necesaria para realizar la lógica empresarial en un formulario. Almacene en caché los datos que se solicitan tanto como sea posible, especialmente para los datos que no cambian con frecuencia o que no necesitan estar actualizados. Por ejemplo, suponga que hay un formulario que solicita datos de una tabla de configuración. Según los datos de la tabla de configuración, el formulario puede optar por ocultar una sección del formulario. En este caso, JavaScript puede almacenar datos en caché en sessionStorage
, para que los datos solo se soliciten una vez por sesión (onLoad1
). También se puede usar una estrategia obsoleta mientras se revalida cuando JavaScript usa los datos de sessionStorage
al solicitar datos para la próxima navegación al formulario (onLoad2
). Finalmente, se podría usar una estrategia de desduplicación en caso de que se llame a un controlador varias veces seguidas en una fila (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
}
}
Utilice la información disponible en la API del cliente en lugar de realizar solicitudes. Por ejemplo, en lugar de solicitar los roles de seguridad de un usuario al cargar el formulario, puede usar getGlobalContext.userSettings.roles.
Cargar el código solo cuando sea necesario
Cargue tanto código como sea necesario para los eventos de un formulario en particular. Si tiene un código que es solo para el formulario A y el formulario B, no debe incluirse en una biblioteca cargada para el formulario C. Debería estar en su propia biblioteca.
Evite cargar bibliotecas en el evento OnLoad
si solo se utilizan para los eventos OnChange
u OnSave
. En su lugar, cárguelos en esos eventos. De esta forma, la plataforma puede aplazar la carga hasta después de que se cargue el formulario. Más información: Optimizar el rendimiento del formulario
Eliminar el uso de API de consola en el código de producción
No use los métodos de API de consola como console.log
en código de producción. El registro de datos en la consola puede aumentar significativamente la demanda de memoria y puede evitar que los datos se limpien en la memoria. Esto puede hacer que la aplicación se vuelva más lenta con el tiempo y eventualmente se bloquee.
Evitar fugas de memoria
Las fugas de memoria en su código pueden conducir a un rendimiento más lento con el tiempo y, finalmente, hacer que su aplicación se bloquee. Las fugas de memoria ocurren cuando la aplicación no puede liberar memoria cuando ya no se necesita. Con todas las personalizaciones y componentes de código en su formulario, debe:
- Considerar minuciosamente y probar los escenarios para cualquier cosa responsable de limpiar la memoria, como las clases responsables de administrar el ciclo de vida de los objetos.
- Limpie todos los oyentes de eventos y suscripciones, especialmente si están en el objeto
window
. - Limpie todos los temporizadores como
setInterval
. - Evite, limite y limpie las referencias de limpieza a objetos globales o estáticos.
Para los componentes de control personalizados, la limpieza se puede realizar en el método destroy.
Para obtener más información sobre cómo solucionar problemas de memoria, vaya a esta documentación para desarrolladores de Edge.
Herramientas que se pueden utilizar para ayudar a que las aplicaciones rindan
Esta sección describe las herramientas que pueden ayudarle a comprender los problemas de rendimiento y ofrecer recomendaciones sobre cómo optimizar sus personalizaciones en aplicaciones basadas en modelos.
Información sobre el rendimiento
Informaciones de rendimiento es una herramienta de autoservicio para los creadores de aplicaciones empresariales que analiza los datos de telemetría en tiempo de ejecución y proporciona una lista priorizada de recomendaciones para ayudar a mejorar el rendimiento de las aplicaciones basadas en modelos. Esta característica proporciona un conjunto diario de información analítica relacionada con el rendimiento de una aplicación de participación del cliente o basada en modelos de Power Apps, como Dynamics 365 Sales o Dynamics 365 Service, con recomendaciones y elementos accionables. Los creadores de aplicaciones empresariales pueden ver información detallada sobre el rendimiento a nivel de la aplicación en Power Apps. Más información: ¿Qué son las estadísticas de rendimiento? (versión preliminar)
Comprobador de soluciones
El comprobador de soluciones es una herramienta poderosa que puede analizar las personalizaciones del cliente y del servidor en busca de problemas de rendimiento o confiabilidad. Puede analizar JavaScript del lado del cliente, formularios XML y complementos del lado del servidor .NET y brindar información específica sobre lo que puede ralentizar a los usuarios finales. Recomendamos que ejecute el comprobador de soluciones cada vez que publique cambios en un entorno de desarrollo, de modo que cualquier problema de rendimiento surja antes de llegar a los usuarios finales. Más información: Use el comprobador de soluciones para validar sus aplicaciones basadas en modelos en Power Apps
Algunos ejemplos de problemas relacionados con el rendimiento encontrados con el comprobador de soluciones:
- il-specify-column. Evite seleccionar todas las columnas mediante API de consulta de Dataverse.
- web-use-async. Interactúe con recursos HTTP y HTTPS forma asincrónica.
- web-avoid-ui-refreshribbon. Evite el uso de
refreshRibbon
en los formulariosOnLoad
yEnableRule
.
Comprobador de objetos
El verificador de objetos ejecuta diagnósticos en tiempo real sobre los objetos componentes dentro de su solución. Si se detectan problemas, se devuelve una recomendación que describe cómo solucionar el problema. Más información: Usar el comprobador de objetos para diagnosticar un componente de la solución (versión preliminar)
Pasos siguientes
Diseño productivo de formularios principales en aplicaciones basadas en modelos