Come pubblicare un modulo scritto in ES6 in NPM?

Stavo per pubblicare un modulo su NPM, quando ho pensato di riscriverlo in ES6, sia a prova di futuro che di imparare ES6. Ho usato Babel per traspolare in ES5 ed eseguire test. Ma non sono sicuro di come procedere:

  1. Traspare e pubblicare la cartella risultante / fuori in NPM?
  2. Includo la cartella dei risultati nel mio repository Github?
  3. O mantengo 2 repository, uno con il codice ES6 + lo script gulp per Github e uno con i risultati transpiled + test per NPM?

In breve: quali passaggi devo seguire per pubblicare un modulo scritto in ES6 su NPM, consentendo comunque alle persone di sfogliare / inserire il codice originale?

Il modello che ho visto finora è quello di mantenere i file es6 in una directory src e build i tuoi contenuti nella pubblicazione in anticipo di npm nella directory lib .

Avrai bisogno di un file .npmignore, simile a .gitignore ma che ignora src invece di lib .

Mi piace la risposta di José. Ho notato che diversi moduli seguono già questo schema. Ecco come puoi implementarlo facilmente con Babel6. Installo babel-cli localmente in modo che la costruzione non si rompa se cambierò mai la mia versione di babel globale.

.npmignore

 /src/ 

.gitignore

 /lib/ /node_modules/ 

Installa Babel

 npm install --save-dev babel-core babel-cli babel-preset-es2015 

package.json

 { "main": "lib/index.js", "scripts": { "prepublish": "node_modules/babel-cli/bin/babel.js src --out-dir lib" }, "babel": { "presets": ["es2015"] } } 

@Jose ha ragione. Non c’è niente di sbagliato con la pubblicazione di ES6 / ES2015 su NPM, ma questo potrebbe causare problemi, specialmente se la persona che usa il pacchetto usa Webpack, ad esempio, perché normalmente le persone ignorano la cartella node_modules durante la pre-elaborazione con babel per motivi di prestazioni.

Quindi, basta usare gulp , grunt o semplicemente Node.js per creare una cartella lib che sia ES5.

Ecco il mio script build-lib.js , che tengo in ./tools/ (nessun gulp o grunt qui):

 var rimraf = require('rimraf-promise'); var colors = require('colors'); var exec = require('child-process-promise').exec; console.log('building lib'.green); rimraf('./lib') .then(function (error) { let babelCli = 'babel --optional es7.objectRestSpread ./src --out-dir ./lib'; return exec(babelCli).fail(function (error) { console.log(colors.red(error)) }); }).then(() => console.log('lib built'.green)); 

Ecco un ultimo consiglio: devi aggiungere un .npmignore al tuo progetto . Se npm publish non trova questo file, userà invece .gitignore , che ti creerà problemi perché normalmente il tuo file ./lib escluderà ./lib e includerà ./src , che è esattamente l’opposto di quello che vuoi quando pubblicano su NPM. Il file .npmignore ha praticamente la stessa syntax di .gitignore (AFAIK).

Se vuoi vedere questo in azione in un modulo Node open source molto semplice allora dai uno sguardo all’ennesimo giorno (che ho iniziato – anche altri contributori). Cerca nel file package.json e nella fase di preparazione che ti porterà dove e come farlo. Se cloni quel modulo, puoi eseguirlo localmente e usarlo come modello per te.

I due criteri di un pacchetto NPM è che è utilizzabile con nient’altro che un require( 'package' ) e fa qualcosa di software-ish.

Se soddisfi questi due requisiti, puoi fare tutto ciò che desideri. Anche se il modulo è scritto in ES6, se l’utente finale non ha bisogno di saperlo, lo trasperei per ora per ottenere il massimo supporto.

Tuttavia, se come il koa , il tuo modulo richiede compatibilità con gli utenti che utilizzano le funzionalità ES6, allora forse la soluzione dei due pacchetti sarebbe un’idea migliore.

Porta via

  1. Pubblicare solo il codice che è necessario per rendere require( 'your-package' ) .
  2. A meno che la differenza tra ES5 e 6 sia importante per l’utente, pubblicare solo 1 pacchetto. Trasformalo se devi.

La chiave principale in package.json decide il punto di ingresso al pacchetto una volta pubblicato. Così puoi mettere la tua uscita di Babel dove vuoi e devi solo menzionare il percorso giusto nella chiave main .

 "main": "./lib/index.js", 

Ecco un articolo ben scritto su come pubblicare un pacchetto npm

https://codeburst.io/publish-your-own-npm-package-ff918698d450

Ecco un repository di esempio che puoi usare come riferimento

https://github.com/flexdinesh/npm-module-boilerplate

Aggiornamento 2018 settembre

Dal 2015, quando è stata posta questa domanda, il supporto JavaScript per i moduli è maturato in modo significativo. Tutte le altre risposte sono ora obsolete o eccessivamente complicate. Ecco la situazione attuale e le migliori pratiche.

Supporto

Il 99% di ES6 (alias 2015) è supportato dal nodo dalla versione 6 . L’attuale versione notturna è 11. Tutti i browser sempreverdi supportano la stragrande maggioranza delle funzionalità di ES6. ECMAScript è ora alla versione 2018 e lo schema di versioning ora favorisce l’utilizzo di anni.

Utilizzo del modulo ES6 (con bonus di importazione / esportazione)

 // lib.mjs export const hello = 'Hello world!'; // index.mjs: import { hello } from './lib'; console.log(hello); 

Nota l’estensione .mjs obbligatoria. Correre come:

 node --experimental-modules index.mjs 

import / exports sono state supportate sperimentalmente dal nodo 8.5.0 e la bandiera sperimentale dovrebbe andare in v10 LTS .

Moduli ES6 (ovvero moduli ECMAScript) nei browser

Tutti i browser sempre verdi supportano import moduli ES6 di import . Maggiori informazioni su https://jakearchibald.com/2017/es-modules-in-browsers/ . Le importazioni dinamiche sono supportate da Chrome e Safari. Non hai più bisogno di Webpack / rollup / pacchi ecc.

E ora per rispondere alla domanda.

Pubblicazione di moduli ES6 su npm, con compatibilità all’indietro

Per pubblicare un modulo ES su npmjs.org in modo che possa essere importato direttamente, senza Babel o altri transpilers, basta puntare il campo main nel file package.json nel file .mjs , ma omettere l’estensione:

 { "name": "mjs-example", "main": "index" } 

Questo è l’unico cambiamento. Omettendo l’estensione, Node cercherà prima un file mjs se eseguito con –experimental-modules. Altrimenti tornerà al file .js, quindi il tuo processo di transpilation per supportare versioni di Node più vecchie funzionerà come prima – assicurati di indirizzare Babel ai file .mjs .

Ecco la fonte di un modulo ES nativo con compatibilità all’indietro per il nodo <8.5.0 che ho pubblicato su NPM. Puoi usarlo subito, senza Babele o qualsiasi altra cosa.

Installa il modulo:

 yarn add local-iso-dt # or, npm install local-iso-dt 

Crea un file di prova test.mjs :

 import { localISOdt } from 'local-iso-dt'; console.log(localISOdt(), 'Starting job...'); 

Esegui nodo (v8.5.0 +) con il flag –experimental-module:

 node --experimental-modules test.mjs 

Dattiloscritto

Se sviluppi in TypeScript, puoi generare codice ES6 e utilizzare i moduli ES6:

 tsc index.js --target es6 --modules es2015 

Quindi, è necessario rinominare l’output *.js in .mjs , un problema noto che si spera .mjs presto risolto in modo che .mjs possa emettere direttamente i file .mjs .

Alcune note extra per chiunque, usando i propri moduli direttamente da github, non passando attraverso i moduli pubblicati :

L’hook “prepubish” ( ampiamente utilizzato ) non fa nulla per te.

La cosa migliore si può fare (se si prevede di fare affidamento su repository github, non su materiale pubblicato):

  • non elencare src da .npmignore (in altre parole: permetterlo). Se non hai un .npmignore , ricorda: una copia di .gitignore verrà invece utilizzata nel percorso installato, come verrà mostrato ls node_modules/yourProject .
  • assicurati che babel-cli sia una depenenza nel tuo modulo, non solo una devDepenceny dato che stai effettivamente costruendo sulla macchina che consuma al computer degli sviluppatori di app, che sta usando il tuo modulo
  • fai la cosa build, nel hook install ie:

    "install": "babel src -d lib -s"

(nessun valore aggiunto nel provare qualcosa “preinstall”, ad esempio babel-cli potrebbe mancare)