Saltar al contenido principal

Eliminación de los presets de etapas en Babel

· 13 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 →

Avanzando con la versión 7, hemos decidido que es mejor dejar de publicar los presets de etapas en Babel (por ejemplo, @babel/preset-stage-0).

No tomamos esta decisión a la ligera y queremos explicar el contexto detrás de la interacción entre TC39, Babel y la comunidad.

Un poco de historia

Un preset de Babel es una lista compartible de plugins.

Los presets oficiales de etapas de Babel seguían el proceso de etapas de TC39 para nuevas propuestas de sintaxis en JavaScript.

Cada preset (ej. stage-3, stage-2, etc.) incluía todos los plugins para esa etapa específica y los de etapas superiores. Por ejemplo, stage-2 incluía stage-3, y así sucesivamente.


Esto permitía que usuarios que querían usar sintaxis experimental simplemente añadieran el preset, en lugar de configurar/instalar cada plugin individualmente.

De hecho, añadimos los presets de etapas poco después del lanzamiento de Babel v6 (antes era una bandera de configuración en v5). Abajo se muestra un ejemplo antiguo de Babel v6.

Era común ver esto en una configuración:

JavaScript
{
"presets": ["es2015", "react", "stage-0"]
}

El código fuente original de babel-preset-stage-0:

babel.config.js
module.exports = {
presets: [
require("babel-preset-stage-1")
],
plugins: [
require("babel-plugin-transform-do-expressions"),
require("babel-plugin-transform-function-bind")
]
};

Problemas

Estos presets eran una forma conveniente de usar lo que todos queríamos: el futuro nuevo y brillante de JavaScript aún por determinar.

Mirando atrás, ¡funcionó muy bien! (¿Quizás demasiado bien?)

¿Demasiado eficaz?

Lenguajes como CoffeeScript y herramientas como Traceur ayudaron a establecer la idea de compilar JavaScript. Babel lo hizo aún más fácil tanto para usar sintaxis nueva/futura como para integrarse con herramientas existentes. Las expectativas pasaron del escepticismo y la preocupación a abrazar completamente lo experimental.

Probablemente no estaríamos donde estamos sin la amplia adopción de compiladores como Babel: aceleró el uso (y enseñanza) de ES2015 a una audiencia mucho mayor. El crecimiento de React impulsó aún más su uso, ya que su sintaxis JSX, propiedades de clase y operador rest/spread llevaron a que más personas conocieran estas propuestas de sintaxis.

Babel se convirtió en una configuración única para muchos, sin necesidad de volver a pensar en ello. Se convirtió en infraestructura subyacente, oculta detrás de otras herramientas hasta que había un SyntaxError, problemas de dependencias o problemas de integración. Simplemente usaban stage-0.

Fue genial verlo en cierto modo, ya que significaba que estas ideas se probaban en entornos reales, incluso en producción. Sin embargo, también implicaba que muchas empresas, herramientas y personas tendrían problemas si una propuesta cambiaba significativamente (o incluso se abandonaba).

Idas y venidas

A lo largo de los años, hemos planteado muchos temas para discutir qué hacer con los presets de etapas en #4914, #4955, #7770. Incluso escribí en una publicación anterior sobre Babel 7.0 que decía que no los eliminaríamos 😅.

Sin embargo, descubrimos que mantener los presets de etapas causaría problemas incluso para el propio Babel:

  • Era un problema común preguntar algo como: "¿Qué preset(s) se necesitan para usar funciones asíncronas?". Resultaba poco claro para la gente saber exactamente qué significaba stage-0, y pocas personas revisaban su package.json o código fuente.

  • Eliminar un plugin de propuesta en Etapa 3 (una vez que pasa a Etapa 4) es de hecho un cambio rompedor. Este problema se agrava cuando intentas usar @babel/preset-env para no compilar una propuesta soportada nativamente.

"Decoradores de ES7"

Parte del problema radica precisamente en nombrar cosas, y como solemos escuchar, poner nombres es difícil.

Hubo muchos nombres para ES6: Harmony, ES Next, ES6, ES2015. Cuando la gente escucha sobre nuevas ideas, es lógico simplemente tomar el último número y adjuntarle el nombre.

Por lo tanto, es fácil buscar por ahí tweets/publicaciones de blog/charlas que digan "Decoradores de ES7" y descubrir que se ha convertido en el nombre habitual.

Es completamente comprensible que esto suceda sin darse cuenta, pero continuar haciéndolo establece expectativas diferentes sobre cómo progresa el lenguaje. No hay que sentirse culpable: aprendemos como comunidad y nos recordamos mutuamente cómo funciona JavaScript.

Jay Phelps escribió un buen artículo sobre este tema. Explica que sería mejor llamarlos por la "Etapa" en la que se encuentran actualmente: "Decoradores de Etapa 2", o simplemente la "Propuesta de Decoradores".

El razonamiento es que decir "Decoradores de ES7" asume que se espera que Decoradores esté en ES7. Mencioné esto en mi última publicación sobre compilar node_modules, pero estar en una etapa particular no garantiza mucho: una propuesta puede estancarse, retroceder o eliminarse por completo.

Quisimos destacar este hecho cuando decidimos cambiar los nombres de los plugins de propuesta de @babel/plugin-transform- a @babel/plugin-proposal-.

BabelScript

Tener presets para propuestas tan tempranas en el proceso puede implicar que estas propuestas están garantizadas para avanzar o tienen una implementación estable.

TC39 insta a la precaución al usar propuestas de Etapa 2 o inferiores, ya que podría generar presión inadvertida de la comunidad para mantener la implementación tal cual, en lugar de mejorarla por miedo a romper código existente o fragmentación del ecosistema (ej. usar un símbolo diferente como # en lugar de @ para decoradores).

La gente bromea diciendo que los desarrolladores que usan Babel están usando "BabelScript" en lugar de JavaScript, insinuando que una vez que se crea un plugin de Babel para cierta característica, eso significa que está "fijada" o ya es oficialmente parte del lenguaje (lo cual no es cierto). Para algunos, el primer pensamiento al ver una nueva sintaxis/idea (Etapa "-1") es si hay un plugin de Babel para ello.

Estableciendo expectativas

Después de que compiladores como Babel hicieran común que la gente escribiera ES2015, era natural que los desarrolladores quisieran probar "características" aún más nuevas y experimentales. La forma de hacer esto en Babel era usar la bandera stage en versiones anteriores o los presets stage-x.

Como la forma más conveniente de activar cualquier característica nueva, rápidamente se convirtió en la opción predeterminada al configurar Babel (aunque en Babel v6 pasó a no hacer nada por defecto, lo que causó muchas quejas).

Se volvió común ver "stage-0" usado en bibliotecas, plantillas, charlas, tuits y diapositivas.

Hubo buenas discusiones incluso hace años, pero no era fácil navegarlas: no queríamos penalizar a usuarios que entendían las compensaciones con console.warn al usarlo, y eliminar la opción parecía irrazonable en ese momento.

Activar ciegamente Stage 0 (tanto si lo teníamos por defecto como si la gente elegía hacerlo) parece peligroso, pero nunca usar ninguna propuesta es excesivamente cauteloso. Idealmente, todos deberían poder tomar decisiones informadas sobre qué características les parecen razonables y usarlas con prudencia, independientemente de su etapa. Mike Pennisi escribió un gran artículo sobre estas preocupaciones.

No es nuestra intención amenazar, apresurar o forzar cosas específicas en el ecosistema o JavaScript, sino mantener fielmente la implementación/discusiones en torno a nuevas ideas.

Dificultades

Otras consideraciones

También podríamos haber intentado:

  • Renombrar los presets para indicar mejor el nivel de estabilidad (no resuelve el problema de versionado)

  • Mejores estrategias de versionado: versionar los presets independientemente y actualizarlos inmediatamente cuando sea necesario, quizás usando 0.x

  • Advertir/Error para versiones antiguas desactualizadas de presets

Al final, la gente aún tendría que buscar qué propuestas están en qué Etapa para saber cuáles usar si mantuviéramos las Etapas.

¿Por qué ahora?

¿Por qué no eliminarlo antes? Los presets Stage llevan años en Babel, y había preocupaciones sobre añadir más "complejidad" al uso de Babel. Muchas herramientas, documentación, artículos y conocimiento giraban en torno a los presets Stage. Antes pensábamos que era mejor mantenerlos oficialmente, ya que alguien más inevitablemente los crearía (y lo hará).

Estamos tratando de determinar el nivel adecuado de retroalimentación: si solo el comité decide qué entra en el lenguaje, puede llevar a características bien especificadas pero innecesarias, pero si la comunidad espera que propuestas experimentales en progreso se consideren estables u óptimas para producción sin consecuencias, tendremos otros problemas. Todos queremos avanzar con intención: sin apresurarnos, pero sin ser demasiado cautelosos. Babel es el lugar adecuado para esa experimentación, pero conocer los límites es necesario.

Eliminar los presets se consideraría una "característica" porque significa que alguien tendría que decidir explícitamente usar cada propuesta, lo cual es razonable dada su variada inestabilidad, utilidad y complejidad.

Esperamos cierta crítica inicial, pero finalmente creemos que eliminar los presets Stage es mejor a largo plazo. Sin embargo, eliminar valores predeterminados anteriores o los presets Stage no significa que no nos importe la facilidad de uso, nuevos usuarios o documentación. Trabajamos para mantener el proyecto estable, proporcionar herramientas que mejoren las cosas y documentar lo que sabemos.

Migración

Para una migración más automática, hemos actualizado babel-upgrade para hacerlo por ti (puedes ejecutar npx babel-upgrade).

El TL;DR es que estamos eliminando los presets de etapa. En cierto modo, los usuarios deberán optar explícitamente y conocer qué tipos de propuestas están utilizando, en lugar de asumir qué deberían usar, especialmente dada la naturaleza inestable de algunas de estas propuestas. Si usas otro preset o una cadena de herramientas (por ejemplo, create-react-app), es posible que este cambio no te afecte directamente.

Hemos marcado como obsoletos los Stage presets a partir de 7.0.0-beta.52. Si no deseas cambiar tu configuración ahora, te sugerimos fijar las versiones a beta.54 hasta que puedas actualizar; después de beta.54 lanzaremos un error con un mensaje explicando cómo migrar. Y verifica que todas tus versiones sean consistentes mientras estés en versión preliminar.

Como alternativa, puedes crear tu propio preset que contenga los mismos plugins y actualizarlos según prefieras. En el futuro, podríamos desarrollar un babel-init que ayude a configurar plugins interactivamente o actualizar babel-upgrade para listar y añadir los plugins actuales de etapa. Quizás Babel debería mantenerse como una herramienta de bajo nivel y depender de otras herramientas/frameworks de alto nivel como create-react-app para gestionar estas elecciones.

Evitar la dependencia permanente de propuestas

James DiGioia escribió recientemente una publicación sobre los cambios en el operador pipeline (|>).

El punto clave es que la propuesta misma está en evolución y tiene varias opciones por explorar. Como queremos implementar las tres posibilidades actuales como plugins de Babel para obtener retroalimentación técnica y de usuarios, consideramos que el uso del plugin también debe cambiar. ¡Este es un enfoque relativamente nuevo para TC39 y Babel!

Anteriormente, simplemente añadíamos el plugin de la propuesta a la configuración. Ahora eliminamos el comportamiento predeterminado y pedimos a los usuarios que opten explícitamente por una bandera que indique qué propuesta eligen, dejando claro que actualmente no hay una opción fija (ni siquiera preferida).

{
"plugins": [
- "@babel/plugin-proposal-pipeline-operator"
+ ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }]
]
}

Queremos mantener este enfoque como señal de que estas propuestas están abiertas a cambios y retroalimentación colectiva. La eliminación de los Stage presets facilita esto, ya que antes debíamos propagar estas opciones incluso si no usabas la sintaxis.

Carga de mantenimiento del ecosistema

El "presupuesto de sintaxis" de un lenguaje no solo afecta su complejidad, sino que se extiende al ecosistema de herramientas. Cada nueva sintaxis añade carga a los mantenedores de otros proyectos JavaScript.

Al proponerse nueva sintaxis, muchos elementos requieren actualización: parsers (babylon), resaltado de sintaxis (language-babel), linters (babel-eslint), frameworks de pruebas (jest/ava), formateadores (prettier), cobertura de código (istanbul), minificadores (babel-minify), y más.

Proyectos como acorn, eslint, jshint y typescript reciben constantes solicitudes para soportar propuestas de Etapa 0 porque estaban en Babel. Pocos proyectos adoptarían políticas que exijan soportar cualquier propuesta, pues sería insostenible. Es sorprendente que incluso Babel intente manejarlo, dada la constante actualización y rotación.

¿Quién realiza este trabajo? ¿Es nuestra responsabilidad garantizar que todo funcione? Estos proyectos (mayoritariamente mantenidos por voluntarios) carecen de ayuda en casi todos los aspectos, y aún así recibimos quejas generalizadas. ¿Cómo debemos, como comunidad, responsabilizarnos de nuestra infraestructura (algo común en el open source en general)?

Babel ha asumido la inusual carga de admitir estas características experimentales; al mismo tiempo, es razonable que otros proyectos adopten políticas más conservadoras. Si deseas ver nuevas características del lenguaje admitidas en todo el ecosistema, contribuye a TC39 y a este proyecto para llevar estas propuestas a la Etapa 4.

El futuro

El propósito de este proyecto es actuar como parte del proceso de TC39: ser un recurso tanto para implementar propuestas más nuevas (Etapa 0-2) como para recibir comentarios de los usuarios, al mismo tiempo que se admiten versiones anteriores de JavaScript. Esperamos que esta publicación arroje más luz sobre cómo estamos intentando, lo mejor posible, alinear mejor este proyecto en el ecosistema de JavaScript. ¡Lanzaremos una versión candidata (RC) para v7 pronto!


Si aprecias esta publicación y el trabajo que estamos haciendo en Babel, puedes apoyarme en Patreon, pedirle a tu empresa que nos patrocine en Open Collective, o mejor aún, lograr que tu empresa se involucre con Babel como parte de su trabajo. Agradeceríamos la propiedad colectiva.

¡Con agradecimiento a todos los revisores! Siéntete libre de dar tu opinión en Twitter.