Modo perezoso
Por defecto, EffCSS genera CSS de forma inmediata: las reglas de la hoja de estilos se escriben en el CSSOM en cuanto se llama a una utilidad. En el modo diferido, la generación se pospone: el CSS se añade a la hoja de estilos solo cuando se utiliza el resolvedor generado (ya sea mediante llamada o conversión a cadena).
El modo diferido está disponible en dos variantes, para que puedas elegir el nivel de control que necesitas:
| Variante | Activador | Ámbito |
|---|---|---|
| Controlado | Utilidades lazy* opcionales | Por utilidad, siempre diferido |
| A nivel de biblioteca | configure({ lazy: true }) | Cada utilidad generadora que devuelve un resolvedor |
Funcionan de forma independiente y se pueden combinar.
1. Controlado: utilidades lazy*
Estas utilidades son siempre diferidas, independientemente de cualquier configuración global. Cada llamada devuelve un resolvedor de funciones. No se genera nada hasta que:
- llames al resolvedor —
fn()(ofn(...args)), - lo conviertas a cadena —
${fn}`oString(fn).
El contenido de la regla se puede pasar como un objeto o como una función que devuelve el objeto. Una función se evalúa de forma diferida, en el primer calentamiento.
| Utilidad | Devuelve | Genera |
|---|---|---|
lazyClassName(regla) (o className.lazy(regla)) | () => string (nombre de la clase) | una regla de clase anónima |
lazyAttribute(regla) (o attribute.lazy(regla)) | () => object ({ 'data-…': '' }) | una regla de atributo anónima |
lazyClassNames(gen) (o classNames.lazy(gen)) | resolvedor de selectores | una hoja de estilo de selector de clase |
lazyAttributes(gen) (o attributes.lazy(gen)) | resolvedor de selectores | una hoja de estilo de selector de atributo |
lazyCustomStyles(gen) (o customStyles.lazy(gen)) | resolvedor de selectores | una hoja de estilo personalizada |
Antes - hacer inmediatamente
import { className, attribute, classNames } from 'effcss';
// CSS is written into the shared stylesheet right here
const centerCls = className({ margin: 'auto' });
const markerAttr = attribute({ fontWeight: 'bold' });
const utils = classNames<Utils>((selectors) => {
const { w } = selectors;
return {
[w.s]: { width: '12px' },
[w.m]: { width: '16px' }
};
});Cada llamada genera una regla inmediatamente, incluso si el resultado nunca se utiliza en la página.
Después — controlado perezoso
import { lazyClassName, lazyAttribute, lazyClassNames } from 'effcss';
// nothing is generated at creation time
const centerCls = className.lazy({ margin: 'auto' });
const markerAttr = attribute.lazy({ fontWeight: 'bold' });
const utils = classNames.lazy<Utils>((selectors) => {
const { w } = selectors;
return {
[w.s]: { width: '12px' },
[w.m]: { width: '16px' }
};
});
// ... later, where the value is actually consumed:
<div className={centerCls()} {...markerAttr()}> // generates the anonymous rules
<div className={utils({ w: 'm' })} /> // generates the stylesheetTenga en cuenta que todos los manejadores perezosos, incluso lazyClassName (className.lazy) y lazyAttribute (attribute.lazy), devuelven funciones. Para los resolutores perezosos de reglas individuales, esto ofrece una ventaja adicional: convertir dicho resolutor a una cadena devuelve el selector correcto, que puede utilizarse en otros estilos:
const divider = className.lazy({
width: '100%',
height: '1px'
});
const layout = classNames.lazy<Layout>((selectors) => ({
[selectors.row]: {
display: 'flex'
},
// `divider` coerce to its real `.class` selector
// when `layout` will be used at the first time
[`& ${divider}`]: {
background: 'red'
}
}));Además, estas funciones pueden aceptar no solo un objeto, sino también un generador:
const divider = className.lazy(() => {
// you can create other global rules inside
// so that they are created the first time className is used
const width = variable('100%');
return {
width: width(),
height: '1px',
'&:hover': {
[width]: '50%'
}
};
});Importante:
className/attributedevuelve un valor que no es una función (string/ objeto); no son perezosos y no están involucrados aquí.
2. A nivel de biblioteca — configure({ lazy: true })
configure({ lazy: true }) cambia, sobre la marcha, toda utilidad generadora que devuelve un solucionador de funciones a su versión perezosa:
variable, variables, animation, animations, layer, layers, font, fonts, classNames, attributes, customStyles.
Sigues escribiendo la misma API; no es necesario usar nombres de carga diferida. Cada una de estas utilidades ahora pospone la generación hasta que se utiliza su resultado.
Las funciones className y attribute no se ven afectadas: devuelven valores simples (string / objeto) en lugar de resolutores, por lo que siguen generándose inmediatamente.
Antes - predeterminado (ansioso)
import { variable, animation, classNames } from 'effcss';
const shadowColor = variable('#58666d');
const spin = animation({ to: { transform: 'rotate(360deg)' } });
const utils = classNames<Utils>((selectors) => {
const { w } = selectors;
return {
[w.s]: { width: '12px' }
};
});Después — configure({ lazy: true })
import { configure, variable, animation, classNames } from 'effcss';
configure({ lazy: true });
// same API, different timing
const shadowColor = variable('#58666d');
const spin = animation({ to: { transform: 'rotate(360deg)' } });
// nothing is written yet
const utils = classNames.lazy<Utils>((selectors) => {
const { w } = selectors;
return {
[w.s]: { width: '12px' }
};
});
// nothing is written yet
// CSS is produced only on first real use:
`${shadowColor()} or ${shadowColor}`
`${spin()} or ${spin}`
utils({ w: 's' })Para utilidades múltiples (variables, animaciones, capas, fuentes, etc.), todo el lote se prepara conjuntamente: al modificar cualquier resolvedor, se genera el conjunto completo, manteniendo el orden determinista para la hidratación del renderizado del lado del servidor (SSR).
Notas sobre el comportamiento
Activadores de precalentamiento: un resolvedor se prepara al llamarlo o mediante conversión de cadena. Simplemente mantenerlo en espera (o llamar a
.get()/.set()para variables) no genera CSS.variable().get()/.set(): antes de prepararse,get()devuelve''yset()no tiene efecto; se activan solo después de que el resolvedor se haya preparado.update(): en modo diferido, no modifica las variables que aún no se han creado.Hidratación SSR: el orden de generación es determinista (contadores internos compartidos), por lo que el servidor y el cliente generan selectores idénticos siempre que calienten los resolvedores en el mismo orden.
Eventos
subscribe: losEffCSSEventse emiten en el momento de la generación real (calentamiento del resolvedor), no cuando se llama inicialmente a la utilidad.
Elegir entre las dos opciones
Utilice las utilidades `lazy controladas* cuando desee la carga diferida solo para reglas específicas y mantenga el resto en modo "eager", o cuando desee garantizar la carga diferida independientemente de la configuración general de la aplicación.
Utilice
configure({ lazy: true })cuando desee un comportamiento general de solo lo que se usa en toda la biblioteca sin modificar el código, por ejemplo, combinado convite-plugin-effcsspara enviar solo el CSS que se renderiza realmente.