Cómo migrar Puppeteer a TypeScript

Somos grandes fanáticos de TypeScript en el equipo de Herramientas para desarrolladores, tanto que se está creando un nuevo código en esta herramienta y estamos en medio de una gran migración de toda la base de código para que TypeScript lo verifique. Puedes obtener más información sobre esa migración en nuestra charla en Chrome Dev Summit 2020. Por lo tanto, también tenía sentido analizar la migración de la base de código de Puppeteer a TypeScript.

Planifica la migración

Cuando planificamos cómo realizar la migración, queríamos poder avanzar con pequeños pasos. Esto mantiene baja la sobrecarga de la migración (solo solo trabajas en una pequeña parte del código en cualquier momento) y también mantienes el riesgo bajo. Si hay algún problema con alguno de los pasos, puedes revertirlo fácilmente. Puppeteer tiene muchos usuarios y una versión dañada podría causar problemas a muchos de ellos, por lo que era fundamental que mantuviéramos el riesgo de romper los cambios al mínimo.

También tuvimos la suerte de que Puppeteer tenga un conjunto sólido de pruebas de unidades que cubre toda su funcionalidad. Esto significaba que podíamos estar seguros de que no rompíamos el código durante la migración, sino también de que no introdujimos cambios en nuestra API. El objetivo de la migración era completarla sin que ningún usuario de Puppeteer se diera cuenta de que habíamos migrado, y las pruebas fueron una parte vital de esa estrategia. Si no hubiésemos tenido una buena cobertura de prueba, habríamos agregado eso antes de continuar con la migración.

Realizar cualquier cambio de código sin pruebas es riesgoso, pero los cambios en los que tocas archivos enteros o toda la base de código son muy riesgosos. Cuando se realizan cambios mecánicos, es fácil pasar por alto un paso y, en varias ocasiones, las pruebas detectaron un problema que pasó por alto el implementador y el revisor.

Invertimos tiempo en nuestra configuración de integración continua (CI) por adelantado. Notamos que las ejecuciones de CI en función de las solicitudes de extracción eran inestables y a menudo fallaban. Esto sucedía con tanta frecuencia que teníamos el hábito de ignorar nuestra CI y combinar las solicitudes de extracción de todos modos, suponiendo que la falla era un problema único en CI en lugar de un problema en Puppeteer.

Después de un poco de mantenimiento general y dedicado a corregir algunas copos de prueba regulares, logramos pasar a un estado de aprobación mucho más coherente, lo que nos permite escuchar la CI y saber que una falla indicaba un problema real. Este trabajo no es glamoroso y resulta frustrante ver las interminables ejecuciones de CI, pero era fundamental que nuestro conjunto de pruebas se ejecutara de manera confiable debido a la cantidad de solicitudes de extracción que arrojaba la migración.

Elige y obtén un archivo

En este punto, teníamos lista la migración y un servidor de CI sólido lleno de pruebas para vigilar. En lugar de buscar archivos arbitrarios, elegimos intencionalmente un archivo pequeño para migrar. Este es un ejercicio útil porque te permite validar el proceso planificado que estás por realizar. Si funciona en este archivo, tu enfoque es válido; si no, puedes volver al tablero de dibujo.

Además, el uso de archivos por archivo (y con las versiones habituales de Puppeteer, por lo que los cambios no se lanzaron en la misma versión de npm) mantuvo el riesgo bajo. Elegimos DeviceDescriptors.js como el primer archivo, porque era uno de los archivos más sencillos de la base de código. Puede resultar algo decepcionante hacer todo este trabajo de preparación y realizar un cambio tan pequeño, pero el objetivo no es hacer grandes cambios de inmediato, sino proceder con precaución y archivo por archivo. El tiempo dedicado a validar el enfoque definitivamente ahorra tiempo más adelante en la migración, cuando se accede a esos archivos más complicados.

Demuestra el patrón y repite

Afortunadamente, el cambio a DeviceDescriptors.js se incorporó con éxito a la base de código, y el plan funcionó como esperábamos. Ya está listo para agacharte y continuar, que es exactamente lo que hicimos. Usar una etiqueta de GitHub es una muy buena forma de agrupar todas las solicitudes de extracción. Eso nos resultó útil para realizar un seguimiento del progreso.

Migrar el sitio y mejorarlo más tarde

Para cualquier archivo JavaScript individual, nuestro proceso fue el siguiente:

  1. Cambia el nombre del archivo de .js a .ts.
  2. Ejecuta el compilador de TypeScript.
  3. Soluciona cualquier problema.
  4. Crea la solicitud de extracción.

La mayor parte del trabajo realizado en estas solicitudes de extracción iniciales consistió en extraer interfaces de TypeScript para estructuras de datos existentes. En el caso de la primera solicitud de extracción que migró DeviceDescriptors.js que mencionamos antes, el código pasó de:

module.exports = [
  { 
    name: 'Pixel 4',
    … // Other fields omitted to save space
  }, 
  …
]

Y se convirtió en:

interface Device {
  name: string,
  …
}

const devices: Device[] = [{name: 'Pixel 4', …}, …]

module.exports = devices;

Como parte de este proceso, trabajamos en cada línea de la base de código para verificar si hay problemas. Al igual que con cualquier base de código que haya existido durante algunos años y creció con el tiempo, hay áreas de oportunidad para refactorizar el código y mejorar la situación. Especialmente con el cambio a TypeScript, vimos lugares en los que una leve reestructuración del código nos permitiría apoyarnos más en el compilador y obtener una mejor seguridad de tipos.

Contrariamente a lo intuitivo, es muy importante resistirse a hacer estos cambios de inmediato. El objetivo de la migración es llevar la base de código a TypeScript y, en todo momento, durante una migración grande, debe pensar en el riesgo de provocar fallas en el software y en sus usuarios. Al mantener los cambios iniciales al mínimo, mantuvimos ese riesgo bajo. Una vez que el archivo se combinó y se migró a TypeScript, pudimos realizar cambios de seguimiento para mejorar el código y aprovechar el sistema de tipos. Asegúrate de establecer límites estrictos para tu migración y trata de mantenerte dentro de ellos.

Migra las pruebas para probar nuestras definiciones de tipos

Una vez que hayamos migrado todo el código fuente a TypeScript, pudimos enfocarnos en nuestras pruebas. Nuestras pruebas tuvieron una gran cobertura, pero todas se escribieron en JavaScript. Esto significa que no probaron nuestras definiciones de tipos. Uno de los objetivos a largo plazo del proyecto (en el que aún estamos trabajando) es enviar definiciones de tipos de alta calidad listas para usar con Puppeteer, pero no tenemos ninguna verificación en nuestra base de código sobre nuestras definiciones de tipo.

Al migrar las pruebas a TypeScript (siguiendo el mismo proceso, archivo por archivo), encontramos problemas con nuestra TypeScript que, de lo contrario, nos habrían hecho los usuarios para que los encontraran. Nuestras pruebas no solo abarcan todas nuestras funciones, sino que también actúan como un control de calidad de TypeScript.

Ya hemos obtenido grandes beneficios de TypeScript como ingenieros que trabajan en la base de código de Puppeteer. Junto con nuestro entorno de CI mucho mejorado, nos permitió ser más productivos cuando trabajamos en Puppeteer y lograr que TypeScript detecte errores que, de otro modo, serían una actualización de npm. Nos complace anunciar el envío de definiciones de alta calidad de TypeScript para que todos los desarrolladores que usan Puppeteer también se beneficien de este trabajo.

Descarga los canales de vista previa

Considera usar Chrome Canary, Dev o Beta como tu navegador de desarrollo predeterminado. Estos canales de vista previa te brindan acceso a las funciones más recientes de Herramientas para desarrolladores, prueban las API de vanguardia de la plataforma web y te permiten encontrar problemas en tu sitio antes que los usuarios.

Cómo comunicarte con el equipo de Herramientas para desarrolladores de Chrome

Usa las siguientes opciones para hablar sobre las nuevas funciones y los cambios en la publicación, o cualquier otro aspecto relacionado con Herramientas para desarrolladores.

  • Envíanos una sugerencia o un comentario a través de crbug.com.
  • Informa un problema en Herramientas para desarrolladores con Más opciones   Más   > Ayuda > Informar problemas de Herramientas para desarrolladores en esta herramienta.
  • Envía un tweet a @ChromeDevTools.
  • Deje comentarios en las Novedades de los videos de YouTube de Herramientas para desarrolladores o en las sugerencias de Herramientas para desarrolladores los videos de YouTube.