Hola Habr! Les presento la traducci贸n del art铆culo
"Introducing Sass Modules" de Miriam Suzanne.
Recientemente, apareci贸 una caracter铆stica en Sass que le resulta familiar en otros idiomas: un
sistema modular . Este es un gran paso adelante para
@import
, una de las funciones m谩s utilizadas en Sass. A pesar de que la directiva
@import
existente le permite conectar paquetes de terceros y separar sus estilos en elementos compatibles, todav铆a tiene varias limitaciones
:
@import
tambi茅n existe en CSS, y cualquier diferencia en su comportamiento puede ser confusa.- Si importa
@import
varias veces para un archivo, esto puede ralentizar la compilaci贸n, provocar conflictos de redefinici贸n y obtener c贸digo duplicado en la salida. - Todo est谩 en el 谩mbito global, incluidos los paquetes de terceros: as铆 es como mi funci贸n de
color
puede anular su funci贸n de color
existente o viceversa. - Cuando utiliza una funci贸n como el
color
, es imposible saber exactamente d贸nde se define. 驴Qu茅 @import
conect贸?
Los autores de los paquetes Sass (como yo) intentaron solucionar los problemas de espacio de nombres estableciendo manualmente prefijos para variables y funciones, pero los m贸dulos Sass son una soluci贸n mucho m谩s poderosa. En resumen,
@import
se
@import
reemplazando por
@forward
m谩s expl铆citas
@use
y
@forward
. En los pr贸ximos a帽os,
@import
en Sass quedar谩 en desuso y luego se eliminar谩. A煤n puede usar
CSS Import
's , pero Sass no los compilar谩. Pero no se preocupe, hay
una herramienta de migraci贸n que lo ayudar谩 a actualizar.
Importar archivos usando @use
@use 'buttons';
El nuevo
@use
es similar a
@import
, pero tiene algunas diferencias notables:
- El archivo se importa una vez, sin importar cu谩ntas veces use
@use
en el proyecto. - Las variables, mixins y funciones (que se llaman "miembros" en Sass) que comienzan con un gui贸n bajo (
_
) o gui贸n ( -
) se consideran privadas y no se importan. - Los miembros del archivo conectado a trav茅s de
@use
(en nuestro caso buttons.scss
) son accesibles solo localmente y no se transfieren a la importaci贸n posterior. - Del mismo modo,
@extends
solo se aplicar谩 en sentido ascendente; es decir, la extensi贸n se aplica solo a los estilos que se importan, y no a los estilos que se importan. - Todos los miembros importados tienen su propio espacio de nombres de forma predeterminada.
Cuando adjuntamos el archivo a trav茅s de
@use
, Sass genera autom谩ticamente un espacio de nombres basado en el nombre del archivo.
@use 'buttons'; @use 'forms';
Ahora tenemos acceso a los miembros tanto del archivo
forms.scss
archivo
forms.scss
, pero este acceso no se transfiere entre las importaciones:
forms.scss
todav铆a no tiene acceso a las variables definidas en
buttons.scss
. Dado que las entidades importadas tienen un espacio de nombres, debemos usar la nueva sintaxis delimitada por puntos para acceder a ellas:
$btn-color: buttons.$color; $form-border: forms.$input-border; $btn-background: buttons.background(); $form-border: forms.border(); @include buttons.submit(); @include forms.input();
Podemos cambiar o eliminar el espacio de nombres predeterminado agregando
as <name>
a la importaci贸n.
@use 'buttons' as *; @use 'forms' as 'f'; $btn-color: $color; $form-border: f.$input-border;
El uso de
as *
agrega el m贸dulo al espacio de nombres ra铆z, por lo que el prefijo no es necesario, pero sus miembros a煤n est谩n limitados localmente por el documento actual.
Importar m贸dulos integrados Sass
Las capacidades internas de Sass tambi茅n se han trasladado a un sistema modular, por lo que tenemos control total sobre el espacio de nombres global. Hay varios m贸dulos integrados (
math
,
color
,
string
,
list
,
map
,
selector
y
meta
) que deben importarse expl铆citamente al archivo antes de su uso.
@use 'sass:math'; $half: math.percentage(1/2);
Los m贸dulos integrados tambi茅n se pueden importar al espacio global:
@use 'sass:math' as *; $half: percentage(1/2);
Las funciones integradas que ya tienen nombres de prefijo, como
map-get
o
str-index
, se pueden usar sin duplicar este prefijo:
@use 'sass:map'; @use 'sass:string'; $map-get: map.get(('key': 'value'), 'key'); $str-index: string.index('string', 'i');
Puede encontrar una lista completa de m贸dulos integrados, funciones y cambios de nombre en
la especificaci贸n del m贸dulo Sass .
Caracter铆sticas principales nuevas y modificadas
Como beneficio adicional, esto significa que Sass puede agregar de manera segura nuevas combinaciones y funciones internas sin causar conflictos de nombres. El ejemplo m谩s sorprendente es el
sass:meta
de
load-css
del m贸dulo
sass:meta
. Funciona de manera similar a
@use
, pero solo devuelve el CSS generado y funciona din谩micamente en cualquier parte de su c贸digo:
@use 'sass:meta'; $theme-name: 'dark'; [data-theme='#{$theme-name}'] { @include meta.load-css($theme-name); }
El primer argumento es la URL del m贸dulo (como en
@use
), pero se puede cambiar din谩micamente usando una variable, incluso usando interpolaci贸n, por ejemplo, el
theme-#{$name}
. El segundo argumento (opcional) toma una estructura de
map
con la configuraci贸n:
@include meta.load-css( 'theme/dark', $with: ('base-color': rebeccapurple) );
El argumento
$with
permite configurar cualquier variable en el m贸dulo cargado utilizando la estructura del
map
, y esta variable debe cumplir las condiciones:
- No es una variable privada que comienza con
_
o -
- Marcado con la directiva
!default
Default
$base-color: black !default; $_private: true !default; $config: false;
Tenga en cuenta que la clave
'base-color'
establece la variable
$base-color
.
Hay un par de nuevas funciones m谩s del m贸dulo
sass:meta
:
module-variables()
y
module-functions()
. Cada uno de ellos devuelve una estructura de
map
partir de nombres y valores de un m贸dulo ya importado. Toman un argumento correspondiente al espacio de nombres del m贸dulo:
@use 'forms'; $form-vars: module-variables('forms'); $form-functions: module-functions('forms');
Varias otras funciones de
sass:meta
-
global-variable-exists()
,
function-exists()
,
mixin-exists()
y
get-function()
- recibir谩n argumentos adicionales de
$module
que nos permitir谩n verificar expl铆citamente cada espacio de nombres.
Ajustar y escalar colores
El m贸dulo
sass:color
tambi茅n tiene algunas reservas interesantes sobre la resoluci贸n de algunos de nuestros viejos problemas. Muchas de las funciones heredadas como
lighten()
o
adjust-hue()
ya no se recomiendan para utilizar las funciones expl铆citas
color.adjust()
y
color.scale()
:
$light-red: color.adjust(red, $lightness: 20%); $complement: color.adjust(red, $hue: 180deg);
Algunas de estas funciones obsoletas (por ejemplo,
adjust-hue
) son redundantes e innecesarias. Otros, como
lighten
,
darken
,
saturate
, etc. - Necesita una nueva implementaci贸n para mejorar la l贸gica interna. Las funciones originales se basaron en
adjust()
, que utiliza matem谩tica lineal: agregar un
20%
a la luminosidad actual del
red
en nuestro ejemplo anterior. En la mayor铆a de los casos, queremos cambiar (
scale()
) el color en un cierto porcentaje en relaci贸n con el valor actual:
$light-red: color.scale(red, $lightness: 20%);
Despu茅s de ser completamente desaprobado y eliminado, estas funciones eventualmente reaparecer谩n en
sass:color
con un nuevo comportamiento basado en
color.scale()
, no
color.adjust()
. Esto suceder谩 gradualmente para evitar problemas repentinos de compatibilidad con versiones anteriores. Mientras tanto, recomiendo verificar manualmente su c贸digo para ver d贸nde
color.scale()
podr铆a ser m谩s 煤til.
Configurar bibliotecas importadas
Las bibliotecas de terceros o reutilizables a menudo vienen con variables con algunos valores predeterminados que puede anular. Hicimos esto con variables antes de importar:
$color: blue !default; $color: red; @import 'buttons';
Dado que cuando se usan m贸dulos ya no hay acceso a variables locales, necesitamos una nueva forma de establecer valores. Podemos hacer esto pasando la configuraci贸n a trav茅s del
map
a
@use
:
@use 'buttons' with ( $color: red, $style: 'flat', );
Esto es similar al argumento
$with
en
load-css()
, pero en lugar de usar nombres de variables como claves, usamos las variables mismas con el s铆mbolo
$
.
Me gusta cu谩n expl铆cito se ha vuelto el ajuste, pero hay una regla que me ha desconcertado varias veces: un
m贸dulo solo se puede configurar una vez al primer uso . El orden de conexi贸n siempre ha sido importante para Sass, incluso con
@import
, pero estos problemas pasaron desapercibidos. Ahora tenemos un error claro, y esto es bueno y un poco inesperado. Aseg煤rese de conectar las bibliotecas a trav茅s de
@use
y configurarlas en el punto de entrada de archivos (el documento central que importa todos los dem谩s archivos) para que estas configuraciones se
@use
antes de otras conexiones de biblioteca a trav茅s de
@use
.
No es posible (por el momento) "enlazar" las configuraciones juntas, manteni茅ndolas editables, pero puede ajustar el m贸dulo configurado y transferirlo como un nuevo m贸dulo.
Transferencia de archivos con @forward
No siempre necesitamos usar el archivo y referirnos a sus miembros. A veces solo queremos pasarlo a importaciones posteriores. Supongamos que tenemos varios archivos asociados con formularios y queremos conectarlos todos juntos como un espacio de nombres. Podemos hacer esto con
@forward
:
@forward 'input'; @forward 'textarea'; @forward 'select'; @forward 'buttons';
Los miembros de dichos archivos reenviados no est谩n disponibles en el documento actual y no se crea ning煤n espacio de nombres, pero estas variables, funciones y mixins estar谩n disponibles cuando otro archivo los conecte a trav茅s de
@use
o
@use
toda la colecci贸n a trav茅s de
@forward
. Si los archivos individuales enviados contienen CSS real, tambi茅n se transmitir谩n sin generarlos directamente hasta que se use el paquete. En esta etapa, todo esto se considerar谩 como un m贸dulo con un espacio de nombres:
@use 'forms';
Nota : Si le pide a Sass que adjunte una carpeta, buscar谩 el
index
o el archivo
_index
en ella.
Por defecto, todos los miembros p煤blicos ser谩n reenviados junto con el m贸dulo. Pero podemos ser m谩s selectivos utilizando las condiciones de
show
y
hide
y especificando miembros espec铆ficos que queremos agregar o excluir.
@forward 'input' show border, $border-color; @forward 'buttons' hide gradient;
Nota : cuando las funciones y los mixins tienen un nombre com煤n, se agregan y se ocultan tambi茅n juntos.
Para aclarar las fuentes o evitar conflictos de nombres de m贸dulos reenviados, podemos agregar prefijos a los miembros del archivo conectado usando
as
:
@forward 'input' as input-*; @forward 'buttons' as btn-*; @use 'forms'; @include forms.input-background(); @include forms.btn-background();
Y, si es necesario, siempre podemos usar a trav茅s de
@use
y
@forward
el mismo m贸dulo a trav茅s de
@forward
, agregando ambas reglas:
@forward 'forms'; @use 'forms';
Esto es especialmente 煤til si desea preconfigurar la biblioteca o agregar herramientas adicionales antes de transferirla a otros archivos. Esto puede ayudar a simplificar las rutas de conexi贸n:
@use 'accoutrement/sass/tools' with ( $font-path: '../fonts/', ); @forward 'accoutrement/sass/tools'; @use 'tools';
Tanto
@use
como
@forward
deben declararse en la ra铆z del documento (no anidado) y al comienzo del archivo. Solo pueden aparecer
@charset
y definiciones de variables simples antes de las directivas de importaci贸n.
Transici贸n a un sistema modular.
Para probar la nueva sintaxis, cre茅 una nueva biblioteca Sass de c贸digo abierto (
Cascading Color Systems ) y un
nuevo sitio para mi grupo , ambos todav铆a en desarrollo. Necesitaba comprender los m贸dulos desde el punto de vista del autor de la biblioteca y desde el punto de vista del desarrollador del sitio. Comencemos con la experiencia del "usuario final" al escribir estilos de sitio utilizando la sintaxis del m贸dulo ...
Soporte y estilos de escritura
Usar los m贸dulos en el sitio fue divertido. La nueva sintaxis admite la arquitectura de c贸digo que ya uso. Todas mis importaciones de configuraciones y herramientas globales est谩n en el mismo directorio (lo llamo
config
) con un archivo de 铆ndice que transfiere todo lo que necesito:
@forward 'tools'; @forward 'fonts'; @forward 'scale'; @forward 'colors';
Al desarrollar otras partes del sitio, puedo importar estas herramientas y configuraciones donde las necesite:
@use '../config'; .page-title { @include config.font-family('header'); }
Incluso funciona junto con mis bibliotecas existentes, como
Accoutrement y
Herman , que todav铆a usan la antigua sintaxis
@import
. Dado que la regla
@import
no se reemplazar谩 en todas partes a la vez, los desarrolladores de Sass han dado algo de tiempo para la transici贸n. Los m贸dulos est谩n disponibles ahora, pero
@import
no
@import
o dos a帽os m谩s y se eliminar谩n del idioma solo un a帽o despu茅s. Al mismo tiempo, los dos sistemas funcionar谩n juntos de cualquier manera:
- Si ejecutamos
@import
para un archivo que contiene la nueva sintaxis @use/@forward
, solo se importar谩n los miembros p煤blicos sin un espacio de nombres. - Si ejecutamos
@use
o @forward
para un archivo que contiene la antigua sintaxis @import
, obtendremos acceso a todas las importaciones anidadas como un solo espacio de nombres.
Esto significa que puede comenzar a usar de inmediato la nueva sintaxis del m贸dulo, sin esperar el lanzamiento de una nueva versi贸n de sus bibliotecas favoritas: 隆y puedo pasar un tiempo actualizando todas mis bibliotecas!
Herramienta de migraci贸n
La actualizaci贸n no tardar谩 mucho si utilizamos la herramienta de migraci贸n creada por Jennifer Thakar. Se puede instalar usando NPM, Chocolatey o Homebrew:
npm install -g sass-migrator choco install sass-migrator brew install sass/sass/migrator
Esta no es una herramienta 煤nica para migrar a m贸dulos. Ahora que Sass ha vuelto al desarrollo activo (ver m谩s abajo), la herramienta de migraci贸n tambi茅n recibir谩 actualizaciones peri贸dicas para ayudar a portar cada nueva caracter铆stica. Es una buena idea instalar esta herramienta a nivel mundial y guardarla para su uso futuro.
El migrador se puede iniciar desde la l铆nea de comandos y, con suerte, se agregar谩 a aplicaciones de terceros como CodeKit y Scout. Apunte a un 煤nico archivo Sass, por ejemplo
style.scss
y d铆gale qu茅 migraciones aplicar. Por el momento, solo hay una migraci贸n llamada
module
:
De manera predeterminada, el migrador solo actualiza un archivo, pero en la mayor铆a de los casos queremos actualizar el archivo principal y todas sus dependencias: cualquier elemento conectado a trav茅s de
@import
,
@forward
o
@use
. Podemos hacer esto especificando cada archivo individualmente o simplemente agregando la bandera
--migrate-deps
.
sass-migrator --migrate-deps module style.scss
Para una ejecuci贸n de prueba, podemos agregar
--dry-run --verbose
(o en forma abreviada
-nv
) y ver los resultados sin cambiar los archivos de origen. Hay una serie de otras opciones que podemos usar para configurar la migraci贸n, incluso hay una dise帽ada espec铆ficamente para ayudar a los autores de bibliotecas a eliminar espacios de nombres antiguos creados manualmente, pero no los describir茅 aqu铆.
La herramienta de migraci贸n est谩 completamente documentada en
el sitio web de Sass .
Actualizaci贸n de bibliotecas publicadas
Encontr茅 varios problemas en el lado de la biblioteca, en particular, cuando intent茅 hacer que las configuraciones de usuario estuvieran disponibles para varios archivos y encontrar una soluci贸n para las configuraciones de "cadena" que faltan. Los errores relacionados con los pedidos pueden ser dif铆ciles de depurar, pero los resultados merecen la pena y creo que pronto veremos algunas soluciones adicionales. Todav铆a necesito experimentar con la herramienta de migraci贸n en paquetes complejos, y tal vez escribir un art铆culo adicional para autores de bibliotecas.
Lo importante que debe saber en este momento es que Sass nos proporcion贸 protecci贸n durante la transici贸n. Las antiguas importaciones y los m贸dulos no solo pueden funcionar juntos, sino que tambi茅n podemos crear archivos "
solo de importaci贸n " para proporcionar un trabajo m谩s conveniente a los usuarios que a煤n conectan nuestras bibliotecas a trav茅s de
@import
. En la mayor铆a de los casos, esta ser谩 una versi贸n alternativa del archivo del paquete principal, y desea que est茅n cerca de:
<name>.scss
para usuarios del m贸dulo y
<name>.import.scss
para usuarios antiguos. Cada vez que el usuario llama a
@import <name>
, carga la
.import
archivo:
@use 'forms'; @import 'forms';
Esto es especialmente 煤til para agregar prefijos para desarrolladores que no usan m贸dulos:
@forward 'forms' as forms-*;
Sass Update
Puede recordar que Sass congel贸 la incorporaci贸n de nuevas funciones hace varios a帽os, por lo que sus diversas implementaciones (LibSass, Node Sass, Dart Sass) se ponen al d铆a con la implementaci贸n original de Ruby, de modo que al final se
abandona por completo . La congelaci贸n termin贸 el a帽o pasado con varias caracter铆sticas nuevas y
debates activos y desarrollo en GitHub, pero no tan solemnemente. Si se perdi贸 estos lanzamientos, puede leer el
blog de Sass :
Actualmente, Dart Sass es una implementaci贸n can贸nica y generalmente es la primera en introducir nuevas caracter铆sticas. Recomiendo cambiar a 茅l si desea recibir lo 煤ltimo. Puede
instalar Dart Sass usando NPM, Chocolatey o Homebrew. Tambi茅n funciona muy bien con
gulp-sass .
Al igual que CSS (comenzando con CSS3), ya no hay un solo n煤mero de versi贸n para las nuevas versiones. Todas las implementaciones de Sass funcionan con la misma especificaci贸n, pero cada una de ellas tiene un cronograma de lanzamiento y numeraci贸n 煤nicos, que se refleja en la informaci贸n de soporte en
una hermosa y nueva documentaci贸n dise帽ada por
Jina .

Los m贸dulos Sass est谩n disponibles a partir
del 1 de octubre de 2019 en
Dart Sass 1.23.0 .