Stylify CSS: primeros paquetes CSS de utilidades automatizados que se dividen en capas CSS en Astro.build
Stylify CSS: primeros paquetes CSS de utilidad automatizados que se dividen en capas CSS en Astro.build
Utility-First CSS de primera utilidad pueden ser muy pequeños. Pero, ¿y si pudiéramos hacerlos aún más pequeños? ¿Dividirlos para cada página/diseño, por ejemplo? Es posible que algunas páginas no tengan estilos de otra página. Aprende a dividir paquetes de CSS en Astro. construir automáticamente usando Stylify CSS.
Video Guide
La introducción de Stylify CSS
Stylify es una biblioteca que utiliza selectores similares a CSS para generar un CSS de primera utilidad optimizado en función de lo que escribe.
- ✅ Selectores tipo CSS
- ✅ Sin marco para estudiar
- ✅ Menos tiempo dedicado a los documentos
- ✅ CSS destrozado y extremadamente pequeño
- ✅ No se necesita purga de CSS
- ✅ Componentes, Variables, Selectores personalizados
- ✅ Puede generar múltiples paquetes CSS
También tenemos una página sobre ¡qué problemas resuelve Stylify CSS y por qué debería probarlo!
Motivación
Cada paquete puede contener solo el CSS necesario. Esto significa casi cero CSS no utilizado y, en producción, se puede modificar y minimizar, por lo que el CSS es aún más pequeño (más información a continuación).
El código
Bien, primero el código, luego la explicación. Aunque el código puede parecer complicado, en realidad es bastante simple:
import stylify from '@stylify/astro';
import { hooks } from '@stylify/bundler';
import fastGlob from 'fast-glob';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
const pagesDir = 'src/pages';
const layoutsDir = 'src/layouts';
const stylesDir = 'src/styles';
/** @type { import('@stylify/bundler').BundlerConfigInterface[]} */
const stylifyBundles = [];
const layoutCssLayerName = 'layout';
const pageCssLayerName = 'page';
const getFileCssLayerName = (filePath) =>
filePath.includes('/pages/') ? pageCssLayerName : layoutCssLayerName;
const getOutputFileName = (file) => {
const parsedFile = path.parse(file);
const fileName = parsedFile.name.toLowerCase();
const dirNameCleanupRegExp = new RegExp(`${pagesDir}|${layoutsDir}|\\W`, 'g');
const dir = parsedFile.dir.replace(dirNameCleanupRegExp, '');
return `${dir.length ? `${dir}-` : ''}${fileName}.css`;
};
const createBundle = (file) => {
const fileName = path.parse(file).name;
const fileCssLayerName = getFileCssLayerName(file);
return {
outputFile: `${stylesDir}/${fileCssLayerName}/${getOutputFileName(file)}`,
files: [file],
cssLayer: fileCssLayerName,
};
};
const createBundles = (files) => {
for (const file of files) {
stylifyBundles.push(createBundle(file));
}
};
// 1. Asignar archivos en diseños/páginas y crear paquetes
createBundles(fastGlob.sync(`${pagesDir}/**/*.astro`));
createBundles(fastGlob.sync(`${layoutsDir}/**/*.astro`));
// 2. Inic Stylify Astro Integraton
const stylifyIntegration = stylify({
bundler: {
id: 'astro',
// Set CSS @layers order
cssLayersOrder: {
// Order will be @layer layout,page;
order: [layoutCssLayerName, pageCssLayerName].join(','),
// Layers order will be exported into file with layout @layer
exportLayer: [layoutCssLayerName],
},
},
bundles: stylifyBundles,
});
// 3. Agregue un enlace que procese los archivos abiertos
/** @param { import('@stylify/bundler').BundleFileDataInterface } data */
hooks.addListener('bundler:fileToProcessOpened', (data) => {
let { content, filePath } = data;
// 3.1 Solo para archivos de diseño y página
if (filePath.includes('/pages/') || filePath.includes('/layouts/')) {
const cssFileName = path.parse(filePath).name;
const cssFilePathImport = `import '/${stylesDir}/${getFileCssLayerName(
filePath
)}/${getOutputFileName(filePath)}';`;
if (!content.includes(cssFilePathImport)) {
if (/import \S+ from (?:'|")\S+(\/layouts\/\S+)(?:'|");/.test(content)) {
content = content.replace(
/import \S+ from (?:'|")\S+\/layouts\/\S+(?:'|");/,
`$&\n${cssFilePathImport}`
);
} else if (/^\s*---\n/.test(content)) {
content = content.replace(/^(\s*)---\n/, `$&${cssFilePathImport}\n`);
} else {
content = `---\n${cssFilePathImport}\n---\n${content}`;
}
fs.writeFileSync(filePath, content);
}
}
// 3.2 Para todos los archivos
const regExp = new RegExp(
`import \\S+ from (?:'|")\\S+(\\/components\\/\\S+)(?:'|");`,
'g'
);
let importedComponent;
const importedComponentFiles = [];
const rootDir = path.dirname(fileURLToPath(import.meta.url));
while ((importedComponent = regExp.exec(content))) {
importedComponentFiles.push(
path.join(rootDir, 'src', importedComponent[1])
);
}
data.contentOptions.files = importedComponentFiles;
});
// 4. Espere a que el paquete se inicialice y observe los directorios
// para crear nuevos paquetes cuando se agrega un archivo
hooks.addListener('bundler:initialized', ({ bundler }) => {
// Ver diseños y directorios de páginas
// Si planea usar directorios anidados como blog/_slug.astro
// para el que desea automatizar la configuración de paquetes
// Deberá agregar la ruta a ellos aquí
const dirsToWatchForNewBundles = [layoutsDir, pagesDir];
for (const dir of dirsToWatchForNewBundles) {
fs.watch(dir, (eventType, fileName) => {
const fileFullPath = path.join(dir, fileName);
if (eventType !== 'rename' || !fs.existsSync(fileFullPath)) {
return;
}
bundler.bundle([createBundle(fileFullPath)]);
});
}
});
export default {
// 5. Agregue Stylify Astro Integration
integrations: [stylifyIntegration]
};
Cómo funciona
El código anterior se divide en 5 pasos:
- Encuentra todas las páginas en
src/pages
y todos los diseños ensrc/layouts
y llama acreateBundles
para crear la configuración de paquetes para nosotros con el nombre de capa y el archivo de salida correctos. - Se inicializa la integración de Stylify y se configura el orden de las capas CSS, por lo que generará el orden solo en un archivo, que tiene el nombre de capa CSS
layout
. - Se agrega el gancho bundler:fileToProcessOpened. Este gancho tiene dos partes. Una parte está hecha, cuando este archivo es un diseño o página y la otra para cada archivo abierto.
- Cuando se abre un diseño o un archivo de página, comprueba si contiene una ruta al archivo CSS y, si no, la agrega al encabezado del archivo.
- Para todos los demás archivos, intenta verificar las
importaciones
. Si se encuentra alguna importación de componentes, la asigna como una dependencia. De esta manera, puede mapear un árbol de dependencia de componentes completo automáticamente, de modo que solo los agregue/elimine y el CSS se genere correctamente.
- Cuando se inicializa Bundler, podemos comenzar a buscar archivos recién agregados dentro del directorio
layout
ypages
. Cada vez que se agrega un nuevo archivo, creamos un nuevo paquete. - La integración Stylify se agrega a la configuración de Astro.
Cuando ejecutamos el comando dev, Stylify hará lo siguiente:
- Diseño de mapa/archivos de página
- Genere CSS en los archivos correctos, envuelva el contenido en la capa CSS correcta y agregue enlaces a estos archivos en las plantillas de Astro.
- Si se crea un nuevo archivo en diseño/páginas, se agrega automáticamente un nuevo paquete
¿Y cómo se ve la salida para la producción? Diseño (src/layouts/Layout.astro):
@layer layout,page;
@layer layout {.b{font-size:16px}}
Página (src/pages/index.astro):
@layer page {.a{color:darkblue}}
Ejemplo de integración
Consulte el [ejemplo en Stack Blitz] interactivo (https://stackblitz.com/edit/stylify-astro-automated-bundles-example?file=src%2Fpages%2Findex.astro).
Configuración
Los ejemplos anteriores no incluyen todo lo que Stylify puede hacer:
- Definir componentes
- Agregar selectores personalizados
- Configure sus macros como
ml:20px
para margin-left - Definir pantallas personalizadas
- Puede mapear archivos anidados en la plantilla
- Y mucho más
No dudes en consultar los documentos para obtener más información 💎.