Saltar al contenido principal

Aproximándonos al Lanzamiento de la Versión 7.0

· 16 min de lectura
Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Consulta Planificación para 7.0 para las últimas actualizaciones durante las preversiones de 7.0. ¡Si algo no queda claro en esta publicación, házmelo saber!

Actualizaciones del Proyecto

  • Creamos una nueva página de videos para quienes quieran aprender cómo funciona Babel y ayudar a contribuir. Incluye charlas sobre Babel y conceptos relacionados de miembros del equipo y la comunidad (puedes enviar un PR si has dado una charla similar).

videos

  • También creamos una nueva página del equipo! Actualizaremos esta página con más detalles sobre las responsabilidades y motivaciones de cada miembro. Para un proyecto de esta envergadura, hay muchas formas de involucrarse y ayudar.

team

  • ¡Babel cumplió 3 años el 28 de septiembre de 2017!

  • Daniel migró babel/babylon y babel/babel-preset-env al monorepo principal babel/babel, incluyendo todo el historial de git, etiquetas e issues.

  • ¡Recibimos una donación de $1k/mes de Facebook Open Source!

    • Es la donación mensual más alta que hemos recibido (la siguiente es de $100/mes).
    • Usaremos estos fondos para reuniones presenciales y asistencia a reuniones de TC39, que ocurren cada 2 meses en distintas partes del mundo.
    • Si una empresa quiere patrocinar algo específico, podemos crear issues separados para seguimiento. Antes esto era difícil porque debíamos pagar de nuestro bolsillo o depender de conferencias coincidentes.

¿Cómo puedes ayudar?

Si tu empresa quiere contribuir apoyando una pieza fundamental del desarrollo JavaScript y su futuro, considera donar a nuestro Open Collective. También puedes donar tiempo de desarrollo para ayudar a mantener el proyecto.

#1 Ayuda a Mantener el Proyecto (tiempo de desarrollo en horario laboral)

Lo más valioso que podemos recibir son personas comprometidas a ayudar, dada la enorme carga de trabajo/responsabilidad. De nuevo, yo nunca me sentí preparado para ser mantenedor, pero terminé siéndolo. Somos solo unas pocas personas.

#2 Financia el desarrollo

Buscamos financiar miembros del equipo para trabajar tiempo completo. ¡Logan dejó su trabajo y actualmente usa nuestros fondos para trabajar en Babel a tiempo parcial!

#3 Contribuye de otras formas 😊

Por ejemplo, ¡Angus nos hizo una canción oficial!

Actualización

También estamos desarrollando una herramienta de actualización que ayudará a reescribir tus archivos package.json/.babelrc y más. Idealmente, esto modificaría los cambios necesarios en números de versión, renombramientos de paquetes y ajustes de configuración.

¡Por favor, contribuye reportando problemas al intentar actualizar! ¡Esta es una gran oportunidad para involucrarte y ayudar al ecosistema a actualizarse!

Resumen de la publicación anterior

  • Se eliminó el soporte para Node 0.10/0.12/5.

  • Actualizadas las propuestas TC39

    • Separador numérico: 1_000
    • Operador de encadenamiento opcional: a?.b
    • import.meta (analizable)
    • Enlace catch opcional: try { a } catch {}
    • BigInt (analizable): 2n
    • Se separaron las extensiones de exportación en export-default-from y export-ns-form
  • Soporte para .babelrc.js (configuración usando JavaScript en lugar de JSON)

  • Nueva Preconfiguración TypeScript + separación de preconfiguraciones React/Flow

  • Se eliminó la dependencia interna babel-runtime para reducir tamaño

Propuestas TC39 actualizadas recientemente

  • Operador de tubería: a |> b

  • Expresiones throw: () => throw 'hi'

  • Operador de coalescencia nula: a ?? b

Preconfiguraciones anuales obsoletas (ej. babel-preset-es20xx)

TL;DR: usa babel-preset-env.

¿Qué es mejor que decidir qué preconfiguración de Babel usar? ¡Que se haga automáticamente por ti!

Aunque el trabajo para mantener estas listas de datos es enorme —de nuevo, por qué necesitamos ayuda— resuelve múltiples problemas: asegura que los usuarios estén al día con la especificación, reduce la confusión en configuración/paquetes, facilita las actualizaciones y disminuye las dudas sobre funcionalidades.

babel-preset-env es en realidad una preconfiguración bastante antigua que reemplaza cualquier otra preconfiguración de sintaxis que necesitarías (es2015, es2016, es2017, es20xx, latest, etc.).

preconfiguraciones npm

Compila el último lanzamiento anual de JavaScript (lo que esté en Etapa 4), reemplazando todas las preconfiguraciones antiguas. Además, puede compilar según entornos objetivo específicos: desde la última versión de un navegador para desarrollo, hasta múltiples builds para compatibilidad con IE y navegadores modernos.

No eliminaremos las preconfiguraciones de etapa (babel-preset-stage-x)

EDIT: Las eliminamos, explicado aquí

Siempre podemos mantenerlas actualizadas, pero quizás necesitemos un sistema mejor que el actual para estas preconfiguraciones.

Actualmente, los presets de etapa son literalmente solo una lista de plugins que actualizamos manualmente después de las reuniones de TC39. Para hacer esto manejable, necesitamos permitir incrementos de versión mayor para estos paquetes "inestables". Parte de la razón es que la comunidad recrearía estos paquetes de todos modos, así que mejor hacerlo desde un paquete oficial para poder brindar mejores mensajes, etc.

Renombres: Paquetes con ámbito (@babel/x)

Aquí está una encuesta que hice hace casi un año:

En ese entonces, pocos proyectos usaban paquetes con ámbito, así que la mayoría ni siquiera sabía que existían. También podrías haber tenido que pagar por una cuenta de organización en npm en ese momento, mientras que ahora es gratis (y también admite paquetes sin ámbito). Los problemas con la búsqueda de paquetes con ámbito están resueltos y los recuentos de descargas funcionan. Lo único que queda es que algunos registros de terceros aún no admiten paquetes con ámbito, y creo que ya es bastante irrazonable esperar por eso.

Si quieres razones por las que preferimos paquetes con ámbito:

  • Nombrar es difícil: no tendremos que verificar si alguien decidió usar nuestra convención de nombres para su propio plugin

  • De manera similar, el acaparamiento de paquetes:

    • A veces la gente crea babel-preset-20xx u otro paquete porque es divertido, y luego tenemos que crear un problema/enviar un correo para pedirlo de vuelta.
    • La gente tiene un paquete legítimo, pero resulta tener el mismo nombre que queríamos usar.
    • La gente ve que una nueva propuesta se está fusionando (como encadenamiento opcional, operador de tubería) y decide bifurcar y publicar una versión bajo el mismo nombre. Luego, cuando publicamos, nos dice que el paquete ya fue publicado 🤔. Entonces, tengo que encontrar su correo electrónico y enviarles un mensaje a ellos y al soporte de npm para recuperar el paquete y volver a publicarlo.
  • ¿Qué es un paquete "oficial" y qué es un paquete de usuario/comunidad con el mismo nombre? Recibimos reportes de personas usando paquetes con nombres incorrectos o no oficiales porque asumieron que eran parte de Babel. Un ejemplo fue un reporte de que babel-env estaba reescribiendo su archivo .babelrc, y les tomó tiempo darse cuenta de que no era babel-preset-env.

Entonces, parece obvio que deberíamos usar paquetes con ámbito, ¡y en todo caso, deberíamos haberlo hecho mucho antes 🙂!

Ejemplos del cambio a nombres con ámbito:

  • babel-cli -> @babel/cli

  • babel-core -> @babel/core

  • babel-preset-env -> @babel/preset-env

Renombres: -proposal-

Cualquier propuesta ahora se nombrará con -proposal- para indicar que aún no son oficiales en JavaScript.

Así que @babel/plugin-transform-class-properties se convierte en @babel/plugin-proposal-class-properties, y lo renombraremos una vez que llegue a la Etapa 4.

Renombres: Eliminar el año del nombre del plugin

Los plugins anteriores tenían el año en el nombre, pero ahora parece que ya no es necesario.

Así que @babel/plugin-transform-es2015-classes se convierte en @babel/plugin-transform-classes.

Como los años solo se usaban para es3/es2015, no cambiamos nada de es2016 o es2017. Sin embargo, estamos dejando obsoletos esos presets en favor de preset-env, y para la revisión de literales de plantilla, simplemente lo agregamos a la transformación de literales de plantilla por simplicidad.

Dependencias Peer e Integraciones

Estamos introduciendo dependencias peer en @babel/core para todos los plugins (@babel/plugin-class-properties), presets (@babel/preset-env) y paquetes de nivel superior (@babel/cli, babel-loader).

Las peerDependencies son dependencias que se espera que utilice tu código, a diferencia de las dependencias que solo se usan como detalles de implementación. — Stijn de Witt vía StackOverflow.

babel-loader ya tenía una peerDependency en babel-core, por lo que este cambio simplemente la actualiza a @babel/core. Esto evita que las personas instalen estos paquetes en versiones incorrectas de Babel.

Para herramientas que ya tienen una peerDependency en babel-core y no están listas para un salto mayor (ya que cambiar la peer dependency es un cambio rompedor), hemos publicado una nueva versión puente de babel-core: babel-core@7.0.0-bridge.0. Para más detalles, consulta este issue.

De manera similar, paquetes como gulp-babel, rollup-plugin-babel, etc., solían tener babel-core como dependencia. Ahora tendrán solo una peerDependency en @babel/core. Esto permite que estos paquetes no requieran saltos de versión mayor cuando la API de @babel/core no ha cambiado.

#5224 Publicación Independiente de Paquetes Experimentales

Mencioné esto en El Estado de Babel en la sección Versioning. Issue en GitHub

Quizás recuerdes que después de Babel 6, Babel se convirtió en un conjunto de paquetes npm con su propio ecosistema de presets y plugins personalizados.

Sin embargo, desde entonces siempre hemos usado un sistema de versionado "fijo/sincronizado" (ningún paquete está en v7.0 o superior). Al hacer un nuevo lanzamiento como v6.23.0, solo los paquetes con código actualizado se publican con la nueva versión, mientras los demás permanecen igual. Esto funciona en la práctica principalmente porque usamos ^ en nuestros paquetes.

Desafortunadamente, este sistema requiere que una versión mayor se libere para todos los paquetes aunque solo uno lo necesite. Esto implica hacer muchos cambios rompedores pequeños (innecesarios) o agrupar numerosos cambios rompedores en un único lanzamiento. En su lugar, queremos diferenciar entre paquetes experimentales (Stage 0, etc.) y el resto (es2015).

Esto significa que planeamos hacer saltos de versión mayor en cualquier plugin de propuesta experimental cuando la especificación cambie, en lugar de esperar a actualizar todo Babel. Cualquier cosa en < Stage 4 estará sujeto a cambios rompedores mediante saltos de versión mayor, igual que los presets de etapa (si no los eliminamos completamente).

Esto va de la mano con nuestra decisión de renombrar los plugins de propuestas TC39 usando el nombre -proposal-. Si la especificación cambia, haremos un salto mayor en el plugin y el preset al que pertenece (en lugar de solo un parche que podría romper código). Luego, necesitaremos depreciar las versiones antiguas y establecer una infraestructura para actualizar automáticamente a los usuarios, asegurando que todos estén al día con lo que será la especificación final (y evitando que se queden estancados, como ocurrió con los decoradores).

¡La opción env en .babelrc NO será deprecada!

A diferencia de lo mencionado en el post anterior, simplemente corregimos el comportamiento de fusión para que sea más consistente.

La configuración en env tiene mayor prioridad que los elementos raíz, y en lugar de un enfoque confuso que usaba ambos, ahora los plugins y presets se fusionan según su identidad, permitiendo hacer:

JavaScript
{
presets: [
['env', { modules: false}],
],
env: {
test: {
presets: [
'env'
],
}
},
}

con BABEL_ENV=test, lo que reemplazaría la configuración env raíz con la de test, que no tiene opciones.

Compatibilidad con class A extends Array (la advertencia más antigua)

Babel envolverá automáticamente elementos nativos como Array, Error, HTMLElement, etc. para que esto funcione al compilar clases.

Velocidad

preset-env: "useBuiltins": "usage"

babel-preset-env introdujo compilar sintaxis para diferentes objetivos y, mediante useBuiltIns, agregar solo polyfills no soportados en el entorno destino.

Con esta opción, algo como:

JavaScript
import "babel-polyfill";

Puede convertirse en

JavaScript
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";
// ...

si el entorno de destino es compatible con polyfills distintos a padStart o padEnd.

Pero es mejor importar solo polyfills "usados" en el código. ¿Por qué importar padStart si no se usa?

"useBuiltins": "usage" implementa esta idea: importa al inicio de cada archivo solo si detecta su uso. Así importamos el mínimo de polyfills necesarios (y solo si el entorno destino no los soporta).

Si usas Promise, lo importará al inicio del archivo (si el destino no lo soporta). Los bundlers deduplicarán archivos idénticos, evitando importaciones múltiples.

JavaScript
import "core-js/modules/es6.promise";
var a = new Promise();
JavaScript
import "core-js/modules/es7.array.includes";
[].includes
a.includes

Con inferencia de tipos detectamos si .includes es para arrays. Los falsos positivos son aceptables temporalmente, pues sigue siendo mejor que importar todo el polyfill.

Actualizaciones varias

  • babel-template es más rápido/fácil de usar

  • regenerator se lanzó bajo Licencia MIT - dependencia para compilar generadores/async

  • Opción "lazy" en el plugin modules-commonjs vía #6952

  • Ahora puedes usar envName: "something" en .babelrc o pasar mediante CLI babel --envName=something en vez de tener que usar process.env.BABEL_ENV o process.env.NODE_ENV

  • ["transform-for-of", { "assumeArray": true }] para compilar bucles for-of como arrays regulares

  • Excluir transform-typeof-symbol en modo loose de preset-env #6831

  • PR implementado para mejores mensajes de error en sintaxis

Pendientes antes del lanzamiento

  • Resolver búsqueda de .babelrc (requerido para la primera RC)

  • Soporte para "overrides": configuración por patrones glob

  • Lógica de caché e invalidación en babel-core.

  • Implementar o tener un plan establecido para el versionado y manejo de polyfills de forma independiente a los helpers, evitando así una dependencia explícita de core-js 2 o 3. Esto es crucial ya que muchos proyectos dependen de una versión específica y generalmente querrán evitar cargar ambas simultáneamente.

  • Contar con una implementación funcional de decoradores o una implementación heredada operativa, junto con una ruta clara para incorporar el comportamiento actual de la especificación durante el ciclo de vida de la versión 7.x.

Agradecimientos

Un reconocimiento especial a nuestro equipo de voluntarios: Logan, quien ha trabajado intensamente resolviendo problemas centrales de configuración y realizando gran parte del trabajo pesado; Brian, que asumió el mantenimiento de preset-env y muchas tareas que yo solía hacer 😛; y Daniel, quien siempre colabora cuando se necesita ayuda, ya sea manteniendo babel-loader o facilitando la migración de los repositorios de babylon y babel-preset-env. Igual mérito para Nicolo, Sven, Artem y Jessica por su apoyo durante el último año.

Estoy realmente ansioso por esta publicación (también estoy cansado; llevamos casi un año 😝), pero sin prisas innecesarias. Ha habido muchos altibajos durante este lanzamiento, pero sin duda he aprendido muchísimo y estoy seguro que el resto del equipo también.

Y si algo he aprendido este año, es que debería aplicar este consejo en lugar de solo escribirlo.

Agradecimiento adicional a Mariko por el pequeño empujón para terminar esta publicación (¡llevaba 2 meses en proceso!)