7.10.0 Lanzado: Campos de Clase en preset-env, verificaciones '#private in' y mejor tree-shaking para React
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
¡Acabamos de publicar una nueva versión menor de Babel!
Esta versión 7.10 incluye:
-
Soporte completo para la nueva propuesta en Etapa 1: verificaciones
#prop in objpara campos privados propuesta. -
@babel/preset-envahora compila secuencias de escape Unicode estilo ES2015 (\u{Babe1}) a sintaxis heredada equivalente (\uDAAA\uDFE1). -
Dos mejoras al operador Encadenamiento Opcional (
?.) -
Soporte en el parser para la nueva propuesta en Etapa 1 Atributos de Módulo (
import a from "./a.json" with type: "json"). -
¡Mejor soporte de tree-shaking para código React (ej.
React.memo)! -
¡Creación del repositorio RFCs y páginas de Discusiones en GitHub!
Puedes leer el changelog completo en GitHub.
Junto con este lanzamiento de Babel, publicamos la primera versión experimental de nuestra nueva arquitectura de compatibilidad para polyfills (ver más abajo), ¡gracias a Nicolò y miembros increíbles de la comunidad! Iniciamos discusiones sobre esto hace más de un año en un issue RFC dentro del repositorio de Babel.
Como nota adicional, ahora tenemos un proceso RFC oficial para discutir cambios que impacten significativamente a nuestros usuarios: ¡consúltalo en el repositorio babel/rfcs! Además, hemos habilitado Discusiones en GitHub en nuestro repositorio si tienes comentarios o preguntas.
Si tú o tu empresa quieren apoyar a Babel y la evolución de JavaScript, pero no están seguros de cómo hacerlo, pueden donar a través de nuestro Open Collective y, mejor aún, ¡colaborar directamente con nosotros en la implementación de nuevas propuestas de ECMAScript! Como proyecto impulsado por voluntarios, dependemos del apoyo de la comunidad para financiar nuestros esfuerzos en atender a la amplia variedad de usuarios de JavaScript. Contáctenos en team@babeljs.io si desean discutir más opciones.
Nuevas funcionalidades habilitadas por defecto
Soporte de parser para import.meta
Ahora que ha alcanzado la Etapa 4, el parseo de import.meta está habilitado por defecto, gracias a Kiko. Ten en cuenta que @babel/preset-env no tiene soporte predeterminado para transformarlo, porque el contenido de ese objeto depende del motor y no está definido en la especificación ECMAScript.
console.log(import.meta); // { url: "file:///home/user/my-module.js" }
Transforming ​u{...}-style Unicode escapes (#11377)
¡También descubrimos que no teníamos soporte para compilar una característica de ECMAScript de hace 5 años: las secuencias de escape Unicode estilo \u{...}! Gracias a Justin, @babel/preset-env ahora puede compilarlas en cadenas e identificadores por defecto.
var \u{1d49c} = "\u{Babe1}";
console.log(\u{1d49c});
var _ud835_udc9c = "\uDAAA\uDFE1";
console.log(_ud835_udc9c);
Campos de Clase y Métodos Privados en la opción shippedProposals de @babel/preset-env (#11451)
Finalmente, gracias a Jùnliàng hemos añadido @babel/plugin-proposal-class-properties y @babel/plugin-proposal-private-methods a la opción shippedProposals de @babel/preset-env. Estas propuestas aún no son Stage 4 (es decir, parte del estándar ECMAScript), pero ya están habilitadas por defecto en muchos motores JavaScript.
Si no estás familiarizado:
class Bork {
// Public Fields
instanceProperty = "bork";
static staticProperty = "babelIsCool";
// Private Fields
#xValue = 0;
a() {
this.#xValue++;
}
// Private methods
get #x() { return this.#xValue; }
set #x(value) {
this.#xValue = value;
}
#clicked() {
this.#x++;
}
}
Si te lo perdiste en la versión anterior, en la 7.9 añadimos una nueva opción: "bugfixes": true que puede reducir significativamente el tamaño de tu código generado.
{
"presets": [
["@babel/preset-env", {
"targets": { "esmodules": true }, // Use the targets that you was already using
"bugfixes": true // will be default in Babel 8
}]
]
}
Mejoras ergonómicas en el encadenamiento opcional ?. (#10961, #11248)
En TypeScript 3.9, se modificó la interacción entre las aserciones de no nulidad (postfijo !) y el encadenamiento opcional para hacerla más útil.
foo?.bar!.baz
En TypeScript 3.8 y Babel 7.9, el código anterior se interpretaba como (foo?.bar)!.baz: "Si foo no es nulo, obtén .bar de él. Luego confía en que foo?.bar nunca es nulo y siempre obtén .bar de ello". Esto significa que cuando foo era nulo, el código siempre lanzaba un error porque intentábamos acceder a .baz desde undefined.
En TypeScript 3.9 y Babel 7.10, el código se comporta similar a foo?.bar.baz: "Si foo no es nulo, obtén .bar.baz de él y confía en que foo?.bar no es nulo". ¡Gracias a Bruno por ayudar a implementar esto!
Adicionalmente, la propuesta de campos de clase añadió recientemente soporte para mezclar el encadenamiento opcional ?. con campos privados. Esto significa que el siguiente código ahora es válido:
obj?.property.#priv;
obj?.#priv;
Nota que en el segundo ejemplo, si obj no es nulo pero no tiene el campo #priv, igualmente lanzará un error (exactamente como lo haría obj.#priv). ¡Puedes leer la siguiente sección para ver cómo evitarlo!
Campos privados en in (#11372)
class Person {
#name;
hug(other) {
if (#name in other) console.log(`${this.#name} 🤗 ${other.#name}`);
else console.log("It's not a person!")
}
}
Esta propuesta en Stage 1 permite verificar estáticamente si un objeto dado tiene un campo privado específico.
Los campos privados tienen una "verificación de marca" integrada: si intentas acceder a ellos en un objeto donde no están definidos, lanzarán una excepción. Puedes determinar si un objeto tiene un campo privado particular usando este comportamiento con un bloque try/catch, pero esta propuesta nos brinda una sintaxis más compacta y robusta para hacerlo.
Puedes leer más sobre esto en la descripción de la propuesta y probarla instalando el plugin @babel/plugin-proposal-private-property-in-object y añadiéndolo a tu configuración de Babel. ¡Gracias a Justin por la PR!
Soporte del parser para Atributos de Módulo (#10962)
La propuesta Atributos de Módulo (Etapa 1) permite proporcionar al motor, cargador de módulos o bundler información adicional sobre el archivo importado. Por ejemplo, se puede especificar explícitamente que debe parsearse como JSON:
import metadata from "./package.json" with type: "json";
También se pueden usar con import() dinámico. ¡Observe el soporte para comas finales para facilitar añadir o eliminar el segundo parámetro!
const metadata = await import(
"./package.json",
{ with: { type: "json" } },
);
Gracias a Vivek, Babel ahora soporta parsear estos atributos: puedes añadir el plugin @babel/plugin-syntax-module-attributes a tu configuración de Babel o, si usas @babel/parser directamente, habilitar el plugin moduleAttributes. Actualmente solo aceptamos el atributo type, pero podríamos relajar esta restricción en el futuro dependiendo de cómo evolucione la propuesta.
Babel no transforma estos atributos, y deben manejarse directamente por tu bundler o un plugin personalizado. Actualmente los transformadores de módulos de Babel ignoran estos atributos. Estamos discutiendo si deberíamos propagarlos en el futuro.
Mejor tree-shaking para componentes React (#11428)
React expone muchas funciones puras usadas para anotar o envolver elementos, como React.forwardRef, React.memo o React.lazy. Sin embargo, minificadores y bundlers no saben que estas funciones son puras y no pueden eliminarlas.
Gracias a Devon del equipo de Parcel, @babel/preset-react ahora inyecta anotaciones /*#__PURE__*/ en esas llamadas para marcarlas como seguras para tree-shaking. Anteriormente solo hacíamos esto con JSX mismo (<a></a> => /*#__PURE__*/React.createElement("a", null)).
import React from 'react';
const SomeComponent = React.lazy(() => import('./SomeComponent'));
import React from 'react';
const SomeComponent = /*#__PURE__*/React.lazy(() => import('./SomeComponent'));
Nueva arquitectura experimental de polyfills (#10008, babel-polyfills)
En los últimos tres años, @babel/preset-env ha ayudado a los usuarios a reducir el tamaño de los bundles transpilando solo las características de sintaxis e incluyendo los polyfills de core-js necesarios para sus entornos objetivo.
Actualmente Babel tiene tres formas diferentes de inyectar polyfills de core-js:
-
Usando
useBuiltIns: "entry"en@babel/preset-env, que inyecta polyfills para toda funcionalidad ECMAScript no soportada nativamente en los navegadores objetivo; -
Con
useBuiltIns: "usage", Babel solo inyecta polyfills para características ECMAScript no soportadas solo si se usan realmente en el código fuente; -
Mediante
@babel/plugin-transform-runtime, Babel inyecta ponyfills (que son "puros" y no contaminan el ámbito global) para cada característica ECMAScript usada soportada porcore-js. Esto se usa normalmente por autores de librerías.
Nuestra posición en el ecosistema JavaScript nos permite llevar estas optimizaciones más allá. @babel/plugin-transform-runtime tiene grandes ventajas sobre useBuiltIns para algunos usuarios, pero no considera entornos objetivo: estamos en 2020 y probablemente muy pocos necesitan cargar un polyfill para Array.prototype.forEach.
Además, ¿por qué limitar la capacidad de inyectar automáticamente solo los polyfills necesarios a core-js? También existen polyfills para DOM, Intl y multitud de otras APIs de la plataforma web. No todo el mundo quiere usar core-js; hay muchas alternativas válidas de polyfills para ECMAScript con diferentes compensaciones (por ejemplo, tamaño del código versus cumplimiento de especificaciones), y los usuarios deberían poder elegir el polyfill que prefieran. Por ejemplo, estamos trabajando activamente en una integración con es-shims.
¿Y si la lógica para inyectarlos no estuviera vinculada a los datos reales sobre los polyfills disponibles o requeridos, permitiendo así su uso y desarrollo independiente?
Estamos lanzando la primera versión experimental de cuatro nuevos paquetes:
-
babel-plugin-polyfill-corejs2(heredado)
Estos paquetes incluyen una opción method para ajustar cómo se inyectan (similar a lo que ofrecen actualmente @babel/preset-env y @babel/plugin-transform-runtime). Puedes inyectar un polyfill en un punto de entrada (solo ámbito global) o mediante uso directo en tu código (opciones de ámbito global y "puro"). Abajo hay un CodeSandbox personalizado donde puedes probar las diferencias entre las opciones de polyfills.
También lanzamos @babel/helper-define-polyfill-provider: un nuevo paquete auxiliar que permite a autores y usuarios de polyfills definir sus propios plugins proveedores de polyfills.
¡Un gran agradecimiento a Jordan por colaborar con Nicolò para hacer posible el plugin de es-shims!
Si quieres saber más sobre estos paquetes y aprender cómo configurarlos, consulta el README del proyecto.
Estos paquetes siguen siendo experimentales. Agradecemos comentarios en Twitter o GitHub, pero aún no están listos para producción. Por ejemplo, aún necesitamos conectar algunos polyfills y no los hemos probado en aplicaciones productivas.
