Saltar al contenido principal

7.9.0 Publicada: Menor tamaño de salida en preset-env, soporte para TypeScript 3.8 y nueva transformación JSX

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

Mientras preparamos el lanzamiento de Babel 8.0.0 (en los próximos meses), acabamos de finalizar una nueva versión menor que incluye actualizaciones relacionadas con @babel/preset-env, TypeScript 3.8, Flow y JSX!

Hace unos meses, Jason Miller comenzó a trabajar en @babel/preset-modules: un experimento para reducir significativamente el tamaño de los bundles al usar el patrón module/nomodule. ¡Nos complace anunciar que su funcionalidad se ha integrado en @babel/preset-env! Esto significa que sus optimizaciones pueden aplicarse a todos los valores de destino de preset-env, sin necesidad de un preset adicional.

Nota: Estas optimizaciones estarán habilitadas por defecto en Babel 8. Pueden activarse manualmente en Babel 7.9 pasando la opción { bugfixes: true } a preset-env.

Esta versión también incluye soporte completo para TypeScript 3.8, que introdujo importaciones y exportaciones explícitas de solo tipo (ej. export type { foo }), y para Flow 0.120, que añadió el modificador declare para campos de clase (ej. class C { declare foo: string }).

También colaboramos con el equipo de React para proporcionar una nueva transformación JSX, que permitirá a React y bibliotecas similares optimizar aún más la creación de elementos JSX mediante la función jsx en lugar de React.createElement.

Finalmente, @babel/parser ahora soporta una propuesta adicional de ECMAScript: Record & Tuple. Ten en cuenta que esto es solo soporte en el parser, y las transformaciones aún están en desarrollo.

Puedes leer el changelog completo en GitHub.


Un agradecimiento especial a Luna Ruan del equipo de React (Facebook) por contribuir con la nueva transformación JSX, y a Rick Button (Bloomberg) quien implementó el soporte en el parser para la propuesta Record & Tuple!

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.

La opción bugfixes de @babel/preset-env (#11083)

La nueva opción bugfixes en @babel/preset-env reemplaza directamente el uso de @babel/preset-modules.

Si deseas más contexto sobre los problemas que ayuda a resolver este cambio, te sugerimos escuchar (o leer) los episodios recientes del podcast con Jason: #2 Modern JavaScript and the Future of preset-env y #3 Compiling Your Dependencies.

Hasta ahora, @babel/preset-env (y los plugins de Babel en general) agrupaban las características de sintaxis de ECMAScript en colecciones de características menores estrechamente relacionadas. Estos grupos pueden ser grandes e incluir muchos casos particulares. Por ejemplo, el grupo y plugin de "argumentos de función" incluye parámetros desestructurados, valores por defecto y parámetros rest.

A partir de esta información de agrupación, Babilonia habilita o deshabilita cada grupo según el destino de compatibilidad del navegador que especifiques en la opción targets de @babel/preset-env.

Este es el problema: si cualquier versión de cualquier navegador en esa lista contiene un error desencadenado por sintaxis moderna, la única solución (que consideramos en su momento) era habilitar el grupo de transformación correspondiente que soluciona ese error.

Con el tiempo, se descubrieron y reportaron más errores en nuestros issues, lo que hizo que preset-env generara más código debido a estos casos particulares. En el peor de los casos, la salida era la misma que compilar todo a ES5, algo que preset-env fue creado para ayudar a evitar.

Cuando la opción bugfixes: true está habilitada, @babel/preset-env adopta un enfoque diferente: transpila la sintaxis defectuosa a la sintaxis moderna no defectuosa más cercana.

Por ejemplo: todas las nuevas características de sintaxis relacionadas con parámetros de función se agrupan en el mismo plugin de Babel (@babel/plugin-transform-function-parameters). Al apuntar a edge 16, existe un error relacionado con el análisis de parámetros desestructurados abreviados con valores predeterminados dentro de funciones flecha:

JavaScript
// this breaks in Edge 16:
const foo = ({ a = 1 }) => {};

// .. but this doesn't:
function foo({ a = 1, b }, ...args) {}

// ... and neither does this:
const foo = ({ a: a = 1 }) => {};

Esto significa que si le damos a @babel/preset-env esta entrada y apuntamos a Edge 16:

JavaScript
const foo = ({ a = 1 }, b = 2, ...args) => [a, b, args];

Lo transforma a parámetros similares a ES5:

JavaScript
const foo = function foo(_ref, b) {
let { a = 1 } = _ref;

if (b === void 0) { b = 2; }

for (
var _len = arguments.length,
args = new Array(_len > 2 ? _len - 2 : 0),
_key = 2; _key < _len; _key++
) {
args[_key - 2] = arguments[_key];
}

return [a, b, args];
};

Sin embargo, si habilitamos la opción bugfixes, solo transforma la sintaxis defectuosa:

JavaScript
const foo = ({ a: a = 1 }, b = 2, ...args) => [a, b, args];

Puedes ver este ejemplo en acción en nuestro REPL

Puedes habilitar esta opción hoy agregándola a @babel/preset-env en tu configuración:

{
"presets": [
["@babel/preset-env", {
"targets": { "esmodules": true }, // Use the targets that you was already using
"bugfixes": true
}]
]
}
consejo

Actualmente, la opción bugfixes ofrece los mejores resultados al usar el destino esmodules: true, que te permite apuntar a navegadores con soporte nativo para módulos ES y utilizar el patrón module/nomodule. Esperamos seguir mejorándola en las próximas versiones y habilitarla por defecto en Babel 8.

De cara al futuro, nos gustaría trabajar con la comunidad (incluyendo navegadores) para permitir que este tipo de enfoque funcione sin problemas mientras continuamos en la transición del desarrollo de JavaScript. En el escenario ideal, Babel podría implementar e influir en el futuro de nuevas propuestas a medida que se sugieren y refinan, y suavizar estos casos particulares para estándares existentes, de modo que la salida compilada mínima sea posible para todos los usuarios de JavaScript según sus destinos.

TypeScript 3.8: importaciones y exportaciones de solo tipo (#11171)

Ahora puedes marcar explícitamente importaciones y exportaciones como solo de tipo, similar a lo que ya puedes hacer en Flow:

import type { SomeThing } from "./some-module.js";

export type { SomeThing };

Al hacerlo, Babel puede determinar con seguridad qué importaciones/exportaciones se usan para tipos y cuáles para valores.

Como Babel no analiza tipos y funciona por archivo (similar a la opción --isolatedModules de TypeScript), hasta ahora @babel/plugin-transform-typescript manejaba las importaciones no utilizadas como valores como si fueran solo de tipo.

A partir de Babel 7.9 puedes usar el nuevo modificador type sin ningún cambio de configuración.

Recomendamos configurar @babel/preset-typescript o @babel/plugin-transform-typescript para que solo considere las importaciones como solo de tipo cuando exista la palabra clave explícita type, similar a la opción --importsNotUsedAsValues preserve de TypeScript:

babel.config.json
{
"presets": [
["@babel/preset-typescript", {
"onlyRemoveTypeImports": true
}]
]
}
consejo

¡Estas características fueron aportadas por el equipo de Babel en conjunto y por Siddhant N Trivedi. Si te interesa ver cómo se implementó, ¡mira cómo lo hicimos en YouTube!

Campos declare de Flow (#11178)

La propuesta de campos de clase especifica que los campos no inicializados se establecen en undefined: esto difiere del comportamiento actual de Babel con Flow, que simplemente los ignora.

Por esta razón, el equipo de Flow añadió soporte para el modificador declare en campos de clase:

JavaScript
class Foo {
x: ?string; // A "real" field
declare y: number; // A type-only field
}

En el ejemplo anterior, solo y debería ser eliminado completamente por Babel.

Para evitar cambios disruptivos, introdujimos soporte para declare en campos de clase mediante el flag "allowDeclareFields", soportado tanto por @babel/plugin-transform-flow como por @babel/preset-flow. Esto será el comportamiento predeterminado en Babel 8, por lo que recomendamos migrar tu configuración:

babel.config.json
{
"presets": [
["@babel/preset-flow", {
"allowDeclareFields": true
}]
]
}

Una nueva transformación JSX (#11154)

El equipo de React creó un RFC en febrero del año pasado para simplificar la creación de elementos.

En una futura versión estable, React admitirá nuevas funciones para instanciar elementos JSX como alternativa a la función de propósito general React.createElement. Esto permitirá optimizarlas mejor en el futuro.

consejo

Aunque aún no está disponible en versión estable, puedes probarlo en el canal experimental de React:

Shell
npm install react@experimental react-dom@experimental

Trabajamos con el equipo para completar una nueva transformación que compila JSX hacia estas nuevas funciones. Además importa automáticamente "react" (u otras bibliotecas compatibles) cuando es necesario, eliminando la necesidad de incluirlo manualmente.

Por ejemplo, esta entrada:

JSX
function Foo() {
return <div />;
}

se convertiría en:

JSX
import { jsx as _jsx } from "react/jsx-runtime";
function Foo() {
return _jsx("div", ...);
}

Nota: Las funciones dentro de react/jsx-runtime y react/jsx-dev-runtime no están diseñadas para usarse fuera de los propios plugins @babel/plugin-transform-react-jsx y @babel/plugin-transform-react-jsx-development.

En resumen (y consulta el RFC para más detalles), la transformación:

  • Siempre pasa los hijos como props.

  • Pasa key separado de otras props.

  • En DEV,

    • Pasar una bandera que determine si era estático o no.
    • Pasar __source y __self por separado de otras props.

Uso: Puedes habilitar esta nueva transformación pasando { "runtime": "automatic" } (en lugar de "classic") a @babel/preset-react (o @babel/plugin-transform-react-jsx):

babel.config.json
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}

Y a partir de Babel 8, "automatic" será el runtime predeterminado.

También puedes habilitar el modo de desarrollo para esta nueva transformación usando el nuevo plugin @babel/plugin-transform-react-jsx-development o pasando { "development": true, "runtime": "automatic" } a @babel/preset-react.

Puedes leer más sobre esta nueva transformación en la documentación.