preloader

Polyfills y Transpiladores

JavaScript es un lenguaje que está en constante evolución. Regularmente se proponen nuevas características que son analizadas y, si se consideran valiosas, se añaden a la especificación oficial del lenguaje en https://tc39.github.io/ecma262/. Sin embargo, la implementación de estas características por parte de los intérpretes de JavaScript puede ser selectiva, priorizando algunas sobre otras debido a su complejidad o interés.

Para los desarrolladores, es crucial poder utilizar estas nuevas características en sus proyectos. Pero ¿cómo hacer que el código moderno funcione en intérpretes más antiguos que aún no las soportan?

Transpiladores

Un transpilador es una herramienta que traduce el código fuente de JavaScript de una versión más moderna a una más antigua. Esto permite que el código escrito con características nuevas pueda ejecutarse en navegadores más antiguos que no las entienden.

Por ejemplo, antes del año 2020, JavaScript no incluía el operador «nullish coalescing» ??. Si un usuario intentaba usar este operador en un navegador desactualizado, el código fallaría. Un transpilador analizaría este código y lo reescribiría utilizando construcciones más antiguas que los navegadores más antiguos pueden entender:

Antes de transpilar:

				
					height = height ?? 100;

				
			

Una especificación tiene tres bloques principales:

  1. describe(«título», function() { … }): Descripción de la funcionalidad que estamos describiendo. En nuestro caso, la función pow. Se utiliza para agrupar bloques de trabajo: los bloques it.

  2. it(«título», function() { … }): Bloque it. En el título de it, describimos el caso de uso. El segundo argumento es la función que lo prueba.

  3. assert.equal(value1, value2): Comprobación. El código dentro del bloque it que, si la implementación es correcta, debe ejecutarse sin errores.

Las funciones assert.* se utilizan para verificar que pow funcione como esperamos. Aquí usamos una de ellas: assert.equal, que compara argumentos y produce un error si no son iguales. Arriba se está verificando que el resultado de pow(2, 3) sea 8. Hay otros tipos de comparaciones y verificaciones que veremos más adelante.

El Flujo de Desarrollo

El flujo de desarrollo es el siguiente:

  1. Se escribe una especificación inicial, con pruebas para la funcionalidad más básica.
  2. Se crea una implementación inicial.
  3. Para verificar que funciona, ejecutamos el framework de pruebas Mocha (detallado más adelante) que ejecuta la “spec”. Mostrará los errores mientras la funcionalidad no esté completa. Hacemos correcciones hasta que todo funcione.
  4. Ahora tenemos una implementación inicial con pruebas.
  5. Añadimos más casos de uso a la especificación, probablemente no soportados aún por la implementación. Las pruebas comienzan a fallar.
  6. Regresamos al paso 3, actualizando la implementación hasta que las pruebas no den errores.
  7. Repetimos los pasos 3-6 hasta que la funcionalidad esté lista.

De esta manera, el desarrollo es iterativo. Escribimos la especificación, la implementamos, nos aseguramos de que las pruebas pasen, luego escribimos más pruebas, y nuevamente verificamos que pasen, etc. Al final, tenemos una implementación funcional con pruebas que la verifican.

La Especificación en Acción

Usaremos las siguientes bibliotecas JavaScript para las pruebas en este tutorial:

  • Mocha: El framework principal que proporciona funciones para pruebas comunes como describe e it, y la función principal que ejecuta las pruebas.
  • Chai: Una biblioteca con muchas funciones de comprobación (assertions). Permite el uso de diferentes comprobaciones. Usaremos assert.equal por ahora.
  • Sinon: Una biblioteca para espiar funciones, emular funciones incorporadas al lenguaje, y más. La necesitaremos a menudo más adelante.

Estas bibliotecas son adecuadas tanto para pruebas en el navegador como en el lado del servidor. Aquí nos enfocaremos en el navegador.

La siguiente es una página HTML con estos frameworks y nuestra especificación de pow:

				
					<!DOCTYPE html>
<html>
<head>
  <!-- Incluir CSS para Mocha, para mostrar los resultados -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css">
  <!-- Incluir el código del framework Mocha -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"></script>
  <script>
    mocha.setup('bdd'); // Configuración mínima
  </script>
  <!-- Incluir Chai -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"></script>
  <script>
    // Chai tiene muchas cosas, hacemos assert global
    let assert = chai.assert;
  </script>
</head>
<body>
  <script>
    function pow(x, n) {
      /* Código de la función, de momento vacío */
    }
  </script>
  <!-- El script con las pruebas (describe, it...) -->
  <script src="test.js"></script>
  <!-- El elemento con id="mocha" que contiene los resultados de las pruebas -->
  <div id="mocha"></div>
  <!-- ¡Ejecutar las pruebas! -->
  <script>
    mocha.run();
  </script>
</body>
</html>

				
			

Después de transpilar:

				
					height = (height !== undefined && height !== null) ? height : 100;

				
			

Babel es uno de los transpiladores más utilizados en la comunidad de JavaScript. Los sistemas modernos de desarrollo de proyectos, como webpack, permiten la integración automática de la transpilación en el flujo de trabajo, lo que facilita la compatibilidad con navegadores antiguos.

Polyfills

Además de las nuevas sintaxis y operadores, las nuevas versiones de JavaScript también pueden incluir nuevas funciones integradas. Por ejemplo, Math.trunc(n) es una función que elimina la parte decimal de un número. Sin embargo, navegadores muy antiguos pueden no tener esta función, lo que causaría que el código falle.

En lugar de transpilar, utilizamos un polyfill para añadir estas funciones faltantes al entorno de ejecución. Un polyfill es un script que verifica si una función existe y, si no es así, la implementa. Por ejemplo:

				
					if (!Math.trunc) {
  Math.trunc = function(number) {
    return number < 0 ? Math.ceil(number) : Math.floor(number);
  };
}

				
			

Esto asegura que la función Math.trunc esté disponible incluso en navegadores que no la soportan nativamente.

Uso Combinado

En resumen, mientras exploras y utilizas las características más modernas del lenguaje JavaScript, es importante asegurarte de que tu código sea compatible con los navegadores más antiguos. Los transpiladores te permiten usar sintaxis modernas al compilarlas a una versión más compatible, mientras que los polyfills te permiten añadir funciones faltantes a tu entorno de ejecución.

Para mantenerse al día con el soporte de las características del lenguaje, sitios como https://kangax.github.io/compat-table/es6/ son herramientas útiles. También puedes usar servicios como polyfill.io para incluir automáticamente los polyfills necesarios según el navegador del usuario.

¡Explora las nuevas características de JavaScript y asegúrate de que tu código sea accesible para todos los usuarios!

Related Post

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *