7.4.0 Disponibile: core-js 3, metodi privati statici e applicazione parziale
Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Oggi rilasciamo Babel 7.4.0!
Questa versione include supporto per TypeScript 3.4, la proposta per l'applicazione parziale nelle chiamate di funzione e i metodi privati statici.
Abbiamo aggiunto supporto per espressioni parentesizzate significative in @babel/parser, rendendolo più conforme alle specifiche che mai!
Ultimo ma non meno importante, sia @babel/preset-env che @babel/transform-runtime supportano ora core-js@3, e @babel/template introduce una nuova sintassi interessante!
Potete consultare l'intero changelog su GitHub.
Un ringraziamento speciale a tutti i nuovi contributor di Babel 😊. Da quando abbiamo iniziato a generare i changelog delle release usando GitHub Actions, non abbiamo avuto modo di ringraziarli in ogni versione, ma a partire da Babel 7.3.3 sono state tantissime persone!
-
Babel 7.3.3: @Alec321, @mhcgrq, @ilyalesik, @yifei-fu
-
Babel 7.3.4: @elevatebart, @ian, @imjacobclark, @irohitb
-
Babel 7.4.0: @AmirS, @agoldis, @byara, @echenley, @tanohzana, @matt, @penielse, @pnowak
Molte funzionalità in questa release sono state sviluppate in collaborazione con i nostri sponsor. Bloomberg ha contribuito al supporto per nuovi elementi privati in ogni release a partire dalla 7.0 (7.1, 7.2, 7.3), e ora hanno implementato i metodi privati statici! Restano solo da completare getter e setter privati statici.
Allo stesso modo, Trivago (Base Support Sponsor su OpenCollective) ha realizzato l'implementazione del plugin per l'applicazione parziale.
Nell'ultimo mese abbiamo sperimentato una collaborazione più diretta con aziende su varie funzionalità/ottimizzazioni utili alla community: RunKit ha sponsorizzato Nicolò per implementare il supporto dei placeholder in @babel/template.
Quando si gestisce un grande progetto open source, non tutto è codice: dobbiamo amministrare server, integrazione continua, account social e... tantissime password! Ringraziamo vivamente 1Password per averci incluso nel loro programma di supporto open source e per averci fornito gratuitamente un account 1Password Teams!
Se tu o la tua azienda volete supportare Babel e l'evoluzione di JavaScript ma non sapete come, potete donare su OpenCollective o, meglio ancora, collaborare direttamente con noi all'implementazione delle nuove proposte ECMAScript! Essendo un progetto gestito da volontari, contiamo sul supporto della comunità sia per finanziare il nostro lavoro a beneficio degli sviluppatori JavaScript sia per mantenere la proprietà del codice. Contatta Henry all'indirizzo henry@babeljs.io per approfondire!
core-js 3 (#7646)
Abbiamo ricevuto molti elogi per il nostro lavoro su @babel/preset-env, ma gran parte del merito spetta all'eccezionale lavoro di Denis. È lui che mantiene core-js, la libreria che fornisce tutti i polyfill caricati da @babel/polyfill, @babel/runtime e @babel/preset-env.
core-js@3 è appena stato rilasciato e include numerose nuove funzionalità: le trovate descritte in "core-js@3, babel and a look into the future". Oltre alle nuove proposte, ora è possibile applicare polyfill ai metodi di istanza tramite @babel/plugin-transform-runtime, consentendone l'uso su browser obsoleti senza inquinare l'ambiente globale:
// 'foo' could be either a string or an array, or a custom object
foo.includes("a");
// ⮕
import _includesInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/includes";
_includesInstanceProperty(foo).call(foo, "a");
@babel/preset-env e @babel/plugin-transform-runtime supportano ora il polyfill delle proposte: nella configurazione basta usare corejs: { version: 3, proposals: true } invece di corejs: 3. Ricordate che le proposte ECMAScript sono per natura instabili e potrebbero cambiare in core-js@4!
In precedenza, @babel/preset-env si basava esclusivamente sui dati di compat-table per determinare quali polyfill caricare per un dato ambiente. core-js@3 introduce un proprio dataset di compatibilità con una suite di test esaustiva che garantisce un polyfill molto più accurato!
Migrazione da core-js@2
Poiché le versioni 2 e 3 di core-js sono incompatibili (non vogliamo rompere il vostro codice!), non sono abilitate di default.
-
If you are using
@babel/preset-env, you need to enable thecorejs: 3option:JavaScriptpresets: [
["@babel/preset-env", {
useBuiltIns: "usage", // or "entry"
corejs: 3,
}]
]Don't forget to update your installed version of
core-js!npm install --save core-js@3When using
core-js3, theuseBuiltIns: "entry"option not only transformsimport "core-js"imports, but alsoregenerator-runtime/runtimeand all the nestedcore-jsentry points.For example, when targeting Chrome 72, it will apply this transformation:
Input
JavaScriptimport "core-js/es";
import "core-js/proposals/set-methods";
import "core-js/features/set/map";Output
JavaScriptimport "core-js/modules/es.array.unscopables.flat";
import "core-js/modules/es.array.unscopables.flat-map";
import "core-js/modules/es.object.from-entries";
import "core-js/modules/esnext.set.difference";
import "core-js/modules/esnext.set.intersection";
import "core-js/modules/esnext.set.is-disjoint-from";
import "core-js/modules/esnext.set.is-subset-of";
import "core-js/modules/esnext.set.is-superset-of";
import "core-js/modules/esnext.set.map";
import "core-js/modules/esnext.set.symmetric-difference";
import "core-js/modules/esnext.set.union";Unlike when using
core-js2, it doesn't transform@babel/polyfillimports because when used directly that package loads version 2 ofcore-js. -
Se usate
@babel/plugin-transform-runtime, dovete impostare l'opzionecorejs: 3:JavaScriptplugins: [
["@babel/transform-runtime", {
corejs: 3,
}]
]Potete rimuovere
@babel/runtime-corejs2, ma dovete installare@babel/runtime-corejs3!npm remove @babel/runtime-corejs2
npm install --save @babel/runtime-corejs3 -
@babel/polyfillnon è un plugin né un preset, ma un pacchetto runtime: se aggiungessimo un'opzione per alternare tracore-js@2ecore-js@3, entrambe le versioni dovrebbero essere incluse nel tuo bundle. Per questo motivo, abbiamo deciso di deprecarlo: ora dovresti caricarecore-jsper i polyfill eregenerator-runtime/runtimese stai trasformando generatori:JavaScript// before
import "@babel/polyfill";
// after
import "core-js/stable";
import "regenerator-runtime/runtime";Questo ti dà la possibilità di caricare qualsiasi versione desideri e di aggiornare i due pacchetti indipendentemente.
Se sei interessato, puoi consultare il vecchio sorgente di
@babel/polyfillpercore-js@2: packages/babel-polyfill/src/index.js.
Applicazione Parziale (#9343 e #9474)
Questa release include sia il supporto in @babel/parser che la trasformazione per la proposta di applicazione parziale, attualmente allo Stage 1 (ultima presentazione a luglio 2018). L'implementazione è stata realizzata da Behrang Yarahmadi, sponsorizzato da Trivago.
Questa nuova funzionalità permette di associare alcuni argomenti e il receiver this a una funzione, similmente al metodo Function#bind esistente ma con meno limitazioni.
const half = divide(?, 2); // half = num => divide(num, 3)
half(6); // 3
element.addEventListener(
"click",
// handleEvent will be called with the correct "this".
this.handleEvent("click", ?) // e => this.handleEvent("click", e)
);
È particolarmente utile in combinazione con la proposta dell'operatore pipeline (soprattutto nelle varianti "minimal" o "F-sharp"), poiché evita l'uso eccessivo di funzioni freccia:
let newScore = player.score
|> add(?, 7)
|> clamp(0, 100, ?);
// Without this proposal:
let newScore = player.score
|> (_ => add(_, 7))
|> (_ => clamp(0, 100, _));
Puoi testarla aggiungendo @babel/plugin-proposal-partial-application alla tua configurazione, o abilitando il preset stage 1 nella repl online!
Sebbene la proposta menzioni anche l'applicazione parziale per i tagged template literal, non è stata implementata poiché verrà probabilmente rimossa.
Metodi privati statici (#9446)
class Person {
static #is(obj) {
return obj instanceof Person;
}
constructor(name) {
if (Person.#is(name)) {
throw "It is already a person!";
}
}
}
Un altro ringraziamento a Tim (Bloomberg) per l'implementazione di questa proposta!
Se già utilizzi metodi privati d'istanza, puoi usare questa nuova funzionalità senza configurazione aggiuntiva; altrimenti devi aggiungere @babel/plugin-proposal-private-methods alla lista dei plugin. Nella repl online è abilitata dal preset stage-3.
Il supporto completo alle funzionalità private delle classi è a un passo dal traguardo! 😄
| Class Private | Instance | Static |
|---|---|---|
Fields class A { #a = 1 } | 7.0.0 | 7.1.0 |
Methods class A { #a() {} } | 7.2.0 | 7.4.0 |
Accessors class A { get #a() {} } | 7.3.0 | ✖️ |
Supporto TypeScript 3.4 RC (#9529 e #9534)
TypeScript 3.4 RC è stato rilasciato pochi giorni fa, e grazie a Tan Li Hau è già supportato da Babel!
Sono presenti due nuove funzionalità per le annotazioni di tipo: contesti const, che contrassegnano un oggetto come "congelato in profondità", e il modificatore readonly per array e tuple.
const student = {
name: "Joe Blogs",
marks: [25, 23, 30]
} as const;
const vowels: readonly string[] = ["a", "e", "i", "o", "u"];
Tieni presente che TypeScript 3.4 RC non è una versione stabile, quindi dovresti attendere il rilascio ufficiale di TypeScript 3.4: puoi iscriverti al blog di TypeScript per ricevere una notifica quando sarà disponibile. 🙂
Espressioni tra parentesi (#8025)
Le parentesi solitamente non sono significative per i compilatori JavaScript o i generatori di codice: sono solo "suggerimenti" usati per indicare al parser che alcuni nodi hanno una precedenza diversa da quella predefinita:
| Code | 1 + 2 * 3 / 1 + (2 * 3) | (1 + 2) * 3 |
|---|---|---|
| AST structure | ![]() | ![]() |
Quando l'AST è stato generato, la precedenza delle operazioni è determinata dalla struttura ad albero e non dalle parentesi originali: per questo motivo Babel non le tracciava.
Durante la stampa di un AST, @babel/generator non ha conoscenza della formattazione originale e genera parentesi solo dove necessario.
Ci sono situazioni in cui questo causa problemi agli utenti. Ad esempio, quando si usa Google Closure Compiler, le parentesi sono utilizzate per contrassegnare le espressioni di type casting:
/** @type {!MyType} */ (valueExpression)
Avevamo già un nodo ParenthesizedExpression per rappresentare le parentesi, ma non veniva mai generato da @babel/parser e poteva essere inserito solo tramite plugin personalizzati. Grazie al lavoro di Erik Arvidsson, ora puoi usare l'opzione createParenthesizedExpressions nel parser per tracciarle automaticamente!
| Code | 1 + (2 * 3) | (1 + 2) * 3 |
|---|---|---|
| AST structure | ![]() | ![]() |
Conformità alle specifiche di @babel/parser
Daniel sta rendendo @babel/parser sempre più conforme alle specifiche ECMAScript: ora supera il 98.97% dei test nella suite Test262. 😎
Questa release rende @babel/parser consapevole delle regole di scope di JavaScript: ora riconosce quali variabili sono dichiarate, se ci sono conflitti, se sono hoisted o meno, e se un costrutto sintattico è consentito nel contesto in cui viene trovato.
Tutti questi esempi non validi sono ora correttamente segnalati come errori, evitando la necessità di vietarli manualmente in ogni strumento che utilizza @babel/parser:
let a, a; // Duplicate declaration 💥
if (foo) {
if (bar) { var b }
let b; // Duplicate declaration, again 💥
}
export { Foo }; // Error, Foo is not declared ❓
class C {
constructor() {
super(); // Super in a non-derived class 🤔
}
method(d, d) {} // Duplicate parameter 💥
}
Placeholder nel codice (#9364)
Il codice non è sempre scritto direttamente dagli esseri umani: cosa succede se parte del codice deve essere generato, magari usando un template predefinito?
I file template sono spesso usati per generare codice HTML, sia tramite linguaggi come PHP che motori di template come Handlebars:
<!-- PHP -->
<section>
<h1><?= $title ?></h1>
<main><?= $body ?></main>
</section>
<!-- Handlebars -->
<section>
<h1>{{ title }}</h1>
<main>{{ body }}</main>
</section>
Se hai mai sviluppato un plugin Babel, potresti aver usato @babel/template: un'utility che permette di fare la stessa cosa, ma generando codice JavaScript:
const buildAssign = template`
var NAME = VALUE;
`;
const result = buildAssign({
NAME: varName,
VALUE: varValue,
});
Fino ad ora, @babel/template utilizzava identificatori maiuscoli come "placeholder", che poi dovevano essere sostituiti. Sebbene questo approccio funzionasse bene nella maggior parte dei casi, presentava alcune limitazioni:
-
per impostazione predefinita, ogni identificatore maiuscolo era considerato un placeholder e
@babel/templategenerava un errore se non veniva sostituito. -
non era possibile inserire un placeholder dove un identificatore non è consentito, ad esempio al posto del corpo di una funzione o di una dichiarazione esportata.
Per risolvere questi problemi, abbiamo introdotto un nuovo elemento sintattico che può sostituire qualsiasi nodo: %%placeholder_name%%.
const buildLazyFn = template`
function %%name%%(%%params%%) {
return function () %%body%%;
}
`;
const result = buildLazyFn({
name: functionName,
params: functionParams,
body: functionBody,
});
Questa funzionalità è stata sponsorizzata da Stripe (tramite Runkit). Abbiamo sperimentato nuovi modi di sponsorizzare Babel, e per la prima volta un'azienda ha finanziato direttamente l'implementazione di una funzionalità pagando un membro del team per lavorarci. Se la tua azienda vuole sponsorizzare l'implementazione di una proposta ECMAScript o un miglioramento generale di Babel, contattaci!



