Esta es la historia de un proyecto mío. Uno grande. Una mezcla entre PHP y Node.js. Es una aplicación de una sola página desde un punto de vista y un sitio web optimizado para SEO desde otro. Se escribieron toneladas de JavaScript, CSS y HTML. En una sola palabra, una pesadilla de espagueti para cualquier desarrollador. Hubo caídas y alzas. Produciendo y resolviendo bugs. Luchar contra las últimas tecnologías y terminar con una biblioteca maravillosamente simple, que es el tema de este artículo..
Como suele ocurrir, el proyecto no fue considerado tan grande. Llegó el resumen, discutimos cómo se manejaría el desarrollo, qué tecnologías se usarían y cómo las usaremos. Hicimos un plan y nos pusimos a trabajar. Al principio teníamos algunas páginas, que estaban controladas por un CMS. Al principio no había mucho código JavaScript porque nuestro sistema entregaba la mayor parte del contenido.
Aquí hay una estructura aproximada del proyecto:
Ponemos nuestro código del lado del cliente en diferentes directorios. El código del lado del servidor era solo PHP en este momento, por lo que entró a php
directorio. Envolvemos todo en alrededor de 30 archivos y todo estuvo bien..
Durante el período de unos pocos meses, probamos diferentes conceptos y cambiamos el código del proyecto varias veces. Desde el punto de vista actual, pude detectar cuatro grandes problemas que conocimos.
Parece que el cliente estaba contento con el resultado y decidió invertir más en su apariencia de Internet. Nos pidieron que construyéramos algunas características nuevas. Algunos de ellos eran solo lugares de contenido nuevos, otros eran adiciones a páginas ya existentes. Comenzamos a agregar más y más archivos en todas las carpetas anteriores. Comenzó a complicarse un poco, así que decidimos crear subdirectorios para las diferentes páginas y guardar el código necesario allí..
Por ejemplo, los estilos CSS para el acerca de la página estaba en css / about / styles.css
. El JavaScript en js / about / scripts.js
y así. Utilizamos un script PHP que concatena los archivos. Había, por supuesto, partes del sitio que estaban en varias páginas y las pusimos en común
directorios Esto fue bueno por un tiempo, pero no funcionó bien por mucho tiempo porque cuando los directorios se llenaron, fue lento para modificar algo. Debes buscar tres directorios diferentes para encontrar lo que necesitas. El sitio fue escrito principalmente en PHP..
En ese momento, las aplicaciones móviles se hicieron populares. El cliente quería tener su sitio disponible para dispositivos móviles y este es el gran punto de inflexión en el proyecto. Tuvimos que convertir el sitio en una aplicación de una sola página. Y no solo eso, tenía que tener toneladas de características en tiempo real. Por supuesto, no todo el contenido del sitio tuvo que ser cargado dinámicamente. El SEO seguía siendo una parte importante de la visión del cliente. Elegimos la pila MEAN para las próximas partes. El problema era con las páginas antiguas. Su contenido tenía que ser servido por PHP, pero la lógica de las páginas cambió y se hizo completamente con JavaScript. Durante varias semanas, nos sentimos como los pasajeros del Titanic. Teníamos prisa por lanzar algo, pero había un agujero tras otro y, muy pronto, nuestro barco estaba lleno de agua (bichos).
Usamos GruntJS por un tiempo, pero migramos a Gulp. Ayudó mucho porque aumentamos nuestra velocidad de desarrollo. Sin embargo, todavía era demasiado molesto agregar o editar componentes existentes. La arquitectura sólida que teníamos al principio se transformó en una mezcla compleja de archivos. Sí, hubo convenciones estrictas para nombrar y colocar estos archivos, pero aún así era demasiado complicado. Luego nos golpeamos la cabeza y creamos el siguiente formato:
Dividimos el sitio en diferentes componentes, que eran como cajas negras. Viven en su propia carpeta. Todo lo relacionado con el componente fue guardado dentro de su directorio. Diseñamos cuidadosamente, las API de las clases. Eran comprobables y comunicativos. Descubrimos que una estructura como esta funcionaba mejor para nosotros porque teníamos toneladas de módulos independientes. Sí, estamos mezclando los archivos JavaScript con estilos CSS y plantillas HTML, pero fue más fácil trabajar sobre una base de unidad, en lugar de profundizar en varios directorios.
Aquellas páginas que eran antiguas y que teníamos que entregar a través de PHP, también estaban llenas de lógica de JavaScript. Sin embargo, en algunos casos, Angular no funcionó muy bien. Tuvimos que hacer pequeños trucos para que las cosas funcionaran bien. Terminamos con una mezcla entre controladores angulares y código personalizado. La buena noticia fue que el presupuesto del proyecto se amplió y decidimos utilizar nuestro propio marco. En ese momento, estaba desarrollando mi propio preprocesador de CSS. El proyecto va muy, muy rápido. Muy pronto porté mi biblioteca para uso del lado del cliente. Línea por línea, se transformó en un pequeño marco, que comenzamos a integrar en el proyecto..
Esto es probablemente lo que estás preguntando. Bueno, hay una docena de otros que ofrecen una amplia gama de capacidades. Sí, es cierto, pero ... no necesitábamos una amplia gama de capacidades. Necesitábamos cosas específicas y nada más. Estábamos listos para aceptar el hecho de que al usar un marco popular, podemos agregar algunos kilobytes a la carga general de la página. Eso no fue un gran problema.
El estado de nuestro código base era el problema. Nos centramos en crear una buena arquitectura y todos estamos de acuerdo en que a veces la solución personalizada se adapta mejor. El uso de Angular, Ember, Knockout o Backbone viene con sus beneficios, pero la verdad es que no existe un marco universal.
Me gustan las palabras de Jeremy Keith, en su charla El poder de la simplicidad, dijo que lo más importante al elegir su herramienta es la filosofía de la persona que hizo la herramienta y si esa filosofía se alinea con la suya. Si las ideas del marco no se alinean con las tuyas, muy pronto, irás en contra de ellas. Lo mismo nos pasó a nosotros. Intentamos usar Angular y hubo demasiadas dificultades. Problemas que pudimos resolver, pero utilizamos hacks y soluciones complejas.
También probamos Ember, pero no funcionó, porque se basa en gran medida en sus mecanismos de enrutamiento. Backbone fue una buena elección y fue lo más parecido a nuestra visión. Sin embargo, cuando introduje AbsurdJS decidimos usarlo.
AbsurdJS se inició originalmente como un preprocesador de CSS, se expandió a un preprocesador de HTML y se portó con éxito para el uso del lado del cliente. Entonces, al principio lo usamos para compilar JavaScript a HTML o CSS. Sí, has oído bien; Empezamos a escribir nuestros estilos y marcas en JavaScript (probablemente suena extraño, pero por favor, sigue leyendo). Empujé la biblioteca hacia adelante y se agregaron una docena de funcionalidades..
Cuando tiene un sistema complejo, con muchas páginas, realmente no quiere resolver grandes problemas. Es mucho mejor dividir todo en tareas más pequeñas y resolverlas una por una. Hicimos lo mismo. Decidimos que nuestra aplicación se compondrá de componentes más pequeños, como los siguientes:
var absurd = absurdo (); var MyComp = absurd.component ('MyComp', constructor: function () //…); var instance = MyComp ();
absurd.component
define una clase. Llamando a la MyComp ()
método crea una nueva instancia.
Teniendo todos estos pequeños componentes, necesitábamos un canal para la comunicación. El patrón observador fue perfecto para este caso. Entonces, cada componente es un despachador de eventos..
var MyComp = absurd.component ('MyComp', doSomething: function () this.dispatch ('algo-sucede');); var instance = MyComp (); instance.on ('algo sucede', function () console.log ('Hello!');); instance.doSomething ();
También podemos pasar datos junto con el mensaje. La definición de los componentes y su naturaleza de "escucha-despacho" es bastante trivial. Adopté este concepto de los otros marcos populares, porque parece natural. También fue mucho más fácil para mis colegas comenzar a usar AbsurdJS.
Junto con el marcado de PHP servido, creamos elementos DOM dinámicamente. Esto significa que necesitábamos acceso a los elementos DOM existentes o nuevos, que luego se agregarán a la página. Por ejemplo, digamos que tenemos el siguiente HTML:
Título de la página
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aquí hay un componente que recupera el encabezado:
absurd.component ('MyComp', html: '.content h1', constructor: function () this.populate (); console.log (this.el.innerHTML); // Título de la página) ();
los poblar
el metodo es el unico mágico Método en toda la biblioteca. Hace varias cosas como compilar CSS o HTML, vincula eventos y cosas así. En el ejemplo anterior, se ve que hay una html
propiedad e inicializa el el
variable que apunta al elemento DOM. Esto funciona bastante bien para nosotros porque una vez que obtuvimos esa referencia, pudimos trabajar con los elementos y sus hijos. Para aquellos componentes que necesitaban elementos creados dinámicamente, el html
la propiedad acepta un objeto.
absurd.component ('MyComp', html: 'div.content': h1: 'Título de la página', p: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', constructor: function () this .populate (); document.querySelector ('body'). appendChild (this.el);) ();
El JSON anterior se traduce al mismo formato HTML. Elegí JSON porque, desde el punto de vista de JavaScript, es mucho más flexible. Podemos fusionar objetos, reemplazar o eliminar solo partes de ellos. En la mayoría de los marcos populares, las plantillas son solo texto sin formato que las hace difíciles de manipular. AbsurdJS también tiene su propio motor de plantillas..
absurd.component ('MyComp', html: 'div.content': h1: '<% this.title %>', ul: ['<% for(var i=0; i', li: '<% this.availableFor[i] %>''<% %>'], título:' That \ 's awesome', availableFor: ['all browser', 'Node.js'], constructor: function () this.populate (); document.querySelector ('body'). appendChild (this.el); ) ();
El resultado es:
Eso es genial
- todos los navegadores
- Node.js
los esta
palabra clave en las expresiones anteriores, apunta al componente en sí. El código entre <%
y %>
Es válido JavaScript. Por lo tanto, las características como las propiedades computadas podrían desarrollarse fácilmente directamente en la definición de la plantilla. Por supuesto, podemos usar el mismo motor de plantillas con marcas ya existentes. Por ejemplo:
<% this.title %>
<% for(var i=0; i<this.availableFor.length; i++) %>
- <% this.availableFor[i] %>
<% %>
... podría controlarse con el siguiente componente (el resultado es el mismo):
absurd.component ('MyComp', html: '.content', título: 'That \' s awesome ', availableFor: [' all browsers ',' Node.js '], constructor: function () this.populate ();) ();
De todos modos, el punto es que pudimos definir plantillas o crearlas desde cero. También podemos controlar los datos que se inyectan de una manera fácil y natural. Todo es sólo propiedades del buen objeto JavaScript antiguo..
Hemos dividido con éxito todo el sistema en pequeños módulos. Las partes que estaban antes de los controladores angulares, se convirtieron en componentes de AbsurdJS. Nos dimos cuenta de que su HTML estaba estrechamente vinculado a su definición, que cambió por completo la gestión del marcado en la aplicación. Dejamos de pensar en la concatenación, las convenciones o algo así. No tuvimos que crear archivos HTML en absoluto. Cuando miro hacia atrás, pude ver este momento exacto en nuestro historial de compromisos. Es fácilmente visible porque muchos archivos se eliminaron de la base de código.
Entonces pensé, ¿qué pasará si hacemos lo mismo con el CSS? Por supuesto, era posible porque AbsurdJS era un preprocesador de CSS y podía producir CSS. Acabamos de obtener la cadena compilada, creamos una nueva estilo
etiqueta en el cabeza
De la página actual e inyectarla allí..
absurd.component ('MyComp', css: '.content': h1: color: '# 99FF00', relleno: 0, margen: 0, p: fontSize: '20px', html : '.content', constructor: function () this.populate ();) ();
Aquí está el estilo
etiqueta que se produce:
Y día a día, transferimos los estilos CSS de los archivos SASS (porque, en algún momento, elegimos SASS como preprocesador CSS) a los componentes de AbsurdJS. Para ser honesto, fue bastante fácil porque todas las combinaciones y variables que tenemos se definieron como funciones y variables de JavaScript. El intercambio de estilos fue aún más fácil porque todo era JavasSript..
... cuando todo funciona perfectamente pero sientes que algo está mal
Estábamos mirando el código. Funcionó. AbsurdJS condujo incluso las partes viejas. Lo nuevo usa la misma biblioteca. El HTML y el CSS estaban bien separados y colocados directamente en la definición de los componentes. Sin embargo, sentí que había algo mal. Me detuve un rato y me pregunté: "¿De qué está hecha la Web?".
Y lo que hicimos, es un poco diferente. Se parece más a la imagen de abajo..
He estado construyendo sitios web durante más de diez años y recuerdo los momentos en que todos luchamos por la gran separación de estos tres materiales de construcción. Y lo que hice en este proyecto es exactamente lo contrario. No había archivos CSS y HTML (casi) en absoluto. Todo fue JavaScript.
Mucha gente dirá que esto es ridículo y deberíamos devolverle el dinero al cliente. Sí, esto podría ser cierto, pero este concepto funcionó perfectamente en nuestro caso. No escribimos una aplicación. De hecho, escribimos un montón de componentes independientes. Creo que la web será una combinación de componentes listos para usar.
Nosotros, como desarrolladores, tendremos que desarrollar dichos componentes y, probablemente, conectarnos y utilizar dichos componentes escritos por otros. Proyectos como AbsurdJS o Polymer están demostrando que esto es posible y los invito a experimentar en esta dirección.
Así que al final el negocio del cliente salió bien. Fue tan bueno que decidió lanzar un nuevo servicio. Y adivina qué. Quería que algunas partes de la aplicación existente fueran transferidas al nuevo proyecto. No puedo decirles lo felices que estábamos de mover componentes de un lugar a otro. No tuvimos que configurar algo, copiar código HTML o archivos CSS. Acabamos de obtener el archivo JavaScript del componente, lo colocamos en algún lugar y creamos una instancia del mismo. Simplemente funcionó porque no había dependencias. No me sorprendería si algunos de estos componentes se pusieran a la venta muy pronto. Son bastante ligeros y proporcionan una buena funcionalidad relacionada con el producto del cliente..
Sí, rompimos algunas reglas. Reglas con las que personalmente estoy de acuerdo. Reglas que seguí durante muchos años. Sin embargo, la realidad es que todos queremos calidad y, a veces, esa calidad es alcanzable rompiendo las reglas. Queremos producir un código bueno y bien estructurado que sea fácil de mantener, flexible y ampliable. No queremos mirar hacia atrás y decir: "Oh, Dios mío ... ¡¿fue eso lo que escribí?". Cuando miro hacia atrás ahora, sé por qué el código se ve como lo hace. Se ve así porque fue escrito específicamente para ese proyecto..
Si encontraste este tutorial interesante, echa un vistazo a la página oficial de AbsurdJS. Hay guías, documentación y artículos. Incluso puedes probar la biblioteca en línea. Como cualquier otra herramienta, AbsurdJS está diseñado para un uso específico. Se ajusta bien a nuestro proyecto y puede ajustarse a los tuyos. Ni siquiera lo llamo un marco, porque no me gusta esta definición. Es más como una caja de herramientas en lugar de un marco de pila completo. Siéntase libre de experimentar con él, realizar solicitudes de extracción o enviar problemas. Es completamente de código abierto y está disponible en GitHub..