Recientemente el equipo de Sass ha implementado un sistema de módulos con el que pretende mejorar las deficiencias que conllevan el uso de @import
. Para ello, han añadido la regla @use
que posibilita la incorporación de CSS, variables, mixins y funciones desde otras hojas de estilo haciendo uso de “nombre base”. En Octubre de 2021 se tiene previsto desaprobar la regla @import
y un año después se dejará de brindar soporte, por lo que al menos durante dos años ambas reglas podrán coexistir.
Principales problemas con @import
Aunque la regla @import
ha cumplido con su cometido durante estos años, el equipo de desarrollo de Sass tenía presente que existían algunas deficiencias que se debían corregir:
- Era casi imposible averiguar dónde se definió originalmente una variable, un mixin o una función (a los que comúnmente denominaremos “miembros”).
- Se podía producir duplicado de código.
- No era posible utilizar nombres concisos, ya que existía la posibilidad de que ese mismo nombre se utilizara en otra parte del código.
- Los autores de bibliotecas de código no tenían forma de garantizar que usuarios intermedios no tuvieran acceso a “helpers” privados.
- La regla
@extend
podía afectar a cualquier selector en cualquier lugar de la hoja de estilos.
Cómo @use lo cambiará todo
La regla @use
será la sustituta para @import
. Por defecto, las variables, mixins y funciones estarán disponibles en un espacio de nombres basado en el nombre base de la URL.
@use "bootstrap"; .element { background-color: bootstrap.$body-bg; @include bootstrap.float-left; }
- Únicamente se ejecutará una hoja de estilo incluyendo el código CSS, sin importar el número de veces que se haga uso de ella.
- Los nombres de variables únicamente estarán presentes en la hoja de estilo actual en lugar de globalmente.
- Los “miembros” cuyos nombres empiecen por
-
o_
serán privados a la hoja de estilo actual. - Si una hoja de estilo incluye la regla
@extend
, esta únicamente será aplicable a la hojas de estilo que importa, no a las hojas de estilo que la importan. Es decir, es exclusiva de la hoja de estilo dónde ha sido implementada originalmente.
Los espacios de nombre
Aunque @use utilice de forma predeterminada el espacio de nombre de la URL, también es posible establecer de forma explícita un espacio de nombre con as
.
@use "bootstrap" as b; .element { @include b.float-left; }
También es posible utilizar as *
para incluir todo en el espacio de nombres del nivel superior. Si varios módulos contienen “miembros” con el mismo nombre y se está haciendo uso de as *
, Sass emitirá un error.
@use "bootstrap" as *; .element { @include float-left; }
Configurando bibliotecas
Con la regla @import, las librerías a menudo están configuradas de tal forma que las variables globales sobrescriben variables !default
definidas por estas variables. Como ya no existirán variables globales con @use
, ahora gracias a la cláusula with
es posible realizar librerías de un modo más explícito.
// bootstrap.scss $paragraph-margin-bottom: 1rem !default; p { margin-top: 0; margin-bottom: $paragraph-margin-bottom; }
@use "bootstrap" with ( $paragraph-margin-bottom: 1.2rem );
De esta forma la variable $paragraph-margin-bottom
se le asigna el valor 1.2rem
antes de ser evaluada. La cláusula with
únicamente permite variables definidas por el módulo importado (o reenviado). De esta forma los usuarios están protegidos contra errores tipográficos.
@forward, para los autores de bibliotecas
La regla @forward
sirve para incluir otras variables de módulos, mixins y otras funciones como parte de una API del módulo actual. En definitiva, permite a los autores de bibliotecas poder dividir su biblioteca en muchos archivos con orígenes diferentes sin sacrificar la localidad dentro de esos archivos. A diferencia de @use
, @forward
no agrega ningún espacio de nombres a los nombres.
// bootstrap.scss @forward "functions"; @forward "variables"; @forward "mixins";
Controles de visibilidad
Una regla @forward
pude elegir mostrar solo nombres específicos:
@forward "functions" show color-yiq;
Pero también puede ocultar nombres destinados a ser privados de la biblioteca:
@forward "functions" hide assert-ascending;
Prefijo adicional
Si se reenvía un módulo secundario a través de un módulo todo en uno, es posible que desee agregar algunos espacios de nombres manuales a ese módulo en concreto. Con la cláusula as
se agregará un prefijo a cada nombre de miembro que se reenvía:
// material/_index.scss @forward "theme" as theme-*;
De esta forma, los usuarios pueden usar el módulo todo en uno con nombres bien definidos para las variables del tema:
@use "material" with ($theme-primary: blue);
o utilizar el módulo hijo con nombres más simples:
@use "material/theme" with ($primary: blue);
Módulos incorporados
El nuevo sistema de módulos también incluye los módulos built-in (sass:math
, sass:color
, sass:string
, sass:list
, sass:map
, sass:selector
y sass:meta
) para mantener las existentes funciones integradas de Sass. Debido a que estos módulos se importarán con un espacio de nombres, ahora es mucho más fácil usar las funciones de Sass sin tener conflictos con las funciones simples de CSS.
Por otra parte, esto hace que sea mucho más seguro el desarrollo de Sass cuando se quieran agregar nuevas funciones en el futuro.
Funciones renombradas
Algunas funciones tienen nombres diferentes en los módulos built-in con respecto a los que tenían como funciones globales. Las funciones built-in que ya disponían de espacios de nombres manuales, por ejemplo map-get()
, tienen esos espacios de nombres eliminados en los nuevos módulos built-in para que sea posible escribir map.get()
. Del mismo modo sucederá con adjust-color()
, scale-color()
y change-color()
.
También se ha aprovechado para cambiar un par de nombres de funciones antiguos que podrían dar lugar a cierta confusión. Hablamos de unitless()
que pasará a llamarse mediante math.is-unitless()
y la función comparable()
que pasará a llamarse mediante math.compatible()
.
Funciones eliminadas
Las funciones de color como lighten()
, darken()
, sauturate()
, desaturate()
, opacity()
, fade-in()
, transparentize()
y fade-out()
todas tenían un comportamiento poco intuitivo. En lugar de alcanzar sus atributos atributos asociados de manera fluida, simplemente se incrementaban a una cantidad estática. Por el momento estas funciones dejarán de estar en los nuevos módulos built-in.
Mixin meta.load-css()
El nuevo sistema de módulos viene con un nuevo mixin meta.load-css($url, $with: ())
. Este nuevo mixin carga de forma dinámica el módulo incluido en la URL y el CSS incluido en él (pero no sus funciones, variables y mixins).
Compatibilidad con la regla @import
La reglas @import
y @use
pueden coexistir ya que el cambio no se producirá de la noche a la mañana y ambas reglas serán soportadas en ambas direcciones:
- Cuando un fichero contiene reglas
@import
, será considerado como un solo módulo. Sus “miembros” serán referenciados usando su espacio de nombres correspondiente. - Cuando un fichero que contiene
@use
, todo su API pública se agrega al alcance global de la hoja de estilo de importación Esto permite que una biblioteca controle qué nombres específicos exporta, incluso para los usuarios que hacen uso de@import
en lugar de@use
.
Para permitir que las bibliotecas mantengan su @import
– API, con espacios de nombres explícitos cuando sea necesario, esta propuesta también agrega soporte para archivos que solo son viables para @import
, no para @use
. Se escribe "file.import.scss"
, e importan cuando el usuario escriba @import "file"
.
Migración automática
Para que todo sea algo más sencillo, el equipo de desarrollo de Sass, ha implementado una herramienta de migración que nos permitirá hacer uso del nuevo sistema de módulos. Puedes seguir las instrucciones desde la página oficial de Sass y después proceder a la migración con la siguiente orden:
$ sass-migrator module --migrate-deps <path/to/style.scss>
El flag --migrate-deps
migrará no sólo el archivo que pasa, sino también cualquier cosa que este archivo importe.
Instalación
El sistema de módulos se encuentra disponible como parte de Dart 1.23.0. Se puede instalar mediante la siguiente orden con NPM:
$ npm install -g sass
Puedes encontrar más información sobre los módulos en Sass en el blog oficial de Sass.