A principios de esta semana, leí un artículo que explica cómo CSS-in-JS ralentiza la representación de algunas aplicaciones React y cómo el CSS estático es más rápido. Pero CSS-in-JS es muy popular porque, entre otras características, puede diseñar dinámicamente usando variables de JavaScript.

En este tutorial, te mostraré cómo recrear este beneficio en cualquiera de tus proyectos web gracias a Webpack (y supongo que sabes cómo usarlo). Para empezar, queremos que Webpack agrupe nuestros archivos fuente en una carpeta dist/ estática.

Puedes revisar el código fuente aquí.

1. Configura nuestra aplicación

La parte aburrida

Crea una carpeta para este tutorial, abre tu terminal, e inicia un proyecto:

npm init -y

Lo primero es lo primero, si aún no está hecho, instala node.js y Webpack:

npm install webpack webpack-cli --save-dev

Vamos a crear un script en nuestro package.json que le dice a Webpack que use nuestro archivo de configuración:

  "scripts": {
    "build": "webpack --config webpack.config.js"
  }

En la root de tu carpeta, cree un archivo globals.js, donde nuestras variables serán guardadas:

module.exports = {
  myTitle: 'Hello freeCodeCamp!',
  myColor: '#42ff87',
};

El archivo de configuración de Webpack se ve así (webpack.config.js). Créelo en el root de tu carpeta:

module.exports = {
  entry: __dirname + '/app/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
};

Nuestro código fuente estará ubicado en una carpeta app. Créelo de esta forma:

mkdir app && cd app

Necesitarás index.html y index.js archivos en este punto. Crea estos archivos en la carpeta app:

touch index.html index.js

¡Perfecto! ¿Ya está todo listo?

Tu carpeta debería verse así:

|-- node_modules/
|-- package.json
|-- webpack.config.js
|-- globals.js
|-- app/
	|-- index.html
	|-- index.js

2. Renderiza nuestros archivos HTML con el html-webpack-plugin

Esta app/index.html está vacía. Vamos a añadir algo de marcado en él y luego agregue una variable personalizada:

<html lang="en">
<head>
  <title>Webpack shared variables!</title>
</head>
<body>
  <h1><%= myTitle %></h1>
</body>
</html>

Como puedes ver, estamos tratando de imprimir una variable en nuestro HTML... ¡Lo cual es imposible! Para hacer que funciones usaremos el html-webpack-plugin que nos brinda la habilidad de usar la sintaxis EJS e inyectar datos en el.

El complemento generará un archivo HTML válido. Mientras tanto, debes cambiar el nombre de tu archivo app/index.html a app/index.ejs.

npm install --save-dev html-webpack-plugin

Volvamos a nuestro archivo de configuración. html-webpack-plugin tiene una interesante opción templateParameters que nos permite pasar un objeto como parámetro. Habilita el complemento de la siguiente manera en webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const globals = require('./globals.js')

module.exports = {
	// ... previous config, entry, output...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'app/index.ejs',
      templateParameters: globals,
    })
  ]
};

Corre npm run build y ta-daaaaa « <%= myTitle %> » se convirtió « Hello freeCodeCamp » ! El trabajo está hecho por Webpack durante la compilación cuando corre el  html-webpack-plugin.

¿Ves? Esto fue bastante sencillo con la herramienta correcta: HTML ✅

3.  Usa nuestras variables en JavaScript

¡Uf, tantas líneas solo para imprimir una variable! ? Con Webpack, las cosas a menudo se complican. Bueno, esta es muy simple: en JavaScript simplemente importa tu archivo. En tu app/index.js:

import globals from '../globals.js'

document.write(
'<pre>' +
  JSON.stringify(globals, null, 2) +
'</pre>'
);

Esta imprimirá nuestros objetos globales en la página. Ahora pasemos al CSS.

4. Usa variables compartidas en nuestro CSS

¿Aquí es nuestro final jefe?

De acuerdo, chicos, me atraparon… Mentí. No podemos usar nuestros globales en CSS  – Tenemos que usar un preprocesador. En este ejemplo, usaremos SASS.

En lado de Webpack, un complemento no será suficiente. Tenemos que usar un cargador para convertir SASS en CSS. En este caso necesitamos el paquete de sass-loader, así que instálalo de acuerdo con los documentos:

npm install sass-loader node-sass css-loader style-loader --save-dev

De vuelta a la codificación. Ahora que tenemos SASS, crea tu archivo de hoja de estilo, app/style.scss:

h1 {
  color: $myColor;
}

Nuestro SASS está configurado – ahora, cómo podemos inyectarle datos? ¡El paquete sass-loader tiene una opción anteponer datos! Pero toma una cadena como parámetro, lo cual significa que tus datos deberían verse así: "$myColor: red; myTitle: '...'";.

Teneos que automatizar eso y convertir un objeto de JavaScript en una cadena. No encontré un paquete en  npm que me satisficiera, entonces escribí mi propio convertidor. Descarga el archivo y agrégalo en tu proyecto (en mi ejemplo es utils/jsToScss.js).

Tu final webpack.config.js debería verse así:

const globals = require("./globals.js");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const jsToScss = require("./utils/jsToScss.js");

module.exports = {
  entry: __dirname + "/app/index.js",
  output: {
    path: __dirname + "/dist",
    filename: "index_bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "app/index.ejs",
      templateParameters: globals
    })
  ],
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          {
            loader: "sass-loader",
            options: {
              prependData: jsToScss(globals)
            }
          }
        ]
      }
    ]
  }
};

Esto es lo que debería ver:

Capture-d-e-cran-2019-12-23-23.44.11
https://glitch.com/edit/#!/shared-variables-webpack?path=webpack.config.js

Si todavía estás leyendo este tutorial, gracias por tu atención. ¡Espero que te ayude! Webpack es una poderosa herramienta que deberías profundizar.

NB: en tu carpeta dist/ puedes ver que no se genera ningún CSS. Eso es porque uso el style-loader para mantener este demo simple. Para generar el archivo CSS, echa un vistazo a la mini-css-extract-plugin.

Traducido del artículo de: Adrien Zaganelli - How to share variables across HTML, CSS, and JavaScript using Webpack