Rimozione dei preset Stage di Babel
Questa pagina è stata tradotta da PageTurner AI (beta). Non ufficialmente approvata dal progetto. Hai trovato un errore? Segnala problema →
Procedendo con la versione 7, abbiamo deciso che è meglio smettere di pubblicare i preset Stage in Babel (ad esempio @babel/preset-stage-0).
Non abbiamo preso questa decisione alla leggera e vogliamo mostrare il contesto dietro l'interazione tra TC39, Babel e la comunità.
Un po' di storia
Un preset di Babel è una lista condivisibile di plugin.
I preset Stage ufficiali di Babel seguivano il processo di staging di TC39 per le nuove proposte di sintassi in JavaScript.
Ogni preset (ad es. stage-3, stage-2, ecc.) includeva tutti i plugin per quella specifica fase e per quelle superiori. Ad esempio, stage-2 includeva stage-3, e così via.
Ciò permetteva agli utenti che volevano usare sintassi sperimentali di aggiungere semplicemente il preset, invece di dover configurare/installare ogni singolo plugin.
In realtà abbiamo aggiunto i preset Stage poco dopo il rilascio di Babel v6 (in precedenza era un flag di configurazione nella v5). Di seguito è mostrato un vecchio esempio di Babel v6.
Era comune vedere questo in una configurazione:
{
"presets": ["es2015", "react", "stage-0"]
}
Il codice sorgente originale di babel-preset-stage-0:
module.exports = {
presets: [
require("babel-preset-stage-1")
],
plugins: [
require("babel-plugin-transform-do-expressions"),
require("babel-plugin-transform-function-bind")
]
};
Problemi
Questi preset erano un modo conveniente per usare ciò che tutti volevamo: il futuro nuovo, brillante e "ancora da determinare" di JavaScript.
A ripensarci, ha funzionato davvero bene! (Forse troppo bene?)
Un lavoro troppo ben fatto?
Linguaggi come CoffeeScript e strumenti come Traceur hanno contribuito a stabilire l'idea di compilare JavaScript. Babel ha reso ancora più semplice sia l'uso di sintassi nuove/future sia l'integrazione con gli strumenti esistenti. Le aspettative sono cambiate da scetticismo e preoccupazione all'abbracciare completamente lo sperimentale.
Probabilmente non saremmo qui senza la vasta adozione di compilatori come Babel: ha accelerato l'uso (e l'insegnamento) di ES2015 per un pubblico molto più ampio. La crescita di React ha ulteriormente alimentato l'utilizzo poiché la sua sintassi JSX, le proprietà delle classi e l'object rest/spread hanno portato le persone a conoscere un po' di più queste proposte di sintassi.
Babel è diventato una configurazione una tantum per le persone, da non ripensare mai più. È diventata l'infrastruttura sottostante, nascosta dietro altri strumenti finché non si verificava un SyntaxError, problemi di dipendenze o problemi di integrazione. Bastava usare stage-0.
In un certo senso è stato fantastico da vedere, perché significava che queste idee venivano testate nel mondo reale, anche in ambienti di produzione. Tuttavia, significava anche che molte aziende, strumenti e persone avrebbero incontrato problemi se una proposta fosse cambiata in modo significativo (o addirittura abbandonata del tutto).
Avanti e indietro
Nel corso degli anni, abbiamo sollevato molti problemi per discutere cosa fare con i preset Stage in #4914, #4955, #7770. Ho persino scritto in un vecchio post su Babel 7.0 che diceva che non li avremmo rimossi 😅.
Tuttavia, abbiamo scoperto che mantenere i preset Stage avrebbe causato problemi anche per Babel stesso:
-
Era un problema comune chiedere ad esempio: "Quali preset sono necessari per usare le funzioni asincrone?". Per gli utenti non era chiaro cosa significasse esattamente
stage-0, e pochi andavano a consultare il suopackage.jsono il codice sorgente. -
Rimuovere un plugin per una proposta allo Stage 3 (una volta che passa allo Stage 4) rappresenta di fatto una breaking change. Questo problema si acuisce quando si cerca di usare
@babel/preset-envper evitare di compilare proposte già supportate nativamente.
I "Decoratori ES7"
Parte del problema risiede proprio nella denominazione, e come spesso si dice, dare nomi alle cose è difficile.
Per ES6 stesso esistevano molti nomi: Harmony, ES Next, ES6, ES2015. Quando le persone sentono parlare di nuove idee, è normale attaccarvi semplicemente l'ultimo numero disponibile.
Di conseguenza, è facile trovare in giro tweet/post/blog/discorsi che parlano di "Decoratori ES7", diventato ormai un nome consolidato.
Your reminder that binding with :: is just an experimental proposal at stage 0 and might never become a part of JS. Don't call it "ES7".
— Dan Abramov (@dan_abramov) October 9, 2016
È comprensibile che ciò accada inconsapevolmente, ma continuare così crea aspettative distorte sull'evoluzione del linguaggio. Non c'è nulla di cui sentirsi in colpa: impariamo come comunità e ci ricordiamo a vicenda come funziona JavaScript.
Jay Phelps ha scritto un ottimo articolo sull'argomento. Spiega che sarebbe meglio chiamarle in base allo "Stage" corrente: "Decoratori Stage 2", o semplicemente "Proposta Decoratori".
Il ragionamento è che dire "Decoratori ES7" presuppone che i Decoratori siano previsti in ES7. Ho menzionato questo aspetto nel mio ultimo post sulla compilazione di node_modules: trovarsi in un determinato Stage non garantisce nulla. Una proposta può bloccarsi, retrocedere o essere abbandonata del tutto.
Abbiamo voluto evidenziare questo fatto quando abbiamo deciso di cambiare i nomi dei plugin per le proposte da @babel/plugin-transform- a @babel/plugin-proposal-.
BabelScript
Avere preset per proposte così premature può suggerire che queste siano garantite per progredire o abbiano un'implementazione stabile.
TC39 raccomanda cautela nell'usare proposte allo Stage 2 o inferiori, poiché potrebbe generare pressioni involontarie dalla comunità a mantenere l'implementazione così com'è, per timore di rompere codice esistente o frammentare l'ecosistema (es. usare un simbolo diverso come # invece di @ per i decoratori).
Si scherza sul fatto che gli sviluppatori che usano Babel stiano scrivendo "BabelScript" invece di JavaScript, implicando che una volta creato un plugin Babel per una certa funzionalità, questa sia già "definitiva" o ufficialmente parte del linguaggio (cosa non vera). Per alcuni, la prima reazione davanti a una nuova sintassi/idea (Stage "-1") è chiedersi se esista un plugin Babel per essa.
Gestire le aspettative
Dopo che compilatori come Babel hanno reso comune scrivere codice ES2015, era naturale che gli sviluppatori volessero provare "funzionalità" ancora più nuove e sperimentali. In Babel questo avveniva usando il flag stage nelle versioni precedenti o i preset stage-x.
Essendo il modo più semplice per attivare nuove funzionalità, diventò rapidamente la scelta predefinita quando si configurava Babel (nonostante in Babel v6 avesse smesso di fare nulla di default, causando molte lamentele).
Divenne comune vedere "stage-0" utilizzato in librerie, boilerplate, talk, tweet e slide.
"Just say no" to
— Ryan Florence (@ryanflorence) July 31, 2015babel?stage=0in production.
Ci furono molte discussioni valide già anni fa, ma non era facile orientarsi: non volevamo penalizzare utenti che comprendevano i compromessi inserendo console.warn durante l'uso, e rimuovere completamente l'opzione sembrava irragionevole all'epoca.
Attivare ciecamente Stage 0 (che fosse predefinito o scelto dagli utenti) appare rischioso, ma evitare completamente le proposte è eccessivamente cauto. Idealmente, tutti dovrebbero prendere decisioni informate sulle funzionalità da utilizzare con giudizio, indipendentemente dallo stage in cui si trovano. Mike Pennisi ha scritto un ottimo articolo su queste preoccupazioni.
Non è nostra intenzione minacciare, accelerare forzatamente o imporre elementi specifici nell'ecosistema JavaScript, ma mantenere fedelmente implementazioni e discussioni sulle nuove idee.
Esitazioni
Altre considerazioni
Avremmo anche potuto:
-
Rinominare i preset per segnalare meglio il livello di stabilità (non risolve il problema del versioning)
-
Strategie di versioning migliori: versionare i preset indipendentemente e aggiornarli immediatamente quando necessario, magari usando
0.x -
Generare avvisi/errori per versioni obsolete dei preset
Alla fine, le persone avrebbero comunque dovuto verificare a quale Stage fossero le proposte per sapere quali utilizzare, se avessimo mantenuto gli Stage.
Perché adesso?
Perché non rimuoverli prima? I preset Stage fanno parte di Babel da anni, e c'erano preoccupazioni sull'aggiungere "complessità" all'utilizzo di Babel. Molti strumenti, documentazione, articoli e conoscenze ruotavano attorno ai preset Stage. Inizialmente, pensavamo fosse meglio mantenerli ufficialmente poiché qualcun altro li avrebbe (e li creerà) inevitabilmente.
Cerchiamo il giusto livello di feedback: se solo il comitato decidesse cosa includere nel linguaggio, potremmo ottenere funzionalità ben specificate ma inutili. Se invece la comunità ritenesse stabili le proposte sperimentali in corso, utilizzabili in produzione senza conseguenze, avremmo altri problemi. Vogliamo procedere con intenzione: senza fretta ma senza eccessiva cautela. Babel è il posto giusto per sperimentare, ma conoscere i limiti è necessario.
Rimuovere i preset sarebbe considerata una "funzionalità" perché obbligherebbe a prendere decisioni esplicite per ogni proposta, cosa ragionevole data la loro variabile instabilità, utilità e complessità.
Ci aspettiamo una certa reazione negativa iniziale, ma riteniamo che rimuovere i preset Stage sia la scelta migliore a lungo termine. Tuttavia, eliminare i preset non significa trascurare facilità d'uso, nuovi utenti o documentazione. Lavoriamo per mantenere il progetto stabile, fornire strumenti migliori e documentare ciò che sappiamo.
Migrazione
Per una migrazione più automatica, abbiamo aggiornato babel-upgrade per occuparsene (puoi eseguire
npx babel-upgrade).
In breve, stiamo rimuovendo i preset Stage. In un certo senso, gli sviluppatori dovranno aderire consapevolmente e conoscere quali proposte vengono utilizzate, anziché dare per scontato cosa si debba usare, soprattutto considerando la natura instabile di alcune di queste proposte. Se utilizzi un altro preset o una toolchain (ad esempio create-react-app), è possibile che questo cambiamento non ti riguardi direttamente.
Abbiamo deprecato i preset Stage a partire da 7.0.0-beta.52. Se non vuoi modificare la tua configurazione ora, ti consigliamo di fissare le versioni a beta.54 finché non potrai effettuare l'aggiornamento; dopo beta.54 genereremo un errore con un messaggio che spiega come migrare. Assicurati inoltre che tutte le tue versioni siano uniformi durante la fase di prerelease.
Come alternativa, sei libero di creare il tuo preset contenente gli stessi plugin e aggiornarli a tuo piacimento. In futuro, potremmo lavorare a un babel-init che ti aiuti a configurare i plugin in modo interattivo o aggiornare babel-upgrade per elencare e aggiungere i plugin Stage attuali. Forse Babel dovrebbe rimanere uno strumento di basso livello e affidarsi ad altri strumenti di alto livello o framework come create-react-app per gestire queste scelte.
Prevenire il Blocco su una Proposta
James DiGioia ha recentemente pubblicato un articolo sui cambiamenti relativi all'operatore pipeline (|>).
Il punto centrale dell'articolo è che la proposta stessa è in evoluzione e presenta diverse opzioni da esplorare. Poiché intendiamo implementare tutte e tre le possibilità attuali come plugin Babel per ottenere feedback sia sulle specifiche che dagli utenti, riteniamo che anche l'utilizzo del plugin debba cambiare. Questo rappresenta un approccio relativamente nuovo per TC39 e Babel!
In precedenza, aggiungevamo semplicemente il plugin della proposta alla configurazione. Ora rimuoviamo il comportamento predefinito e chiediamo agli utenti di aderire esplicitamente a un flag che indica quale proposta è stata scelta, chiarendo che al momento non esiste un'opzione consolidata (né tantomeno preferita).
{
"plugins": [
- "@babel/plugin-proposal-pipeline-operator"
+ ["@babel/plugin-proposal-pipeline-operator", { "proposal": "minimal" }]
]
}
Intendiamo proseguire con questa direzione come ulteriore segnale che queste proposte sono aperte a cambiamenti e feedback collettivi. La rimozione dei preset Stage semplifica ulteriormente il processo, poiché in precedenza dovevamo propagare queste opzioni anche a chi non utilizzava la sintassi.
Onere di Manutenzione per l'Ecosistema
Il "budget sintattico" di un linguaggio non riguarda solo la complessità del linguaggio stesso, ma si estende anche agli strumenti. Ogni nuova aggiunta sintattica comporta un nuovo onere per i maintainer di altri progetti JavaScript.
Quando viene proposta una nuova sintassi, molti elementi richiedono aggiornamenti: parser (babylon), evidenziazione sintattica (language-babel), linter (babel-eslint), framework di test (jest/ava), formattatori (prettier), code coverage (istanbul), minificatori (babel-minify) e altro ancora.
Sono stati sollevati numerosi problemi su progetti come acorn, eslint, jshint, typescript e altri per supportare proposte di Stage 0 semplicemente perché presenti in Babel. Pochi progetti aderirebbero a una politica che richiedesse di supportare qualsiasi proposta, data l'estrema difficoltà di manutenzione. In molti modi, è sorprendente che persino Babel tenti di gestirle, considerando gli aggiornamenti continui e l'instabilità.
Chi svolge questo lavoro, ed è nostra responsabilità garantire che tutto funzioni? Ciascuno di questi progetti (sostenuti principalmente da volontari) manca di supporto in quasi ogni aspetto, eppure riceviamo costantemente lamentele trasversali. Come comunità, come possiamo assumerci la responsabilità di gestire la nostra infrastruttura (non diversamente dall'open source nel suo complesso)?
Babel si è assunto l'insolito onere di supportare queste funzionalità sperimentali; allo stesso tempo, è ragionevole che altri progetti adottino una politica più conservativa. Se desideri vedere nuove funzionalità del linguaggio supportate nell'intero ecosistema, contribuisci a TC39 e a questo progetto per portare queste proposte allo Stage 4.
Il futuro
Lo scopo di questo progetto è fungere da parte del processo TC39: essere una risorsa sia per implementare proposte più recenti (Stage 0-2) sia per ricevere feedback dagli utenti, supportando al contempo le versioni più vecchie di JavaScript. Speriamo che questo post faccia più luce su come stiamo cercando, nel miglior modo possibile, di allineare meglio questo progetto nell'ecosistema JavaScript. Rilascieremo presto una RC per la v7!
Se apprezzi questo post e il lavoro che stiamo facendo su Babel, puoi supportarmi su Patreon, chiedere alla tua azienda di sponsorizzarci su Open Collective o, ancora meglio, coinvolgere la tua azienda con Babel come parte del tuo lavoro. Apprezziamo la proprietà collettiva.
Con ringraziamenti a tutti i revisori! Sentitevi liberi di dare un feedback su Twitter.