Vai al contenuto principale

7.10.0 Rilasciato: Class Fields in preset-env, controlli '#private in' e migliore tree-shaking per React

· Lettura di 11 min
Traduzione Beta Non Ufficiale

Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →

Abbiamo appena rilasciato una nuova versione minore di Babel!

Questa versione 7.10 include:

  • Supporto completo per la nuova proposta Stage 1, controlli #prop in obj per campi privati proposta.

  • @babel/preset-env ora compila le sequenze di escape Unicode in stile ES2015 (\u{Babe1}) nella sintassi legacy equivalente (\uDAAA\uDFE1).

  • Due miglioramenti per l'operatore Optional Chaining (?.)

  • Supporto del parser per la nuova proposta Stage 1 Module Attributes (import a from "./a.json" with type: "json").

  • Miglior supporto per il tree-shaking nel codice React (ad esempio React.memo)!

  • Configurazione del repository RFCs e delle pagine GitHub Discussions!

Puoi leggere l'intero changelog su GitHub.

In concomitanza con questa versione di Babel, rilasciamo la prima versione sperimentale della nostra nuova architettura di compatibilità per polyfill (vedi sotto per dettagli), grazie a Nicolò e ad altri fantastici membri della comunità! Le discussioni su questo tema sono iniziate oltre un anno fa in una RFC issue nel repository Babel.

Inoltre, abbiamo ora un processo RFC ufficiale per discutere modifiche con impatto significativo sugli utenti: consultalo nel repository babel/rfcs! Abbiamo anche abilitato le GitHub Discussions sul nostro repository per feedback e domande!

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!

Nuove funzionalità abilitate di default

Parsing per import.meta

Ora che ha raggiunto lo Stage 4, il parsing per import.meta è abilitato di default, grazie a Kiko. Nota che @babel/preset-env non supporta di default la sua trasformazione, poiché il contenuto di questo oggetto è gestito dal motore e non definito nelle specifiche ECMAScript.

JavaScript
console.log(import.meta); // { url: "file:///home/user/my-module.js" }

Transforming ​u{...}-style Unicode escapes (#11377)

Abbiamo anche scoperto che mancava il supporto per una funzionalità ECMAScript di 5 anni fa: le sequenze di escape Unicode nello stile \u{...}! Grazie a Justin, @babel/preset-env ora le compila in stringhe e identificatori per impostazione predefinita.

Esempio su CodeSandbox

JavaScript
var \u{1d49c} = "\u{Babe1}";
console.log(\u{1d49c});
JavaScript
var _ud835_udc9c = "\uDAAA\uDFE1";
console.log(_ud835_udc9c);

Proprietà di classe e metodi privati nell'opzione shippedProposals di @babel/preset-env (#11451)

Infine, grazie a Jùnliàng abbiamo aggiunto @babel/plugin-proposal-class-properties e @babel/plugin-proposal-private-methods all'opzione shippedProposals di @babel/preset-env. Queste proposte non hanno ancora raggiunto lo Stage 4 (ovvero non fanno parte dello standard ECMAScript), ma sono già abilitate di default in molti motori JavaScript.

Se non le conosci:

JavaScript
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++;
}
}

Se ti è sfuggito nella scorsa release, nella 7.9 abbiamo aggiunto una nuova opzione: "bugfixes": true che può ridurre significativamente l'output del tuo codice.

JavaScript
{
"presets": [
["@babel/preset-env", {
"targets": { "esmodules": true }, // Use the targets that you was already using
"bugfixes": true // will be default in Babel 8
}]
]
}

Miglioramenti ergonomici per l'optional chaining ?. (#10961, #11248)

In TypeScript 3.9, l'interazione tra le asserzioni di non-null (postfisso !) e l'optional chaining è stata modificata per renderla più utile.

foo?.bar!.baz

In TypeScript 3.8 e Babel 7.9, il codice sopra sarebbe interpretato come (foo?.bar)!.baz: "Se foo non è nullish, ottieni .bar da esso. Poi considera che foo?.bar non è mai nullish e ottieni sempre .bar da esso". Ciò significa che quando foo è nullish quel codice genererebbe sempre un errore, perché cerchiamo di ottenere .baz da undefined.

In TypeScript 3.9 e Babel 7.10, il codice si comporta in modo simile a foo?.bar.baz: "Se foo non è nullish, ottieni .bar.baz da esso e considera che foo?.bar non è nullish". Grazie a Bruno per aver contribuito all'implementazione!


Inoltre, la proposta per i class fields ha aggiunto di recente il supporto per combinare l'optional chaining ?. con i campi privati. Ciò significa che il seguente codice è ora valido:

JavaScript
obj?.property.#priv;
obj?.#priv;

Nota che nel secondo esempio, se obj non è nullish ma non ha il campo #priv, genererebbe comunque un errore (esattamente come farebbe obj.#priv). Puoi leggere la prossima sezione per vedere come evitarlo!

Campi privati con in (#11372)

Esempio su CodeSandbox

JavaScript
class Person {
#name;

hug(other) {
if (#name in other) console.log(`${this.#name} 🤗 ${other.#name}`);
else console.log("It's not a person!")
}
}

Questa proposta di Stage 1 consente di verificare staticamente se un determinato oggetto contiene un campo privato specifico.

I campi privati hanno un "brand check" integrato: se provi ad accedervi in un oggetto dove non sono definiti, generano un'eccezione. Puoi determinare se un oggetto ha un campo privato specifico sfruttando questo comportamento con un'istruzione try/catch, ma questa proposta ci offre una sintassi più compatta e robusta per farlo.

Puoi approfondire nella descrizione della proposta e testarla installando il plugin @babel/plugin-proposal-private-property-in-object aggiungendolo alla tua configurazione Babel. Grazie a Justin per la PR!

Supporto al parser per gli attributi dei moduli (#10962)

La proposta sugli Attributi dei Moduli (Stage 1) consente di fornire a motori, loader di moduli o bundler informazioni aggiuntive sui file importati. Ad esempio, puoi specificare esplicitamente che un file dovrebbe essere interpretato come JSON:

JavaScript
import metadata from "./package.json" with type: "json";

Possono inoltre essere utilizzati con import() dinamico. Nota il supporto per le virgole finali per semplificare l'aggiunta/rimozione del secondo parametro!

JavaScript
const metadata = await import(
"./package.json",
{ with: { type: "json" } },
);

Grazie a Vivek, Babel supporta ora l'analisi di questi attributi: puoi aggiungere il plugin @babel/plugin-syntax-module-attributes alla tua configurazione Babel o, se usi direttamente @babel/parser, abilitare il plugin moduleAttributes. Attualmente accettiamo solo l'attributo type, ma potremmo allentare questa restrizione in futuro in base all'evoluzione della proposta.

informazioni

Babel non trasforma questi attributi, che dovrebbero essere gestiti dal tuo bundler o da un plugin personalizzato. Gli attuali trasformatori di moduli di Babel ignorano questi attributi. Stiamo discutendo se dovremmo propagarli in futuro.

Miglior tree-shaking per componenti React (#11428)

React espone numerose funzioni pure per annotare o avvolgere elementi, come React.forwardRef, React.memo o React.lazy. Tuttavia minificatori e bundler non riconoscono che queste funzioni sono pure e non possono rimuoverle.

Grazie a Devon del team Parcel, @babel/preset-react inserisce ora annotazioni /*#__PURE__*/ nelle chiamate di queste funzioni per segnalare che sono eliminabili via tree-shaking. Precedentemente lo facevamo solo col JSX stesso (<a></a> => /*#__PURE__*/React.createElement("a", null))

JavaScript
import React from 'react';
const SomeComponent = React.lazy(() => import('./SomeComponent'));
JavaScript
import React from 'react';
const SomeComponent = /*#__PURE__*/React.lazy(() => import('./SomeComponent'));

Nuova architettura sperimentale per polyfill (#10008, babel-polyfills)

Negli ultimi tre anni, @babel/preset-env ha aiutato gli utenti a ridurre le dimensioni dei bundle traspilando solo le funzionalità sintattiche e includendo i polyfill core-js necessari per i loro ambienti target. Attualmente Babel offre tre approcci per iniettare polyfill core-js nel codice sorgente:

  • Con useBuiltIns: "entry" in @babel/preset-env, si iniettano polyfill per ogni funzionalità ECMAScript non supportata nativamente dai browser target;

  • Con useBuiltIns: "usage", Babel inietta polyfill solo per le funzionalità ECMAScript non supportate effettivamente utilizzate nel codice sorgente;

  • Con @babel/plugin-transform-runtime, Babel inietta ponyfills (di tipo "puro" che non inquinano lo scope globale) per ogni funzionalità ECMAScript utilizzata supportata da core-js. Solitamente usato dagli autori di librerie.

La nostra posizione nell'ecosistema JavaScript ci permette di spingere ulteriormente queste ottimizzazioni. @babel/plugin-transform-runtime offre vantaggi significativi rispetto a useBuiltIns per alcuni utenti, ma non considera gli ambienti target: siamo nel 2020 e probabilmente pochissime persone hanno bisogno di caricare un polyfill per Array.prototype.forEach.

Inoltre, perché dovremmo limitare l'iniezione automatica dei soli polyfill necessari a core-js? Esistono anche polyfill per DOM, Intl e una miriade di altre API della piattaforma web. Non tutti vogliono usare core-js; ci sono molti altri polyfill ECMAScript validi con diversi compromessi (es. dimensioni del codice vs conformità alle specifiche), e gli utenti dovrebbero poter scegliere il polyfill preferito. Ad esempio, stiamo lavorando attivamente all'integrazione con es-shims.

E se la logica per iniettarli fosse indipendente dai dati effettivi sui polyfill disponibili o necessari, così da poterli usare e sviluppare autonomamente?

Stiamo rilasciando la prima versione sperimentale di quattro nuovi pacchetti:

Questi pacchetti supportano tutti un'opzione method per regolare la modalità di iniezione (analoga a quanto offerto attualmente da @babel/preset-env e @babel/plugin-transform-runtime). È possibile iniettare un polyfill in un entry point (solo scope globale) o tramite uso diretto nel codice (opzioni "global scope" e "pure"). Qui sotto trovate un CodeSandbox personalizzato per testare le differenze tra le opzioni di polyfill.

image

Stiamo rilasciando anche @babel/helper-define-polyfill-provider: un nuovo pacchetto helper che permette agli autori e utenti di polyfill di definire i propri plugin provider.

Un enorme ringraziamento a Jordan per la collaborazione con Nicolò che ha reso possibile costruire il plugin per es-shims!

consiglio

Per approfondimenti su questi pacchetti e le istruzioni di configurazione, consultate il README del progetto.

attenzione

Questi pacchetti sono ancora sperimentali. Apprezziamo feedback su Twitter o GitHub, ma non sono ancora pronti per la produzione. Ad esempio, mancano alcuni polyfill da integrare e non li abbiamo testati in applicazioni reali.