7.9.0 Rilasciato: Output più compatto per preset-env, supporto TypeScript 3.8 e nuova trasformazione JSX
Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Mentre prepariamo il rilascio di Babel 8.0.0 nei prossimi mesi, abbiamo appena completato una nuova release minore che include aggiornamenti relativi a @babel/preset-env, TypeScript 3.8, Flow e JSX!
Qualche mese fa, Jason Miller ha iniziato a lavorare a @babel/preset-modules: un esperimento per ridurre drasticamente le dimensioni dei bundle quando si utilizza il pattern module/nomodule. Siamo lieti di annunciare che questa funzionalità è stata integrata in @babel/preset-env! Ciò significa che le sue ottimizzazioni possono essere applicate a tutti i valori target di preset-env senza bisogno di un preset separato.
Nota: Queste ottimizzazioni saranno abilitate di default in Babel 8. Possono essere attivate manualmente in Babel 7.9 passando l'opzione { bugfixes: true } a preset-env.
Questa release include inoltre pieno supporto per TypeScript 3.8, che introduce import/export espliciti per tipi (es. export type { foo }), e per Flow 0.120, che aggiunge il modificatore declare per i campi classe (es. class C { declare foo: string }).
Abbiamo anche collaborato con il team React per fornire una nuova trasformazione JSX, che consentirà a React e librerie simili di ottimizzare ulteriormente la creazione degli elementi JSX tramite la funzione jsx invece di React.createElement.
Infine, @babel/parser supporta ora un'ulteriore proposta ECMAScript: Record & Tuple. Si noti che si tratta esclusivamente di supporto nel parser, mentre le trasformazioni sono ancora in fase di sviluppo.
È possibile consultare l'intero changelog su GitHub.
Un ringraziamento speciale a Luna Ruan del React Team (Facebook) per aver contribuito alla nuova trasformazione JSX, e a Rick Button (Bloomberg) che ha implementato il supporto nel parser per la proposta Record & Tuple!
Se tu o la tua azienda volete supportare Babel e l'evoluzione di JavaScript, potete donare sul nostro Open Collective o, meglio ancora, collaborare direttamente all'implementazione di nuove proposte ECMAScript! Come progetto guidato da volontari, dipendiamo dal supporto della comunità per finanziare il nostro lavoro a beneficio degli utenti JavaScript. Contattateci a team@babeljs.io per discutere!
L'opzione bugfixes di @babel/preset-env (#11083)
La nuova opzione bugfixes in @babel/preset-env rappresenta l'evoluzione diretta dell'utilizzo di @babel/preset-modules.
Se desideri maggiori dettagli sui problemi che questa modifica aiuta a risolvere, ti suggeriamo di ascoltare (o leggere) i recenti episodi del podcast con Jason: #2 Modern JavaScript and the Future of preset-env e #3 Compiling Your Dependencies.
Fino ad ora, @babel/preset-env (e in generale i plugin di Babel) raggruppavano le funzionalità sintattiche di ECMAScript in collezioni di funzionalità minori strettamente correlate. Questi gruppi possono essere ampi e includere molti casi limite. Ad esempio, il gruppo "parametri di funzione" include parametri destrutturati, predefiniti e rest.
Sulla base di queste informazioni di raggruppamento, Babilone abilita o disabilita ogni gruppo in base al target di supporto del browser specificato nell'opzione targets di @babel/preset-env.
Ecco il problema: se qualsiasi versione di qualsiasi browser in quell'elenco contiene un bug attivato dalla sintassi moderna, l'unica soluzione (che abbiamo considerato all'epoca) era abilitare il corrispondente gruppo di trasformazione che risolveva quel bug.
Nel tempo sono stati scoperti e segnalati più bug nei nostri issue, il che ha causato un output di preset-env più verboso per gestire questi casi limite. Nel peggiore dei casi, l'output era identico alla semplice compilazione completa in ES5, proprio ciò che preset-env era stato creato per evitare.
Quando l'opzione bugfixes: true è abilitata, @babel/preset-env adotta un approccio diverso: transpila la sintassi difettosa nella sintassi moderna più vicina e non difettosa.
Esempio: tutte le nuove funzionalità sintattiche relative ai parametri delle funzioni sono raggruppate nello stesso plugin Babel (@babel/plugin-transform-function-parameters). Quando si targetta edge 16, esiste un bug relativo all'analisi dei parametri destrutturati shorthand con valori predefiniti all'interno delle funzioni freccia:
// 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 }) => {};
Ciò significa che se forniamo a @babel/preset-env questo input con target Edge 16:
const foo = ({ a = 1 }, b = 2, ...args) => [a, b, args];
Viene trasformato in parametri simili a ES5:
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];
};
Tuttavia, se abilitiamo l'opzione bugfixes, viene trasformata solo la sintassi difettosa:
const foo = ({ a: a = 1 }, b = 2, ...args) => [a, b, args];
Puoi vedere questo esempio in azione nel nostro REPL
Puoi abilitare questa opzione oggi aggiungendola a @babel/preset-env nella tua configurazione:
{
"presets": [
["@babel/preset-env", {
"targets": { "esmodules": true }, // Use the targets that you was already using
"bugfixes": true
}]
]
}
Attualmente, l'opzione bugfixes offre i migliori risultati quando si utilizza il target esmodules: true, che consente di targettare browser con supporto nativo ai moduli ES e utilizzare il pattern module/nomodule. Ci auguriamo di continuare a migliorarla nelle prossime release e di abilitarla di default in Babel 8.
Andando avanti, vorremmo collaborare con la community (inclusi i browser) per garantire che questo approccio funzioni senza intoppi durante l'evoluzione di JavaScript. Nello scenario ideale, Babel potrebbe implementare e contribuire a influenzare il futuro delle nuove proposte man mano che vengono presentate e affinate, risolvendo questi casi limite per gli standard esistenti affinché l'output compilato sia minimo possibile per tutti gli utenti di JavaScript in base ai loro target.
TypeScript 3.8: import ed export solo per i tipi (#11171)
Ora puoi esplicitamente contrassegnare import ed export come type-only, analogamente a quanto già possibile in Flow:
import type { SomeThing } from "./some-module.js";
export type { SomeThing };
In questo modo, Babel può determinare in modo sicuro quali import o export sono utilizzati per i tipi e quali per i valori.
Poiché Babel non analizza i tipi e lavora su base per-file (simile all'opzione --isolatedModules di TypeScript), finora @babel/plugin-transform-typescript gestiva gli import non utilizzati come valori come se fossero type-only.
A partire da Babel 7.9 puoi utilizzare il nuovo modificatore type senza alcuna modifica di configurazione.
Raccomandiamo di configurare @babel/preset-typescript o @babel/plugin-transform-typescript in modo che consideri gli import come type-only solo quando è presente la keyword esplicita type, simile all'opzione --importsNotUsedAsValues preserve di TypeScript:
{
"presets": [
["@babel/preset-typescript", {
"onlyRemoveTypeImports": true
}]
]
}
Queste funzionalità sono state sviluppate dal team di Babel insieme a Siddhant N Trivedi. Se sei interessato a vedere come è stato realizzato, guarda il nostro workflow su YouTube!
Campi declare in Flow (#11178)
La proposta dei class fields specifica che i campi non inizializzati sono impostati su undefined: questo comportamento differisce dall'implementazione attuale di Babel con Flow, che invece li ignora completamente.
Per questo motivo, il team di Flow ha aggiunto il supporto per il modificatore declare nei campi delle classi:
class Foo {
x: ?string; // A "real" field
declare y: number; // A type-only field
}
Nell'esempio sopra, solo y verrà completamente rimosso da Babel.
Per evitare breaking changes, abbiamo introdotto il supporto per declare nei class fields dietro un flag: "allowDeclareFields", supportato sia da @babel/plugin-transform-flow che da @babel/preset-flow. Questo diventerà il comportamento predefinito in Babel 8, quindi ti consigliamo di migrare la tua configurazione per utilizzarlo:
{
"presets": [
["@babel/preset-flow", {
"allowDeclareFields": true
}]
]
}
Una nuova trasformazione JSX (#11154)
Il team di React ha creato un RFC nel febbraio dello scorso anno per semplificare la creazione degli elementi.
In una futura release stabile, React supporterà un nuovo gruppo di funzioni per creare elementi JSX come alternativa alla funzione generica legacy React.createElement. Ciò consentirà ottimizzazioni più avanzate in futuro.
Sebbene non sia ancora disponibile in una release stabile, puoi provarlo sul canale sperimentale di React:
npm install react@experimental react-dom@experimental
Abbiamo collaborato con il team per implementare una nuova trasformazione che supporta la compilazione di JSX verso queste nuove funzioni. Inoltre importa automaticamente "react" (o altre librerie compatibili con la nuova API) quando necessario, eliminando la necessità di includerlo manualmente.
Ad esempio, questo input:
function Foo() {
return <div />;
}
verrebbe trasformato in:
import { jsx as _jsx } from "react/jsx-runtime";
function Foo() {
return _jsx("div", ...);
}
Nota: Le funzioni all'interno di
react/jsx-runtimeereact/jsx-dev-runtimenon sono destinate all'uso esterno al di fuori dei plugin@babel/plugin-transform-react-jsxe@babel/plugin-transform-react-jsx-development.
In sintesi (consultare l'RFC per maggiori dettagli), la trasformazione:
-
Passa sempre i children come props.
-
Passa
keyseparatamente dalle altre props. -
In DEV,
- Passare un flag che determina se era statico o meno.
- Passare
__sourcee__selfseparatamente dalle altre props.
Utilizzo: È possibile abilitare questa nuova trasformazione passando { "runtime": "automatic" } (anziché "classic") a @babel/preset-react (o @babel/plugin-transform-react-jsx):
{
"presets": [
["@babel/preset-react", {
"runtime": "automatic"
}]
]
}
A partire da Babel 8, "automatic" sarà il runtime predefinito.
È anche possibile abilitare la modalità sviluppo per questa nuova trasformazione utilizzando il nuovo plugin @babel/plugin-transform-react-jsx-development o passando { "development": true, "runtime": "automatic" } a @babel/preset-react.
Puoi approfondire questa nuova trasformazione nella documentazione.