Activos Web - Consejos para una mejor organización y rendimiento

¿Recuerda cuando tuvimos que dedicar mucho tiempo a optimizar los activos de nuestro proyecto (imágenes, CSS, etc.)? Bueno, hoy en día, los usuarios tienen una conexión a Internet mucho más rápida y parece que podemos permitirnos usar imágenes más grandes o archivos flash más grandes con una gran cantidad de videos e imágenes dentro. Sin embargo, con el aumento del desarrollo móvil, volvemos a estar en la misma situación. Es extremadamente importante crear sitios bien optimizados, para que tengamos aplicaciones más rápidas, que descarguen menos contenido y respondan de inmediato..


Imágenes

Servir el tamaño adecuado

Muchas veces usamos las mismas imágenes para diferentes partes de nuestros sitios web. Por ejemplo, en una tienda en línea, todos los productos tienen una imagen general. Digamos que tenemos tres páginas donde tenemos que mostrar esas imágenes: una página para enumerar los productos, otra página para los detalles del producto y una tercera página que muestra solo la imagen en su tamaño original.

Entonces, necesitamos tres tamaños de imagen diferentes y si usamos el mismo archivo para los tres lugares diferentes, entonces el navegador descargará la imagen de tamaño completo incluso para la página de listado, donde en realidad solo necesitamos una imagen de 200x200. Si el archivo original es de alrededor de 1 MB y tenemos diez productos por página, el usuario descargaría 10 MB. Esa no es una muy buena idea. Si puede, intente generar diferentes imágenes para las diferentes partes de su sitio, esto ahorrará muchos KB para sus usuarios. Es una buena idea tener en cuenta la resolución de pantalla actual. Por ejemplo, si alguien abre su sitio en su iPhone, no es necesario que sirva la imagen de encabezado gigante, que normalmente utiliza. Al utilizar consultas de medios CSS, puede enviar una imagen con un tamaño más pequeño:

Pantalla solo @media y (min-device-width: 320px) y (max-device-width: 480px) .header background-image: url (… /images/background_400x200.jpg); 

Compresión

Enviar una imagen con las dimensiones adecuadas no siempre es suficiente. Algunos formatos de archivo se pueden comprimir mucho sin perder su calidad. Hay muchos programas que pueden ayudarte. Por ejemplo, Photoshop proporciona una buena característica llamada Guardar para web y dispositivos:


Hay muchas opciones en este diálogo, pero una de las más importantes es Calidad. Si se configura en un 80%, el tamaño del archivo puede disminuir considerablemente.

Por supuesto, puede usar el código para comprimir los archivos, pero personalmente prefiero Photoshop y lo uso siempre que sea posible. Aquí hay un ejemplo simple escrito en PHP:

la función compressImage ($ source, $ destination, $ quality) $ info = getimagesize ($ source); switch ($ info ['mime']) case "image / jpeg": $ image = imagecreatefromjpeg ($ source); imagejpeg ($ image, $ destination, $ quality); descanso; caso "image / gif": $ image = imagecreatefromgif ($ source); imagegif ($ imagen, $ destino, $ calidad); descanso; caso "image / png": $ image = imagecreatefrompng ($ source); imagepng ($ image, $ destination, $ quality); descanso;  compressImage ('source.png', 'destination.png', 85);

Sprites

Una de las cosas que puede hacer para aumentar el rendimiento de su aplicación es reducir el número de solicitudes al servidor. Por lo tanto, cada nueva imagen significa una nueva solicitud. Es una buena idea combinar tus imágenes en una sola. La imagen resultante se llama duende y con el cambio de la posición de fondo En el estilo CSS, solo puede mostrar la parte de la imagen que necesita. Por ejemplo, Twitter Bootstrap usa sprites para sus íconos internos:


Luego, en el CSS, puedes hacer algo como esto, para mostrar la parte del sprite que desees:

.icon-edit background-image: url ("... /img/glyphicons-halflings-white.png"); posición de fondo: -96px -72px; 

Almacenamiento en caché

El mecanismo de almacenamiento en caché del navegador es tu amigo. Sí, a veces durante el desarrollo puede llevar a algunos gracioso situaciones, pero realmente ayuda a mejorar el rendimiento de su sitio. Cada navegador almacena en caché contenido como imágenes, JavaScript o CSS. Hay varias formas de controlar el almacenamiento en caché y le sugiero que revise este gran artículo para una revisión detallada. En general, puede controlar el proceso estableciendo encabezados, de esta manera:

$ expire = 60 * 60 * 24 * 1; // segundos, minutos, horas, días header ('Cache-Control: maxage = ". $ expire); header (" Expires:' .gmdate ('D, d MYH: i: s ', time () + $ expire).' GMT '); encabezado ('Last-Modified:' .gmdate ('D, d M Y H: i: s'). 'GMT');

Prefetching

HTML5 avanza cada día más. Hay una bonita característica llamada búsqueda previa que le dice al navegador que necesitará algún recurso en un futuro próximo y que debe descargarlo ahora, con anticipación. Por ejemplo:

Esquema URI de datos / Imágenes en línea

Hace un par de años tuve que desarrollar una página web simple, que se suponía que era solo un archivo HTML. Por supuesto había varias imágenes, que tenía que incluir. Los esquemas de URI de datos me ayudaron a resolver el problema. La idea es convertir tus imágenes en una cadena codificada en base64 y colocarlas en el src atributo de la img etiqueta. Por ejemplo:

punto rojo

Al utilizar este enfoque, su imagen está realmente en el HTML y guarda una solicitud HTTP. Por supuesto, si tienes una imagen grande, la cadena será muy larga. Aquí hay un simple script PHP que convierte imágenes a cadenas base64:

$ picture = fread ($ fp, tamaño de archivo ($ archivo)); fclose ($ fp); // base64 codifica los datos binarios, luego los divide // en partes de acuerdo con la semántica RFC 2045 $ base64 = base64_encode ($ picture); $ tag = ''; $ css = 'url (datos: imagen / jpg; base64,'. str_replace ("\ n", "", $ base64). '); ';

Puede que esto le resulte útil en algunos casos, pero tenga en cuenta que no funciona muy bien en IE.


CSS

Me gusta pensar que escribir CSS es como escribir código. Todavía tienes que organizar tus estilos, definir diferentes bloques y la relación entre ellos. Por eso creo que la gestión de CSS es realmente importante. Cada parte de la aplicación debe tener sus propios estilos y estar bien separados. Mantener todo en diferentes archivos proporciona una buena organización, pero también tiene sus propios problemas..

Todos sabemos que el uso de la @importar declaración no es una muy buena idea Eso es porque cada nueva @importar Significa una nueva solicitud al servidor. Y si tienes, por ejemplo, 20 diferentes. .css Archivos significa que el navegador hará 20 peticiones. Y el navegador no muestra / muestra la página antes de descargar todos los estilos. Si alguno de tus .css Faltan archivos o son muy grandes, obtendrá un gran retraso antes de ver algo en la pantalla..

Utilizar procesadores de CSS

Los preprocesadores CSS resuelven todos los problemas anteriores. Todavía divide sus estilos en diferentes archivos, pero al final, el preprocesador compila todo en un solo archivo. .css expediente. En realidad, ofrecen un montón de características geniales como variables, bloques anidados, mixins y herencia. El código todavía parece CSS, pero está bien formateado / estructurado. Hay algunos preprocesadores populares que vale la pena comprobar: Sass, LESS y Stylus. Aquí hay un ejemplo simple escrito en MENOS:

.position (@top: 0, @left: 0) position: absolute; arriba: @top; izquierda izquierda; alineación de texto: izquierda; tamaño de fuente: 24px;  .header .position (20px, 30px); .tips .position (10px, -20px);  .logo .position (10px, 20px); 

Producirá

.cabecera posición: absoluta; superior: 20px; izquierda: 30px; alineación de texto: izquierda; tamaño de fuente: 24px;  .header .tips posición: absoluta; superior: 10px; izquierda: -20px; alineación de texto: izquierda; tamaño de fuente: 24px;  .header .logo posición: absoluta; superior: 10px; izquierda: 20px; alineación de texto: izquierda; tamaño de fuente: 24px; 

O, por ejemplo, si tiene un estilo para un botón y desea producir el mismo botón pero con otro color para el texto, podría hacer esto:

.botón borde: sólido 1px # 000; relleno: 10px; fondo: # 9f0; color: # 0029FF;  .active-button .button (); color: #FFF; 

CSS eficiente

Normalmente, la mayoría de los desarrolladores no piensan en CSS eficiente. La eficiencia del CSS se refleja en la representación de la página y, si sus estilos son ineficientes, los navegadores procesarán su aplicación lentamente. Un hecho interesante es que los navegadores analizan los selectores de CSS de derecha a izquierda. Lo que significa que el siguiente código:

body ul li a color: # F000; texto-decoración: ninguno; 

... no es eficiente en absoluto. Eso es porque el motor obtendrá todos los y tendrá que evaluar cada uno de los elementos principales para finalmente recopilar el estilo necesario. También debe saber que, en términos de eficiencia, los selectores se clasifican en el siguiente orden: ID, clase, etiqueta y universal. Esto significa que un elemento con una carné de identidad el conjunto se procesará más rápido que un elemento con solo un selector de etiquetas. Por supuesto, no tiene sentido agregar identificadores a todos los elementos en el árbol DOM, pero definitivamente debe verificar su código y mejorarlo cuando sea posible. Por ejemplo, si tienes algo como esto:

ul #navigation li background: # ff0232; 

Debes quitar el ul parte, porque solo tienes uno #navegación Elemento en la página. O en el siguiente selector:

body .content p font-size: 20px; 

Está claro que la .contenido elemento es un hijo de la cuerpo etiqueta. Todos los elementos son en realidad hijos de este elemento..

Aquí hay dos enlaces útiles sobre este tema: developers.google.com y css-tricks.com

Tamaño del archivo

Como mencionamos anteriormente, es bueno tener el menor código posible, ya que el navegador no muestra la página antes de descargar el CSS. Aquí hay algunos consejos para reducir el tamaño del archivo.

Combina estilos similares:

.encabezado font-size: 24px;  .content font-size: 24px; 

... se transforma en:

.encabezado, .content font-size: 24px; 

Usa taquimales. En lugar de:

.encabezado color de fondo: # 999999; imagen de fondo: url (… /images/header.jpg); posición de fondo: arriba a la derecha; 

Escríbelo de esta manera:

.header background: # 999 url (… /images/header.jpg) arriba a la derecha; 

Minimice su código CSS. Puedes hacerlo usando una herramienta que generalmente elimina todos los espacios y nuevas líneas. Por ejemplo, CSSOptimiser o Minifycss. Es una práctica común utilizar dichos instrumentos en el lado del servidor de la aplicación, es decir, algo escrito en el idioma del servidor. Normalmente estos componentes minimizan su código y se lo entregan al usuario.

Ponga sus archivos CSS en el Etiqueta

Es una buena práctica incluir su .css archivos en el cabeza Etiqueta, de esa manera el navegador lo descargará primero..


JavaScript

Reducir el número de solicitudes HTTP

Igual que con su CSS: es bueno reducir la cantidad de solicitudes que se envían al servidor. En la mayoría de los casos, la carga de los archivos JavaScript no detendrá la representación de la página, pero hará que algunas partes de la página no funcionen..

Reducir su código

Hay un montón de bibliotecas que hacen minificación de JavaScript. Es algo que reducirá el tamaño de los archivos, pero tenga en cuenta que en un entorno de desarrollo es bueno mantener el código limpio. La mayoría de estas herramientas cambian el nombre de sus variables y convierten todo en una cadena de una línea, lo que hace que el proceso de depuración sea casi imposible..

CommonJS, AMD, RequireJS - Pruébelo

JavaScript nativamente no tiene un mecanismo para gestionar módulos. Entonces, todas esas cosas están inventadas para resolver este problema. Proporcionan una API que puede utilizar para definir y utilizar módulos. Por ejemplo, aquí hay un ejemplo tomado de http://requirejs.org/:

   Mi proyecto de muestra     

Mi proyecto de muestra

Dentro de main.js, puedes usar exigir() para cargar cualquier otro script que necesites:

require (["helper / util"], function (util) // Esta función se llama cuando se cargan scripts / helper / util.js. // Si util.js llama a define (), entonces esta función no se activa hasta que // se han cargado las dependencias de util, y el argumento util contendrá // el valor del módulo para "helper / util".);

Utilizar espacios de nombres

Si estamos hablando de organización de códigos, no podemos omitir la parte sobre espacios de nombres. De forma nativa, no existe tal función en JavaScript, pero aún puede lograr lo mismo con un pequeño código. Por ejemplo, si desea crear su propio marco MVC, probablemente tendrá las siguientes clases:

var model = function () …; var view = function () …; controlador var = función () …;

Si deja las cosas como están en el código anterior, entonces se hacen públicas y hay una mayor probabilidad de generar conflictos con otras bibliotecas en su proyecto. Por lo tanto, agruparlos en un objeto independiente (espacio de nombres) hace que el marco esté protegido:

var MyAwesomeFramework = model: function () …, view: function () …, controller: function () …

Seguir los patrones de diseño

No hay necesidad de reinventar la rueda. JavasScript se hizo muy popular y hay muchas buenas prácticas por ahí. Los patrones de diseño son soluciones reutilizables para problemas comunes en la programación. Seguir algunos de ellos te ayudará a construir una buena aplicación. Sin embargo, si trato de cubrirlos todos aquí, tendría que escribir un libro, así que aquí están algunos de ellos:

Patrón de constructor

Utilice este patrón para crear una instancia de un tipo de objeto específico. Aquí hay un ejemplo:

var Class = function (param1, param2) this.var1 = param1; this.var2 = param2;  Class.prototype = method: function () alert (this.var1 + "/" + this.var2); ;

O puedes probar esto:

clase de función (param1, param2) this.var1 = param1; this.var2 = param2; this.method = function () alert (param1 + "/" + param2); ; ; var instance = new Class ("value1", "value2");

Patrón del módulo

El patrón del módulo nos da la capacidad de crear métodos privados y públicos. Por ejemplo, en el siguiente código, la variable _índice y el método Método privado son privados. incremento y getIndex son publicos.

var Module = (function () var _index = 0; var privateMethod = function () return _index * 10; return increment: function () _index + = 1;, getIndex: function () return _index; ;) ();

Patrón de observador

Donde sea que vea la suscripción o el envío de eventos, es probable que vea este patrón. Hay observadores que están interesados ​​en algo relacionado con un objeto específico. Una vez que ocurre la acción, el objeto notifica a los observadores. El siguiente ejemplo muestra cómo podemos agregar un observador a la Usuarios objeto:

var Users = list: [], listeners: , add: function (name) this.list.push (name: name); this.dispatch ("agregado por el usuario"); , en: function (eventName, listener) if (! this.listeners [eventName]) this.listeners [eventName] = []; this.listeners [eventName] .push (listener); , dispatch: function (eventName) if (this.listeners [eventName]) for (var i = 0; i 

Patrón de encadenamiento de funciones

Este patrón es una buena forma de organizar la interfaz pública de su módulo. Ahorra tiempo y mejora la legibilidad:

var Usuario = perfil: , nombre: función (valor) this.profile.name = valor; devuelve esto , trabajo: función (valor) this.profile.job = valor; devuelve esto , getProfile: function () return this.profile; ; var perfil = Nombre de usuario ("Krasimir Tsonev"). job ("desarrollador web"). getProfile (); console.log (perfil);

Recomiendo encarecidamente revisar este libro de Addy Osmani. Es uno de los mejores recursos que puedes encontrar sobre los patrones de diseño en JavaScript.


Paquete de activos

Ahora que estamos llegando al final de este artículo, quiero compartir algunas ideas sobre la administración de código CSS y JavaScript en el servidor. Es una técnica muy común para agregar la fusión, la minificación y la compilación en la lógica de la aplicación. A menudo hay algún tipo de mecanismo de almacenamiento en caché, pero todas las cosas están sucediendo durante el tiempo de ejecución. Así que probablemente tengas algo de lógica de código, que maneja la solicitud de .js o .css Archivos y sirve el contenido adecuado. Detrás de este proceso está la compilación, la minificación o lo que esté usando para empacar sus activos.

En mis últimos proyectos utilicé una herramienta llamada paquete de activos. Es realmente útil y explicaré en detalle qué hace exactamente, pero la parte más interesante es cómo la usé. Esta biblioteca está diseñada para ser utilizada solo en modo de desarrollo, no es algo que permanezca en su base de código y no es algo que deba implementar en su servidor de producción.

La idea es usar el empaquetador solo mientras está trabajando en los activos (CSS, JS). En realidad, observa los cambios en directorios específicos y compila / empaqueta el código en un solo archivo. Al utilizar este enfoque, no necesita pensar en la compilación o en la compilación. Todo lo que tienes que hacer es enviar el archivo estático compilado al usuario. Esto aumenta el rendimiento de su aplicación, porque solo sirve archivos estáticos y, por supuesto, simplifica las cosas. No necesita configurar nada en su servidor o implementar una lógica innecesaria.

Aquí es cómo puede configurar y utilizar paquete de activos.

Instalación

Esta herramienta es un módulo de Nodejs, por lo que debe tener Node ya instalado. Si no lo hace, solo vaya a nodejs.org/download y tome el paquete para su sistema operativo. Después de esto:

npm install -g assetpack

Uso

El módulo funciona con la configuración JSON. Cuando se utiliza a través de la línea de comando, debe colocar su configuración en un .json expediente.

A través de la línea de comando

Crear un activos.json Archivo y ejecute el siguiente comando en el mismo directorio:

paquete de activos

Si su archivo de configuración usa otro nombre o está en otro directorio, use:

assetpack --config [ruta al archivo json]

En codigo

var AssetsPack = require ("assetpack"); var config = [type: "css", watch: ["css / src"], output: "tests / packed / styles.css", minify: true, exclude: ["custom.css"]]; var pack = nuevo AssetsPack (config, function () console.log ("AssetsPack está mirando");); pack.onPack (function () console.log ("AssetsPack hizo el trabajo"););

Configuración

La configuración debe ser un archivo / objeto JSON válido. Es sólo una serie de objetos:

[(objeto de activo), (objeto de activo), (objeto de activo), ...]

Objeto activo

La estructura básica del objeto activo es así:

type: (tipo / cadena de archivo, podría ser css, js o menos, por ejemplo), watch: (directorio o directorios para ver / string o array de cadenas /), pack: (directorio o directorios para empaquetar / string o array de cadenas /.), salida: (ruta al archivo de salida / cadena /), minimizar: / boolean /, excluir: (matriz de nombres de archivos)

los paquete La propiedad no es obligatoria. Si lo echas de menos, entonces su valor es igual a reloj. minimizar por defecto es falso.

Aquí están algunos ejemplos:

Embalaje CSS

type: "css", watch: ["tests / data / css", "tests / data / css2"], pack: ["tests / data / css", "tests / data / css2"], salida: " tests / packed / styles.css ", minify: true, exclude: [" header.css "]

Packing JavaScript

type: "js", watch: "tests / data / js", pack: ["tests / data / js"], output: "tests / packed / scripts.js", minify: true, exclude: ["A .js "]

Embalaje .Menos Archivos

El embalaje de .Menos Los archivos son un poco diferentes. los paquete La propiedad es obligatoria y es básicamente su punto de entrada. Debes importar todos los demás .Menos archivos allí. los excluir la propiedad no está disponible aquí.

type: "less", watch: ["tests / data / less"], pack: "tests / data / less / index.less", salida: "tests / packed / styles-less.css", minify: true 

Si encuentra algún problema, por favor revise el tests / packing-less.spec.js del repositorio en GitHub.

Empaquetar otros formatos de archivo

paquete de activos Funciona con cualquier formato de archivo. Por ejemplo, podemos combinar plantillas HTML en un solo archivo haciendo algo como esto:

type: "html", watch: ["tests / data / tpl"], output: "tests / packed / template.html", exclude: ["admin.html"]

Lo único que debes saber aquí es que no hay minificación.


Conclusión

Como desarrolladores web front-end, debemos intentar ofrecer el mejor rendimiento posible para nuestros usuarios. Los consejos anteriores no deben cubrir todos los aspectos de la organización de activos y el rendimiento, pero son los que he tratado personalmente durante mi trabajo diario. Por favor, siéntase libre de compartir algunos de sus consejos a continuación, en los comentarios.