Cómo monetizar su sitio HTML5

Introducción

El desarrollo para la Web móvil es un tema popular en la actualidad. Este año, por primera vez en la historia, los teléfonos inteligentes superan a las PCs. Cada vez más usuarios utilizan un dispositivo móvil para atravesar la Web, lo que significa que es fundamental que los desarrolladores optimicen sus sitios para los navegadores móviles.

El campo de batalla de los "dispositivos móviles" sigue siendo desconocido para una gran cantidad de desarrolladores. Muchas personas tienen sitios heredados que desestiman completamente a los usuarios de dispositivos móviles. En cambio, el sitio se diseñó principalmente para la navegación desde computadoras de escritorio y se deteriora en los navegadores para dispositivos móviles. Este sitio (html5rocks.com) no es la excepción. En el lanzamiento, no nos esforzamos mucho por crear la versión móvil del sitio.

Cómo crear un sitio html5rocks.com optimizado para dispositivos móviles

Como ejercicio, pensé que sería interesante tomar html5rocks (un sitio HTML5 existente) y mejorarlo con una versión optimizada para dispositivos móviles. Me preocupaba la cantidad mínima de trabajo que se necesitaba para orientar los anuncios a teléfonos inteligentes. El objetivo de mi ejercicio no era crear un sitio móvil completamente nuevo y mantener dos bases de código. Eso habría tomado una eternidad y habría sido una gran pérdida de tiempo. Ya habíamos definido la estructura del sitio (lenguaje de marcado). Tuvimos una apariencia (CSS). La funcionalidad principal (JS) estaba allí. El punto es que muchos sitios están en el mismo barco.

En este artículo, se analiza cómo creamos una versión móvil de html5rocks optimizada para dispositivos iOS y Android. Para ver la diferencia, simplemente cargue html5rocks.com en un dispositivo que admita uno de esos SO. No hay redireccionamientos a m.html5rocks.com ni a ningún otro software de esa naturaleza. Obtienes html5rocks tal como está... con el beneficio adicional de algo que se ve muy bien y funciona bien en un dispositivo móvil.

Escritorio html5rocks.com html5rocks.com para celulares
html5rocks.com en computadoras de escritorio (izquierda) y en dispositivos móviles (derecha)

Consultas de medios de CSS

HTML4 y CSS2 admiten hojas de estilo dependientes del contenido multimedia durante un tiempo. Por ejemplo:

<link rel="stylesheet" media="print" href="printer.css">

se orientarían a los dispositivos impresos y proporcionarían un estilo específico para el contenido de la página cuando se imprima. CSS3 lleva la idea de los tipos de medios un paso más allá y mejora su funcionalidad con consultas de medios. Las consultas de medios extienden la utilidad de los tipos de contenido multimedia, ya que permiten un etiquetado más preciso de las hojas de estilo. De esta manera, la presentación del contenido se puede personalizar para un rango específico de dispositivos de salida sin tener que cambiar el contenido. ¡Suena perfecto para un diseño existente que necesita modificación!

Puedes usar consultas de medios en el atributo media de tus hojas de estilo externas para establecer como objetivo el ancho de la pantalla, el ancho del dispositivo, la orientación, etc. Si deseas ver la lista completa, consulta la especificación de consultas de medios de W3C.

Cómo segmentar los anuncios para tamaños de pantalla

En el siguiente ejemplo, phone.css se aplicaría a dispositivos que el navegador considera "de mano" o con pantallas inferiores a 320 px de ancho.

 <link rel='stylesheet'
  media='handheld, only screen and (max-device-width: 320px)' href='phone.css'>

Si agregas la palabra clave "only" como prefijo a una consulta de medios, los navegadores que no cumplen con CSS3 ignorarán la regla.

Lo siguiente se orientaría a tamaños de pantalla de entre 641 y 800 píxeles:

 <link rel='stylesheet'
  media='only screen and (min-width: 641px) and (max-width: 800px)' href='ipad.css'>

Las consultas de medios también pueden aparecer dentro de las etiquetas <style> intercaladas. Lo siguiente se orienta a los tipos de contenido multimedia all en orientación vertical:

 <style>
  @media only all and (orientation: portrait) { ... }
 </style>

media="handheld"

Tenemos que detenernos un minuto para hablar sobre media="handheld". Lo cierto es que iOS y Android ignoran media="handheld". Se afirma que los usuarios se perderán el contenido de alta gama que proporcionan las hojas de estilo orientadas a media="screen", y es menos probable que los desarrolladores mantengan una versión de media="handheld" de menor calidad. Por lo tanto, como parte de su lema de "Web completa", la mayoría de los navegadores de smartphones modernos ignoran las hojas de estilo para dispositivos portátiles.

Sería ideal usar esta función para segmentar los anuncios para dispositivos móviles, pero varios navegadores la implementaron de diferentes maneras:

  • Algunos leen solo la hoja de estilo portátil.
  • Algunos solo leen la hoja de estilo portátil si existe, pero, de lo contrario, usan la hoja de estilo de pantalla de forma predeterminada.
  • Algunos leen tanto la hoja de estilo portátil como la hoja de estilo de pantalla.
  • Algunos leen solo la hoja de estilo de pantalla.

Opera Mini no ignora media="handheld". El truco para que Windows Mobile reconozca media="handheld" es utilizar mayúsculas en el valor del atributo multimedia de la hoja de estilo de la pantalla:

 <!-- media="handheld" trick for Windows Mobile -->
 <link rel="stylesheet" href="screen.css" media="Screen">
 <link rel="stylesheet" href="mobile.css" media="handheld">

Cómo html5rocks utiliza las consultas de medios

Las consultas de medios se usan mucho en HTML5rocks para celulares. Nos permitieron retocar el diseño sin tener que hacer cambios significativos en el lenguaje de marcado de nuestra plantilla de Django... ¡realmente un salvavidas! Además, su compatibilidad con varios navegadores es bastante buena.

En el <head> de cada página, verás las siguientes hojas de estilo:

 <link rel='stylesheet'
  media='all' href='/static/css/base.min.css' />
 <link rel='stylesheet'
  media='only screen and (max-width: 800px)' href='/static/css/mobile.min.css' />

base.css siempre definió el aspecto principal de html5rocks.com, pero ahora estamos aplicando nuevos estilos (mobile.css) a anchos de pantalla inferiores a 800 px. Su consulta de medios abarca teléfonos inteligentes (~320px) y el iPad (~768px). El efecto: se anulan de forma incremental los estilos en base.css (solo cuando es necesario) para que las cosas se vean mejor en dispositivos móviles.

Estos son algunos de los cambios de diseño que aplica mobile.css:

  • Reduce los espacios en blanco y el relleno adicionales en el sitio. Las pantallas pequeñas significan que el espacio es escaso.
  • Quita los estados :hover. Nunca se verán en dispositivos táctiles.
  • Ajusta el diseño para que sea de una sola columna. Explicaré eso después.
  • Quita la box-shadow alrededor del elemento div principal del contenedor del sitio. Las sombras de cuadro grandes reducen el rendimiento de la página.
  • Se usó el modelo de cuadro flexible de CSS box-ordinal-group para cambiar el orden de cada sección en la página principal. Verás que "APRENDER CON GRUPOS DE FUNCIONES DE HTML5 PRINCIPALES" aparece antes de la sección "INSTRUCTIVOS" en la página principal, pero después en la versión para dispositivos móviles. Este orden tenía más sentido para los dispositivos móviles y no requería cambios en el lenguaje de marcado. La estrella de CSS flexbox
  • Quita opacity de cambios. El cambio de los valores alfa afecta el rendimiento en dispositivos móviles.

Metaetiquetas para dispositivos móviles

WebKit para dispositivos móviles admite algunos accesorios que les brindan a los usuarios una mejor experiencia de navegación en ciertos dispositivos.

Configuración de viewport

La primera configuración meta (y la que usarás con mayor frecuencia) es la propiedad del viewport. Configurar un viewport le indica al navegador cómo debe caber el contenido en la pantalla del dispositivo y le informa que el sitio está optimizado para dispositivos móviles. Por ejemplo:

 <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">

le indica al navegador que establezca el ancho del viewport del dispositivo con una escala inicial de 1. En este ejemplo, también se permite el uso del zoom, algo que podría ser deseable para un sitio web, pero no para una aplicación web. Podríamos evitar el zoom con user-scalable=no o limitar el escalamiento a un nivel determinado:

 <meta name=viewport
  content="width=device-width, initial-scale=1.0, minimum-scale=0.5 maximum-scale=1.0">

Android extiende la metaetiqueta de la vista del puerto, ya que permite a los desarrolladores especificar para qué resolución de pantalla se desarrolló el sitio:

 <meta name="viewport" content="target-densitydpi=device-dpi">

Los valores posibles para target-densitydpi son device-dpi, high-dpi, medium-dpi y low-dpi.

Si quieres modificar tu página web para diferentes densidades de pantalla, usa la consulta de medios de CSS -webkit-device-pixel-ratio o la propiedad window.devicePixelRatio en JavaScript. Luego, establece la metapropiedad target-densitydpi en device-dpi. Esto evita que Android realice ajustes en tu página web y te permite hacer los ajustes necesarios para cada densidad mediante CSS y JavaScript.

Consulta la documentación de WebView para Android a fin de obtener más información sobre cómo orientar anuncios a resoluciones de dispositivos.

Navegación en pantalla completa

Existen otros dos metavalores que son específicos de iOS. apple-mobile-web-app-capable y apple-mobile-web-app-status-bar-style renderizarán el contenido de la página en modo de pantalla completa similar a la de una app y harán que la barra de estado sea translúcida:

 <meta name="apple-mobile-web-app-capable" content="yes">
 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

Para obtener más información sobre todas las opciones meta disponibles, consulta la documentación de referencia de Safari.

Íconos de la pantalla principal

Los dispositivos iOS y Android también aceptan un rel="apple-touch-icon" (iOS) y un rel="apple-touch-icon-precomposed" (Android) para los vínculos. Cuando estos crean un ícono llamativo similar a una aplicación en la pantalla de inicio del usuario cuando agregan su sitio a favoritos:

 <link rel="apple-touch-icon"
      href="/static/images/identity/HTML5_Badge_64.png" />
 <link rel="apple-touch-icon-precomposed"
      href="/static/images/identity/HTML5_Badge_64.png" />

Cómo usa HTML5rocks las metaetiquetas para dispositivos móviles

Para resumir todo, aquí hay un fragmento de la sección <head> de html5rocks:

 <head>
  ...
   <meta name="viewport"
        content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />

   <link rel="apple-touch-icon"
        href="/static/images/identity/HTML5_Badge_64.png" />
   <link rel="apple-touch-icon-precomposed"
        href="/static/images/identity/HTML5_Badge_64.png" />
  ...
 </head>

Diseño vertical

En pantallas más pequeñas, es mucho más conveniente desplazarse vertical que horizontalmente. En los dispositivos móviles, se prefiere mantener el contenido en una sola columna con el diseño vertical. Para html5rocks, usamos consultas de medios CSS3 para crear este diseño. De nuevo, sin cambiar el lenguaje de marcado.

Índice de instructivos. Instructivo. Página de funciones de HTML5 Página de perfiles de autor
Diseño vertical de una sola columna en todo el sitio

Optimizaciones para dispositivos móviles

La mayoría de las optimizaciones que realizamos son cosas que se deberían haber realizado en primer lugar. Por ejemplo, reducir la cantidad de solicitudes de red, la compresión de JS/CSS, gzipping (proviene de la versión gratuita de App Engine) y minimizar las manipulaciones del DOM. Estas técnicas son prácticas recomendadas comunes, pero en ocasiones se pasan por alto cuando se agiliza un sitio.

Ocultar automáticamente la barra de direcciones

Los navegadores para dispositivos móviles carecen del espacio en pantalla de sus equivalentes para computadoras de escritorio. Para peor, en diferentes plataformas a veces tienes una gran barra de direcciones en la parte superior de la pantalla, incluso después de que la página termina de cargarse.

Una manera fácil de lidiar con esto es desplazarse por la página con JavaScript. Incluso si lo haces con un píxel, se ocupará de la molesta barra de direcciones. Para forzar la ocultación de la barra de direcciones en html5rocks, adjunté un controlador de eventos onload al objeto window y me desplacé por la página verticalmente un píxel:

Barra de direcciones.
La barra de direcciones fea ocupa espacio en pantalla.
  // Hides mobile browser's address bar when page is done loading.
  window.addEventListener('load', function(e) {
    setTimeout(function() { window.scrollTo(0, 1); }, 1);
  }, false);

También unimos este objeto de escucha es nuestra variable de plantilla is_mobile, ya que no es necesaria en el escritorio.

Reduce las solicitudes de red y ahorra ancho de banda

Es un hecho conocido que reducir la cantidad de solicitudes HTTP puede mejorar en gran medida el rendimiento. Los dispositivos móviles limitan aún más la cantidad de conexiones simultáneas que puede hacer el navegador, por lo que los sitios móviles se beneficiarán aún más de reducir estas solicitudes superfluas. Además, reducir cada byte es fundamental, ya que el ancho de banda suele ser limitado en los teléfonos. Es posible que les estés cobrando dinero a los usuarios.

Los siguientes son algunos de los enfoques que adoptamos para minimizar las solicitudes de red y reducir el ancho de banda en HTML5rocks:

  • Elimina los iframes; los iframes son lentos. Una gran parte de nuestra latencia provino de widgets de uso compartido de terceros (Buzz, Google Friend Connect, Twitter, Facebook) en las páginas de instructivos. Estas se incluyeron mediante etiquetas <script> y crean iframes que disminuyen la velocidad de la página. Se quitaron los widgets para dispositivos móviles.

  • display:none: En algunos casos, ocultamos el lenguaje de marcado si no se ajustaba al perfil de dispositivo móvil. Un buen ejemplo fueron los cuatro cuadros redondeados en la parte superior de la página principal:

Botones de cuadro en la página de inicio.
Botones de cuadro en la página de inicio.

No aparecen en el sitio móvil. Es importante recordar que, de todos modos, el navegador realiza una solicitud para cada ícono, a pesar de que el contenedor esté oculto con display:none. Por lo tanto, no fue suficiente esconder estos botones. No solo eso sería desperdiciar ancho de banda, sino que el usuario ni siquiera vería los frutos de ese ancho de banda desperdiciado. La solución fue crear un booleano "is_mobile" en nuestra plantilla de Django para omitir secciones de HTML de forma condicional. Cuando el usuario ve el sitio en un dispositivo inteligente, los botones no aparecen.

  • Caché de la aplicación: Esto no solo nos brinda soporte sin conexión, sino que también permite un inicio más rápido.

  • Compresión CSS/JS: usamos un compresor YUI en lugar del compilador de cierre, principalmente porque controla CSS y JS. Un problema con el que nos encontramos fue que las consultas de medios intercaladas (consultas de medios que aparecen dentro de una hoja de estilo) se filtraron en el compresor YUI 2.4.2 (consulta este problema). El uso de YUI Compressor 2.4.4+ solucionó el problema.

  • Se usan objetos de imagen CSS cuando es posible.

  • Se usó pngcrush para la compresión de imágenes.

  • Usó dataURIs para imágenes pequeñas. La codificación Base64 agrega alrededor del 30%o más a la imagen, pero guarda la solicitud de red.

  • Búsqueda personalizada de Google cargada automáticamente con una sola etiqueta de secuencia de comandos en lugar de cargarla de forma dinámica con google.load() El segundo realiza una solicitud adicional.

<script src="//www.google.com/jsapi?autoload={"modules":[{"name":"search","version":"1"}]}"> </script>
  • En cada página se incluían nuestra impresora de código, Modernizr, aunque nunca se hayan usado. Modernizr es genial, pero ejecuta muchas pruebas en cada carga. Algunas de esas pruebas realizan modificaciones costosas en el DOM y ralentizan la carga de la página. Ahora, solo incluimos estas bibliotecas en páginas en las que realmente son necesarias. -2 solicitudes :)

Ajustes adicionales de rendimiento:

  • Se movió todo el JS al final de la página (si es posible).
  • Se quitaron las etiquetas <style> intercaladas.
  • Búsquedas del DOM en caché y manipulaciones del DOM minimizadas: Cada vez que tocas el DOM, el navegador realiza un reprocesamiento. Los reprocesamientos son aún más costosos en un dispositivo móvil.
  • Se descargó al servidor el código del cliente con desperdicio. Específicamente, la verificación para establecer el estilo de navegación de la página actual: js var lis = document.querySelectorAll('header nav li'); var i = lis.length; while (i--) { var a = lis[i].querySelector('a'); var section = a.getAttribute("data-section"); if (new RegExp(section).test(document.location.href)) { a.className = 'current'; } }
  • Se reemplazaron los elementos con anchos fijos por width:100% o width:auto flexibles.

Caché de aplicación

La versión para dispositivos móviles de html5rocks usa la caché de la aplicación para acelerar la carga inicial y permite a los usuarios leer el contenido sin conexión.

Cuando implementes AppCache en tu sitio, es muy importante que no almacenes en caché el archivo de manifiesto (ya sea explícitamente en el archivo de manifiesto o implícitamente con encabezados de control de caché pesados). Si el navegador almacena tu manifiesto en caché, depurarlo es una pesadilla. iOS y Android hacen un trabajo particularmente bueno para almacenar este archivo en caché, pero no proporcionan una manera conveniente de vaciar la caché como lo hacen los navegadores de escritorio.

A fin de evitar dicho almacenamiento en caché para nuestro sitio, primero configuramos App Engine para que nunca almacene en caché archivos de manifiesto:

- url: /(.*\.(appcache|manifest))
  static_files: \1
  mime_type: text/cache-manifest
  upload: (.*\.(appcache|manifest))
  expiration: "0s"

En segundo lugar, usamos la API de JS para informar al usuario cuando un nuevo manifiesto haya terminado de descargarse. Se le solicitará que actualice la página:

window.applicationCache.addEventListener('updateready', function(e) {
  if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
    window.applicationCache.swapCache();
    if (confirm('A new version of this site is available. Load it?')) {
      window.location.reload();
    }
  }
}, false);

Para ahorrar tráfico de red, mantén simple el manifiesto. Es decir, no mencione todas las páginas de su sitio. Solo enumera las imágenes importantes, CSS y los archivos de JavaScript. Lo último que debes hacer es forzar al navegador para dispositivos móviles a descargar una gran cantidad de elementos en cada actualización de appcache. En cambio, recuerda que el navegador almacenará en caché de manera implícita una página HTML cuando el usuario la visite (y que incluye un atributo <html manifest="...">).