Vai al contenuto principale

Aggiornamento a Babel 7 (API)

Traduzione Beta Non Ufficiale

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

Fai riferimento a questo documento durante l'aggiornamento a Babel 7.

Consulta anche la guida alla migrazione v7 per altri cambiamenti a livello utente.

Tutti i pacchetti Babel

Supporto per NodeJS

high

Il supporto per Node.js 0.10 e 0.12 è stato rimosso poiché entrambe queste versioni sono fuori manutenzione.

Modifiche alle esportazioni

medium

Rimosso l'uso del plugin add-module-exports nei pacchetti Babel. Era necessario in precedenza per prevenire un breaking change nelle esportazioni. Se importi un pacchetto Babel in una libreria, potresti dover utilizzare .default con require invece di import.

@babel/core

L'opzione ast è ora impostata su false per impostazione predefinita per ottimizzare le prestazioni (la maggior parte degli strumenti non la utilizza) babel/babel#7436.

La classe Pipeline, esposta pubblicamente ma non documentata, è stata rimossa. Si consiglia di utilizzare direttamente i metodi di trasformazione esposti da @babel/core babel/babel#5376.

I metodi helper babel.util.* sono stati rimossi e util.EXTENSIONS è stata spostata in babel.DEFAULT_EXTENSIONS babel/babel#5487.

Le chiamate a babel.transform o ad altre funzioni di trasformazione potrebbero restituire null se il file corrisponde a un pattern ignore o non corrisponde a un pattern only babel/babel#5487.

L'opzione opts.basename esposta su state.file.opts è stata rimossa. Se necessaria, è consigliabile ricostruirla autonomamente da opts.filename babel/babel#5467.

Rimosso resolveModuleSource. Si consiglia di utilizzare l'opzione 'resolvePath' di babel-plugin-module-resolver@3 babel/babel#6343

Rimosso babel.analyse poiché era semplicemente un alias per babel.transform

Rimosso path.mark() poiché non veniva utilizzato e può essere implementato nel tuo plugin.

Rimosso babel.metadata poiché i metadati del plugin generati sono sempre inclusi nell'output.

Rimosso path.hub.file.addImport. È possibile utilizzare invece il modulo @babel/helper-module-imports.

+  import { addDefault } from "@babel/helper-module-imports";
function importModule(pkgStore, name, path) {
- return path.hub.file.addImport(resolvePath(pkgStore, name, path), 'default', name);
+ return addDefault(path, resolvePath(pkgStore, name, path), { nameHint: name });
}

Modifiche alla configurazione

Sono state apportate modifiche significative al funzionamento della ricerca della configurazione:

Per impostazione predefinita, durante la ricerca di file .babelrc per un dato file, ci si ferma al package.json.

Per qualsiasi file specifico, Babel v6 continua a cercare nella gerarchia delle directory fino a trovare un file di configurazione. Ciò significa che il tuo progetto potrebbe interrompersi perché utilizza un file di configurazione esterno alla root del pacchetto, ad esempio nella home directory.

Aggiunge il supporto per un file babel.config.js simile a quanto implementato da Webpack

Poiché questo comprometterebbe il funzionamento dei monorepo (incluso Babel stesso), viene introdotto un nuovo file di configurazione che elimina sostanzialmente la natura gerarchica delle configurazioni.

È inclusa un'opzione root che di default corrisponde alla directory di lavoro corrente per consentire di trovare il file. Non viene caricata in modo relativo, quindi gestirà correttamente i symlink, mentre in precedenza poteva essere necessario impostare manualmente i percorsi in Webpack.

Consulta la documentazione di babel.config.js per maggiori informazioni: configurazione a livello di progetto

Questo file, combinato con la nuova proprietà overrides e env, ti permette di avere un singolo file di configurazione che funziona per tutti i file di un progetto, a differenza di più file di configurazione per cartella.

Escludiamo anche node_modules di default e cerchiamo solo nella radice, a meno che non opti per impostare un array per l'opzione .babelrcRoots come "babelrcRoots": [".", "node_modules/pkgA"]

Verifica della versione di Babel #7450

I plugin possono verificare di essere caricati con una certa versione di Babel. L'API esporrà un metodo assertVersion, a cui puoi passare una versione semver.

L'helper declare viene utilizzato per mantenere la compatibilità con la versione 6.

JavaScript
import { declare } from "@babel/helper-plugin-utils";

export default declare(api => {
api.assertVersion(7);
// ...
});

Plugin e preset di Babel

Attualmente prende come primo parametro l'oggetto babel, le opzioni del plugin/preset e la dirname.

JavaScript
module.exports = function(api, options, dirname) {};

babel-parser (conosciuto come Babylon)

Rimossa l'opzione plugin * #301 basso

Questa opzione è stata introdotta in v6.14.1 (17 novembre 2016) quindi è improbabile che qualcuno la stesse utilizzando.

Questa opzione generica è stata rimossa; dovrai invece specificare esattamente quali plugin attivare.

Pensavamo fosse utile per gli strumenti per evitare aggiornamenti continui della configurazione, ma ciò impediva di apportare facilmente modifiche che rompono la compatibilità.

Prima:

JavaScript
babelParser.parse(code, {
plugins: ["*"],
});

Puoi ottenere il vecchio comportamento utilizzando:

JavaScript
babelParser.parse(code, {
plugins: [
"asyncGenerators",
"classProperties",
"decorators",
"doExpressions",
"dynamicImport",
"exportExtensions",
"flow",
"functionBind",
"functionSent",
"jsx",
"objectRestSpread",
],
});

Vedi le opzioni dei plugin di Babylon.

Il plugin decorators è stato rinominato in decorators-legacy medio

È stato rinominato per allinearsi all'opzione legacy di @babel/plugin-proposal-decorators. È stato implementato un nuovo plugin decorators che applica la nuova proposta per i decoratori.

Le due versioni delle proposte hanno sintassi diverse, quindi si consiglia vivamente di usare decorators-legacy finché Babel non implementerà le nuove semantiche.

Rimosso il plugin classConstructorCall #291 basso

@babel/traverse

Rimossa la gestione dei binding per flow babel/babel#6528

Questa modifica è dovuta al fatto che declare var foo non introduce un nuovo binding locale, ma rappresenta uno globale.

getFunctionParent non restituirà più Program; utilizza invece getProgramParent #5923. basso

Non ha senso che una funzione chiamata getFunctionParent restituisca anche Program, quindi questa funzionalità è stata rimossa.

Per ottenere lo stesso comportamento, dovrai apportare una modifica simile a:

- path.scope.getFunctionParent()
+ path.scope.getFunctionParent() || path.scope.getProgramParent()

Le API di sostituzione/rimozione percorsi ora restituiscono un array di nuovi percorsi low

Ad esempio, l'uso di Path#insertBefore o Path#replaceWith restituirà ora sempre un array dei percorsi appena inseriti/sostituiti.

JavaScript
const node = t.nullLiteral();
const [replaced] = path.replaceWith(node);
replace.node === node; // => true

Questo è particolarmente utile quando si inseriscono diversi nodi in uno scope superiore, poiché puoi immediatamente chiamare le API Path sul nuovo Path del nodo.

JavaScript
const parent = path.findParent(() => /* some selection criteria */);
const helperPaths = path.unshiftContainer("body", helpers);
// helperPaths can now be referenced, manipulated, etc.

Modifiche all'AST

Aggiunto nodo InterpreterDirective #7928

Babylon già analizzava gli "shebang" (#!env node) ma li inseriva come commenti nel nodo Program. Ora creiamo un nodo dedicato.

Aggiunto un nuovo campo interpreter al nodo Program.

JavaScript
extend interface Program {
interpreter: InterpreterDirective;
}

Aggiunto il nodo InterpreterDirective

JavaScript
interface InterpreterDirective <: Node {
type: "InterpreterDirective";
value: string;
}

Costruttori di nodi JSX* e TS* (da @babel/types) rinominati

La grafia è stata modificata: jsx e ts sono ora in minuscolo.

- t.jSXIdentifier()
+ t.jsxIdentifier()

In generale, abbiamo differenziato i tipi di nodo con TypeAnnotation per Flow e TSTypeAnnotation per TypeScript, quindi per i nodi di tipo condivisi TypeScript ha il prefisso TS.

Rimosso il campo .expression da ArrowFunctionExpression

Il campo expression è stato rimosso per eliminare due fonti di verità separate e la necessità che i plugin li mantenessero sincronizzati manualmente. Ora puoi semplicemente verificare se il corpo della funzione è un BlockStatement:

  return {
visitor: {
ArrowFunctionExpression({ node }) {
- if (node.expression) {
+ if (node.body.type !== "BlockStatement") {
// () => foo;
}
}
}
};

Token rimossi

Nelle versioni precedenti i tokens venivano sempre allegati all'AST a livello principale. Nell'ultima versione di @babel/parser abbiamo rimosso questo comportamento disabilitandolo di default per migliorare le prestazioni. Tutti gli utilizzi in Babel stesso sono stati rimossi e @babel/generator non utilizza più i token per la formattazione.

Se il tuo plugin Babel utilizza attualmente i tokens, valuta se è ancora necessario e cerca di rimuoverne l'uso se possibile. Se il tuo plugin dipende fortemente dall'ottenere i token, puoi riattivarli ma considera questa opzione solo se non esiste alternativa, poiché compromette le prestazioni.

Per attivarlo, devi impostare l'opzione tokens di babylon su true. Puoi farlo direttamente dal tuo plugin.

JavaScript
export default function() {
return {
manipulateOptions(opts, parserOpts) {
parserOpts.tokens = true;
},
...
};
}

Ridenominazioni

I seguenti nodi sono stati rinominati:

Name 6.xName 7.xExamplePR
ExistentialTypeParamExistsTypeAnnotationtype A = B<*>;#322
NumericLiteralTypeAnnotationNumberLiteralTypeAnnotationtype T = 0;#332

Oltre ai nodi AST, anche tutte le funzioni corrispondenti in @babel/types sono state rinominate.

 import * as t from "@babel/types";

return {
- ExistentialTypeParam(path) {
- const parent = path.findParent((path) => path.isExistentialTypeParam());
- t.isExistentialTypeParam(parent);
+ ExistsTypeAnnotation(path) {
+ const parent = path.findParent((path) => path.isExistsTypeAnnotation());
+ t.isExistsTypeAnnotation(parent);

- return t.existentialTypeParam();
+ return t.existsTypeAnnotation();
},
- NumericLiteralTypeAnnotation(path) {
- const parent = path.findParent((path) => path.isNumericLiteralTypeAnnotation());
- t.isNumericLiteralTypeAnnotation(parent);
+ NumberLiteralTypeAnnotation(path) {
+ const parent = path.findParent((path) => path.isNumberLiteralTypeAnnotation());
+ t.isNumberLiteralTypeAnnotation(parent);

- return t.numericLiteralTypeAnnotation();
+ return t.numberLiteralTypeAnnotation();
}
};

Sostituzioni

Nei seguenti nodi AST, il valore del campo variance è stato modificato da una semplice stringa a un nodo AST dedicato chiamato Variance. #333

Il campo è disponibile solo abilitando il plugin flow in babylon.

  • ObjectProperty

  • ObjectMethod

  • AssignmentProperty

  • ClassMethod

  • ClassProperty

  • Property

Il tipo del nuovo nodo Variance ha questa struttura:

JavaScript
type VarianceNode = {
type: "Variance",
kind: "plus" | "minus",
};
 return {
Property({ node }) {
- if (node.variance === "plus") {
+ if (node.variance.kind === "plus") {
...
- } else if (node.variance === "minus") {
+ } else if (node.variance.kind === "minus") {
...
}
}
};

Modifiche alle posizioni

Le informazioni di posizione di ObjectTypeIndexer sono state modificate per escludere i punti e virgola. Questo allineamento con il parser Flow garantisce informazioni di posizione coerenti. #228

Esempio:

JavaScript
var a: { [a: number]: string };
 {
"type": "ObjectTypeIndexer",
"start": 9,
- "end": 29,
+ "end": 28,
"loc": {
"start": {
"line": 1,
"column": 9,
},
"end": {
"line": 1,
- "column": 29
+ "column": 28
}
}
}

Rimozioni

ForAwaitStatement

Il nodo AST ForAwaitStatement è stato rimosso e sostituito dal campo await nel nodo ForOfStatement #349

 interface ForOfStatement <: ForInStatement {
type: "ForOfStatement";
+ await: boolean;
}
 return {
- ForAwaitStatement(path) {
- ...
+ ForOfStatement(path) {
+ if (path.node.await) {
+ ...
+ }
}
};

RestProperty & SpreadProperty

I due nodi AST RestProperty e SpreadProperty sono stati rimossi in favore del riutilizzo di RestElement e SpreadElement #384

 return {
SpreadElement(path) {
- ...
- },
- SpreadProperty(path) {
- ...
+ if (path.parentPath.isObjectExpression()) {
+ ...
+ } else if (path.parentPath.isArrayExpression()) {
+ ...
+ }
},
RestElement(path) {
- ...
- },
- RestProperty(path) {
- ...
+ if (path.parentPath.isObjectPattern()) {
+ ...
+ } else if (path.parentPath.isArrayPattern()) {
+ ...
+ }
}
};

Per maggiori informazioni, consulta la nostra PR di aggiornamento per Babel e le specifiche AST di Babylon.