El artículo se centrará en el ensamblaje de proyectos BEM usando el paquete Webpack. Mostraré un ejemplo de una configuración sin cargar lectores con entidades innecesarias.
El material es adecuado para aquellos que recién comienzan a familiarizarse con BEM. Primero, tocaremos los aspectos teóricos de la metodología, y en la sección “Práctica” mostraré cómo se pueden aplicar.
Poco de teoría
Si es la primera vez que escucha sobre BEM y desea conocerlo usted mismo, conserve la documentación .
BEM es una metodología que se utiliza para organizar proyectos de cualquier escala. Yandex lo desarrolló y al principio lo usó solo en el trabajo de sus servicios, pero luego se publicó en el dominio público.
BEM significa "Bloque, Elemento, Modificador".
Block es una entidad con una arquitectura autónoma que se puede reutilizar. Un bloque puede contener sus propios elementos.
Un elemento es una parte integral de un bloque. Un artículo solo se puede usar dentro del bloque principal.
Un modificador es una entidad que cambia la visualización, el estado o el comportamiento de un bloque.
Estos componentes subyacen a la metodología. Proporcionan belleza y conveniente separación de códigos. Más detalles sobre su dispositivo están escritos en la documentación .
La documentación de BEM está ampliamente escrita. Sin embargo, hay un "pero": un umbral alto para ingresar al material. Si los aspectos básicos del diseño se pueden resolver leyendo una página de la documentación, entonces el tema del montaje del proyecto es más complicado.
¿Por qué se trataba de armar el proyecto? Cuando se trabaja en un proyecto a gran escala, todos se enfrentan al problema de organizar el código. No es conveniente almacenar todo el código de un proyecto grande en un archivo. Dividir el código en múltiples archivos, luego compilarlo manualmente tampoco es una buena salida. Para resolver este problema, se utilizan recopiladores o paquetes que automatizan la conversión del código fuente del proyecto en un código que está listo para ser enviado a producción.
Permíteme recordarte: se supone además que los lectores tienen habilidades básicas de Webpack. Si no ha trabajado con él antes, le recomiendo que primero se familiarice con esta herramienta.
La documentación de BEM proporciona recomendaciones para el ensamblaje de proyectos. Solo se ofrecen dos opciones como ejemplos: ensamblaje utilizando ENB y Gulp.
ENB es una utilidad diseñada específicamente para construir proyectos BEM. Ella puede trabajar con entidades BEM fuera de la caja. Pero mira el código. A primera vista, puede desmotivar a un desarrollador no preparado:
El código de configuración ENB obviamente será complicado para aquellos que recién comienzan a usar BEM.
La documentación contiene configuraciones preparadas para el recopilador , y se pueden utilizar sin profundizar en los detalles del ensamblaje. Pero, ¿qué pasa si usted, como yo, desea tener una imagen completa de lo que sucede con el proyecto durante la construcción?
La documentación de BEM explica bien el proceso de ensamblaje en teoría, sin embargo, hay pocos ejemplos prácticos y no siempre son adecuados para una comprensión clara del proceso. Para resolver este problema, intentaré construir un proyecto BEM elemental usando Webpack.
Practica
Antes de eso, mencioné que la organización de ensamblaje y separación de código simplificó el trabajo con el proyecto. En el siguiente ejemplo, proporcionaremos la separación de código usando BEM y su ensamblaje usando Webpack.
Queremos obtener la configuración más simple, la lógica de ensamblaje debe ser lineal e intuitiva. Armemos una página con un bloque BEM, que tendrá dos tecnologías: CSS y JS.
Puede escribir código HTML con un DIV con la clase "bloque" y conectar manualmente todas sus tecnologías. Al usar el nombre de clase BEM y la estructura de archivos correspondiente, no violamos los principios de la metodología.
Obtuve el siguiente árbol de proyectos:
├── desktop
La primera línea se refiere al nivel de anulación de "escritorio". En la terminología BEM, los niveles de redefinición son directorios que contienen sus propias implementaciones de bloque. Al ensamblar un proyecto, las implementaciones de todos los niveles de redefinición en un cierto orden caen en el paquete final.
Por ejemplo, tenemos un nivel de redefinición de "escritorio" en el que se almacenan las implementaciones de bloque para dispositivos de escritorio. Si necesitamos complementar el proyecto con un diseño para dispositivos móviles, será suficiente para nosotros crear un nuevo nivel de redefinición de "móvil" y llenarlo con nuevas implementaciones de los mismos bloques. La conveniencia de este enfoque es que en un nuevo nivel de redefinición, no necesitaremos duplicar el código que ya existe en el "escritorio", ya que se conectará automáticamente.
Aquí está la configuración de Webpack:
Aquí especificamos el archivo /pages/index.js
como un punto de entrada, agregamos cargadores para estilos CSS y copiamos /pages/index.html
a /dist/index.html
.
index.html <html> <body> <div class="block">Hello, World!</div> <script src="index.js"></script> </body> </html>
block.css .block { color: red; font-size: 24px; text-align: center; }
block.js document.getElementsByClassName('block')[0].innerHTML += " [This text is added by block.js!]"
El ejemplo usa un nivel de anulación y un bloque. La tarea es ensamblar la página para que las tecnologías (css, js) de nuestro bloque estén conectadas a ella.
Para conectar tecnologías, usamos require()
:
Inicie Webpack y vea qué sucede. Abra index.html
desde la carpeta ./dist
:
Captura de pantalla de la página Se cargaron los estilos de bloque, javascript funcionó correctamente. Ahora podemos agregar con acierto las preciadas letras "BEM" a nuestro proyecto.
En primer lugar, BEM fue creado para trabajar con grandes proyectos. Imaginemos que nuestro diseñador lo intentó y en la página ahora no hay un bloque, sino cien. Siguiendo el escenario anterior, conectaremos manualmente las tecnologías de cada bloque usando require()
. Es decir, al menos cien líneas adicionales de código aparecerán en index.js.
Las líneas de código adicionales que podrían haberse evitado son malas. El código no utilizado es aún peor. ¿Qué pasa si en nuestra página solo habrá 10 de los bloques disponibles, o 20, o 53? El desarrollador tendrá trabajo adicional: tendrá que centrarse exactamente en qué bloques se usan en la página, así como conectarlos y desconectarlos manualmente para evitar código innecesario en el paquete final.
Afortunadamente, este trabajo puede confiarse a Webpack.
El algoritmo óptimo de acciones para automatizar este proceso:
- Seleccione las clases correspondientes a los nombres BEM del código HTML existente;
- Según las clases, obtenga la lista de entidades BEM utilizadas en la página;
- Compruebe si hay directorios de bloques, elementos y modificadores usados en los niveles de redefinición;
- Conecte la tecnología de estas entidades al proyecto agregando las expresiones
require()
apropiadas.
Para empezar, decidí comprobar si hay algún gestor de arranque listo para esta tarea. No encontré un módulo que proporcionara toda la funcionalidad necesaria en una botella. Pero me encontré con bemdecl-to-fs-loader , que convierte las declaraciones BEM para require()
expresiones require()
. Se basa en niveles y tecnologías de redefinición disponibles en la estructura de archivos del proyecto.
Declaración BEM : una lista de entidades BEM utilizadas en la página. Lea más sobre ellos en la documentación .
Falta un enlace: convertir HTML a una matriz de entidades BEM. Esta tarea se resuelve con el módulo html2bemjson .
bemjson : datos que reflejan la estructura de la página futura. Por lo general, los usa el motor de plantillas bem-xjst para formar páginas. La sintaxis de bemjson es similar a la sintaxis de las declaraciones, pero la declaración contiene solo una lista de entidades utilizadas, mientras que bemjson también refleja su orden.
bemjson no es una declaración, por lo que primero lo convertimos a formato decl para la transmisión a bemdecl-to-fs-loader. Para esta tarea, use el módulo del SDK: bemjson-to-decl . Como se trata de módulos NodeJS normales, no de cargadores Webpack, debe crear un cargador envoltorio. Después de eso, podemos usarlos para convertir a Webpack.
Obtenemos el siguiente código del gestor de arranque:
let html2bemjson = require("html2bemjson"); let bemjson2decl = require("bemjson-to-decl"); module.exports = function( content ){ if (content == null && content == "") callback("html2bemdecl requires a valid HTML."); let callback = this.async(); let bemjson = html2bemjson.convert( content ); let decl = bemjson2decl.convert( bemjson ); console.log(decl);
Para simplificar la instalación del gestor de arranque y ahorrar tiempo en el futuro, descargué el módulo en NPM .
Instalemos el gestor de arranque en nuestro proyecto y realicemos cambios en la configuración de Webpack:
const webpack = require('webpack'); const path = require('path'); const opy = require('copy-webpack-plugin'); module.exports = { entry: path.resolve(__dirname, "pages", "index.js"), output: { filename: 'index.js', path: path.join(__dirname, 'dist') }, module: { rules: [ { test: /\.html$/, use: [ {
El parámetro de levels
bemdecl-to-fs-loader
arranque bemdecl-to-fs-loader
especifica qué niveles de anulación se deben usar y en qué orden. Las extensions
dan las extensiones de tecnología de archivo que se utilizan en nuestro proyecto.
Como resultado, en lugar de conectar tecnologías manualmente, solo incluimos un archivo HTML. Todas las conversiones necesarias se realizarán automáticamente.
Reemplacemos el contenido de index.js con la línea:
require('./index.html');
Ahora ejecuta Webpack. Al ensamblar, se muestra la línea:
[ BemEntityName { block: 'block' } ]
Esto significa que la formación de la declaración fue exitosa. Nos fijamos directamente en la salida de Webpack:
Entrypoint main = index.js [0] ./pages/index.js 24 bytes {0} [built] [1] ./pages/index.html 74 bytes {0} [built] [2] ./desktop/block/block.css 1.07 KiB {0} [built] [3] ./node_modules/css-loader/dist/cjs.js!./desktop/block/block.css 217 bytes {0} [built] [7] ./desktop/block/block.js 93 bytes {0} [built] + 3 hidden modules
Captura de pantalla de la página Obtuvimos un resultado idéntico al anterior, con la diferencia de que todas las tecnologías de bloques se conectaron automáticamente. Por ahora, es suficiente para nosotros agregar una clase con nombre BEM al HTML, conectar este HTML con require()
y crear el directorio apropiado con las tecnologías para conectarse.
Por lo tanto, tenemos una estructura de archivos que corresponde a la metodología BEM, así como un mecanismo para conectar automáticamente tecnologías de bloques.
Resumiendo de los mecanismos y entidades de la metodología, hemos creado una configuración Webpack extremadamente simple pero efectiva. Espero que este ejemplo ayude a todos los que comienzan a conocer BEM a comprender mejor los principios básicos de la construcción de proyectos BEM.
Enlaces utiles