> Manuales > Manual de Webpack

Cómo hacer procesamiento de CSS, para ejecutar los preprocesadores necesarios para convertir nuestro código CSS, con Webpack. Usaremos Sass.

Una de las tareas típicas del desarrollo frontend actual es el procesamiento de CSS, para ejecutar los correspondientes preprocesadores y producir un código de hojas de estilo compatible con los navegadores y optimizado para una rápida descarga.

Esta tarea de procesamiento del código CSS permite pasar nuestro código escrito en Sass, Less, etc. en código CSS estándar, compatible con los navegadores. Para realizar esta acción los distintos preprocesadores tienen herramientas específicas, pero nosotros queremos usar Webpack, básicamente porque así podremos tener un mismo flujo de trabajo para todos los lenguajes o componentes del proyecto frontend.

Este paso requiere la transformación del código CSS, para lo que tenemos que usar un loader distinto de los que hemos visto hasta este momento en el Manual de Webpack. En este artículo explicaremos los pasos necesarios para configurar la herramienta y poder hacer el paso del procesamiento del código Sass en código CSS estándar.

Incluir el código CSS en nuestro entry point

Recordemos que en Webpack se trabaja con un punto de entrada, que es un archivo Javascript. Webpack analiza el código de este archivo JS para producir los correspondientes bundles de código. En el caso que nos ocupa, el procesamiento del CSS, Webpack necesita encontrar el código CSS a partir del punto de entrada. Por tanto, aunque parezca un poco raro, dentro de nuestro Javascript tendremos que hacer el import del código CSS.

/* css */
import './css/estilos.css';
Nota: La primera vez que ves ese import de un archivo CSS dentro del código Javascript te puedes sorprender un tanto, pues resulta bastante antinatural. Sin embargo, es la manera habitual de trabajar en las aplicaciones React, por lo que realmente es algo común cuando se trabaja con Webpack.

Como dentro de un archivo Javascript no podemos incluir código CSS, si ejecutas el proceso de Webpack en estos momentos apreciarás un error, producido por la sintaxis del archivo estilos.css. Es normal que esto ocurra, pues en este archivo colocaremos código CSS, que el intérprete de Javascript no acepta como válido. Pero no te preocupes, porque realmente nos faltaba un paso muy importante para dejarlo todo listo.

Extraer el código CSS del bundle Javascript

Ahora vamos a sacar todo el CSS que se ha importado dentro del Javascript, para enviarlo a un archivo de CSS común. Para esta tarea necesitamos un par de paquetes.

Plugin mini-css-extract-plugin

Para realizar esta tarea tenemos que usar un plugin llamado mini-css-extract-plugin, que realizará la extracción de todo el código CSS que tengamos dentro de Javascript. Este plugin creará el archivo .css para llevar a producción.

El primer paso será instalar el plugin:

npm install -D mini-css-extract-plugin

Loader css-loader

Recuerda además que las transformaciones del código en Webpack se realizan mediante loaders. Los Loaders permiten procesar y transformar el código fuente de tu aplicación, según se importa en el archivo Javascript mediante la sentencia import. Puedes pensar en los loaders como una especie de tareas a realizar por Webpack. En el caso del css-loader sirve para poder importar CSS como si fueran módulos Javascript.

Para disponer de este loader tenemos que instalarlo en nuestro proyecto.

npm install -D css-loader

Configurar Webpack para la extracción del CSS

Ahora veamos la configuración que tenemos que realizar de Webpack, con css-loader y mini-css-extract-plugin, para realizar las siguientes acciones:

Esta configuración se realiza en dos pasos:

  1. Instanciación del plugin mini-css-extract-plugin
  2. Definición de las reglas de transformación del código para archivos CSS

Además, para el paso de la inyección del código CSS dentro del HTML generado tienes que usar html-webpack-plugin, como se explicó en el artículo dedicado a HtmlWebpackPlugin.

Puedes ver a continuación el código de un ejemplo básico de uso de mini-css-extract-plugin y css-loader.

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({  
      filename: 'index.html',
      template: 'src/index.html',
      hash: true
    }),
    new MiniCSSExtractPlugin()
  ],
  module: {
    rules: [
      { 
        test: /\.css$/, 
        loader: [
          MiniCSSExtractPlugin.loader,
          "css-loader"
        ]
      }
    ]
  }
}

Los puntos importantes que debes fijarte en el anterior código son:

Como consecuencia de la ejecución de Webpack se generará un archivo CSS llamado "main.css", que contendrá todo el CSS importado. En este caso se usará "main.css" como nombre de archivo, ya que no hemos configurado ningún otro nombre de archivo. Pero podríamos hacer la personalización del nombre de archivo CSS resultante por medio del objeto de configuración pasado al instanciar el plugin.

new MiniCSSExtractPlugin({
  filename: "estilos.css",
})

Preprocesamiento de Sass con Webpack

Una vez que tenemos montado todo el sistema para el procesamiento del CSS, adaptarlo para trabajar también con Sass, u otro preprocesador de nuestra preferencia, será muy sencillo.

Nota: Si quieres aprender Sass te recomendamos la lectura del Manual de Sass. Es una herramienta altamente recomendable para el desarrollo frontend, que te permitirá generar código CSS más mantenible y con más productividad.

Básicamente necesitas instalar dos paquetes nuevos en tu proyecto. Por un lado node-sass que es quien tiene el código para poder preprocesar Sass desde el lenguaje NodeJS. Por otro lado sass-loader que sirve para que desde Webpack puedas hacer las transformaciones pertinentes sobre tu código CSS.

npm i -D node-sass sass-loader

Luego nos toca configurar el correspondiente loader. Algo que es muy sencillo, pues solamente lo tenemos que agregar al array de loaders que tenemos en la regla de transformación de nuestro CSS.

rules: [
  { 
    test: /\.scss$/, 
    loader: [
      MiniCSSExtractPlugin.loader,
      "css-loader",
      'sass-loader'
    ]
  }
]

Solo un detalle que no debe pasar desapercibido: fíjate que la expresión regular de "test" ha cambiado, ya que en Sass se suelen usar extensiones de archivos "scss" en lugar de "css". Es por ello que ahora debemos extraer el CSS que viene de archivos .scss. Obviamente, si sigues usando extensión .css, aunque escribas en Sasss (algunos desarrolladores lo hacen así), ese "test" tendría que tener la expresión regular del ejemplo anterior.

Eso es todo! ahora al ejecutarse Webpack se generará el Código CSS de nuestra aplicación y se meterá en un archivo .css, separado del código Javascript. Además el código Sass se preprocesará, de modo que tendremos únicamente código CSS compatible con todos los navegadores.

Solo ten en cuenta de nuevo que los loaders usados para esta regla tienen que ejecutarse en el orden correcto, definido por la posición dentro de la declaración del array. Por ejemplo, si intentas colocar el "sass-loader" antes del "css-loader" apreciarás que Webpack te responde con un error.

Resumen del entorno para CSS y preprocesamiento de Sass

Para que sirva de guía para crear tu entorno de desarrollo Webpack, capaz de procesar los CSS y hacer el preprocesamiento de Sass, vamos a hacer un relatorio de los archivos que tenemos. Comenzamos mostrando el árbol de archivos y carpetas involucrados.

Nuestro package.json, una vez instaladas las dependencias y creados los scripts para compilación de Webpack, lucirá de una manera parecida a esta:

{
  "name": "frontend-css-y-sass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode production",
    "builddev": "webpack --mode development"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^2.1.1",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.6.0",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.1.0",
    "webpack": "^4.32.1",
    "webpack-cli": "^3.3.2"
  }
}

Ahora puedes ver el archivo webpack.config.js de ejemplo. Ten en cuenta que algunas cosas relacionadas con este archivo de configuración ya se vienen explicando, o se van a explicar, en el Manual de Webpack. Especialmente el artículo dedicado al webpack.config.js y el dedicado a Inyectar bundles Javascript / CSS

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({  
      filename: 'index.html',
      template: 'src/index.html',
      hash: true
    }),
    new MiniCSSExtractPlugin({
      filename: "./css/estilos.css",
    })
  ],
  module: {
    rules: [
      { 
        test: /\.scss$/, 
        loader: [
          MiniCSSExtractPlugin.loader,
          "css-loader",
          "sass-loader"
        ]
      }
    ]
  }
}

Ahora, dentro de la carpeta "src" tenemos los archivos fuente de nuestro proyecto. Comenzamos a verlos atendiendo al archivo que se usa como punto de entrada, "src/index.js", que tendrá un código como este:

console.log('Arrancada la aplicación compilando CSS y SaSS');

/* CSS */
import './css/estilos.scss';

A continuación podemos ver el archivo de CSS, "css/estilos.scss", en el que podemos colocar perfectamente instrucciones de Sass.

Nota: Ten en cuenta que no estamos explicando aquí las cuestiones sobre el propio lenguaje Sass. Esto es materia de estudio del Manual de Sass. Lo interesante que puedes obtener en este artículo es aprender a configurar Webpack para que sirva como sistema de preprocesamiento del Sass, ya que en el mencionado manual se explica a preprocesar Sass usando el compilador oficial. La ventaja de usar Webpack es que podemos personalizar nuestro entorno de trabajo más a medida, y por supuesto procesar otras cosas como el Javascript, además de poder montar prácticamente de manera inmediata un servidor de desarrollo con live-reload, que nos puede facilitar mucho el flujo de trabajo.
body {
  background-color: aquamarine;
}

.Panel {
  background-color: #fff;
  padding: 25px;

  &-destacado {
    background-color: red;
  }
}

Por último vamos a ver el archivo de código HTML, "src/index.html", que sería el template del que tiraría Webpack para colocar como documento raíz de publicación.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Template principal para el sitio web</title>
  
</head>
<body>
  <h1>Mi sitio web</h1>
  <div class="Panel">
    Esto es un panel
  </div>
  <div class="Panel Panel-destacado">
    Esto es un panel destacado
  </div>
</body>
</html>

Del archivo anterior se tiene que destacar el hecho de no contener ninguna referencia al index.js del proyecto, ni a los archivos de estilos CSS. Las correspondientes etiquetas para enlazar el Javascript y el CSS procesado (SCRIPT para el Javascript y LINK para los CSS) las va a inyectar Webpack cuando lancemos los scripts correspondientes de compilación de proyecto, como "npm run build".

Conclusión

Hemos aprendido a incorporar CSS en nuestras aplicaciones de una nueva manera, importando directamente desde Javascript. Es algo antinatural, pero gracias a Webpack cada cosa se pondrá en su sitio al llevar los archivos a producción.

Hemos conocido los paquetes necesarios para producir las transformaciones necesarias en el código CSS, incluyendo la posibilidad de escribir código Sass y preprocesarlo para obtener el código CSS estándar, compatible con los navegadores.

Miguel Angel Alvarez

Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...

Manual