Come pubblicare una cartella specifica in npm ma come root del pacchetto


91

Ho un progetto che include un'attività gulp per la creazione e il packaging dei sorgenti e del rilascio in una directory chiamata dist. Il mio obiettivo è pubblicarlo come pacchetto npm, ma solo la mia cartella dist. La documentazione di npm dice che posso usare il filestag per specificare i file da esportare. Funziona. Ma la documentazione dice anche che:

Se assegni un nome a una cartella nell'array, includerà anche i file all'interno di quella cartella

Il risultato è un pacchetto npm, che assomiglia a node_modules:

pacchetto npm generato

Ma mi piacerebbe vedere tutti i miei file alla radice del pacchetto (senza quella distcartella). Il mio index.jsfile è all'interno della distcartella, ma dovrebbe essere alla radice. Ho provato a impostare il tag filescome /dist/**/*ma non ha funzionato.

Come posso ottenerlo?

Risposte:


45

Ho lo stesso desiderio, ma penso che non ci sia modo di farlo utilizzando solo gli strumenti npm . Un altro script / strumento potrebbe essere utilizzato per organizzare il pacchetto.

Soluzione alternativa

Attualmente sto copiando il mio package.jsonnella distcartella e poi corro npm packall'interno della distcartella. Penso che questo essenzialmente fornisca la disposizione desiderata del nostro pacchetto.

Ecco alcune letture rilevanti su questo progetto npm: Why no Directories.lib in Node .

È anche interessante notare che jspm rispetta l' directories.libopzione in package.jsone riorganizza i file quando risolve il pacchetto npm. Tutto questo è accaduto per me perché desidero creare una libreria comune che può essere utilizzata da jspm o npm / webpack.


1
(Why no Directories.lib ...) is a dead link
Shanimal

1
Perché nessun Directories.lib in Node dice, se non lo fai a modo nostro, dovresti provare dolore. Tutto ciò crea la necessità di strumenti per risolvere questo problema.
Brian Takita

6
Credo che questa risposta sia obsoleta. Come notano le risposte di seguito, l'utilizzo di npm packpackage.json filese dei maincampi e .npmignorefornisce a uno sviluppatore tutto il necessario per creare un pacchetto da una directory specifica e installabile.
Jefftopia

1
Realizzato alcuni script per semplificare / applicare il modello "pubblica sottodirectory"
ridimensionare il

2
Qualcuno può pubblicare la soluzione su come può essere ottenuta utilizzando npmignore, file e proprietà principale in package.json. Voglio spostare tutti i file nella directory principale e non avere la cartella dist
Angad

17

Ho un problema simile al poster originale (@robsonrosa). Nel mio caso utilizzo il typecript che compila in una distdirectory. Sebbene sia possibile compilare il dattiloscritto nella directory principale, penso che la soluzione migliore sia generare un package.jsonfile separato nella directory dist.
Questo è simile al suggerimento di @scvnc di copiare il package.jsonma con una svolta:

Come parte del processo di creazione package.jsondel pacchetto, è necessario generare un per il pacchetto che è basato ma distinto dal package.jsonfile principale nella directory principale

La logica:

  • Il package.jsonfile radice è il file di sviluppo. Può contenere script o dipendenze di sviluppo che non sono di alcuna utilità per l'utente del pacchetto, ma possono porre problemi di sicurezza per te. La procedura di confezionamento può includere un codice che elimina tali informazioni dalla produzione package.json.
  • Potresti voler distribuire il tuo pacchetto in ambienti diversi che potrebbero richiedere file di pacchetto differenti (ad esempio potresti voler avere versioni o dipendenze differenti).

--- MODIFICARE ---

Mi è stata chiesta una soluzione nei commenti. Quindi ecco del codice che sto usando. Questo dovrebbe essere considerato come un esempio, non vuole essere generico ed è specifico per i miei progetti.

La mia configurazione:

package.json         - main package.json with dev dependencies and useful scripts.
.npmignore           - files to ignore; copied to 'dist' directory as part of the setup.
/src                 - directory where my typescript code resides.
/src/SetupPackage.ts - bit of code used to setup the package.
/dist                - destination directory for the compiled javascript files.

Voglio creare un pacchetto solo per la distdirectory e la directory dovrebbe essere la directory principale nel pacchetto.

Il file SetupPackage.tsnella mia srcdirectory verrà compilato SetupPackage.jsnella distdirectory tramite dattiloscritto:

import fs from "fs";

// DO NOT DELETE THIS FILE
// This file is used by build system to build a clean npm package with the compiled js files in the root of the package.
// It will not be included in the npm package.

function main() {
    const source = fs.readFileSync(__dirname + "/../package.json").toString('utf-8');
    const sourceObj = JSON.parse(source);
    sourceObj.scripts = {};
    sourceObj.devDependencies = {};
    if (sourceObj.main.startsWith("dist/")) {
        sourceObj.main = sourceObj.main.slice(5);
    }
    fs.writeFileSync(__dirname + "/package.json", Buffer.from(JSON.stringify(sourceObj, null, 2), "utf-8") );
    fs.writeFileSync(__dirname + "/version.txt", Buffer.from(sourceObj.version, "utf-8") );

    fs.copyFileSync(__dirname + "/../.npmignore", __dirname + "/.npmignore");
}

main();

Questa vita:

  • Copia la root package.jsonma rimuove gli script e le dipendenze dev che non sono necessarie nel pacchetto. Risolve anche il punto di ingresso principale del pacchetto.
  • Scrive la versione del pacchetto da package.jsonin un file chiamato version.txt.
  • Copia il .npmignorepacchetto dalla radice.

Il contenuto .npmignore è:

*.map
*.spec.*
SetupPackage.*
version.txt

Vale a dire gli unit test (file spec) e i file di mappa del dattiloscritto vengono ignorati così come il SetupPackage.jsfile e il version.txtfile che crea. Questo lascia un pacchetto pulito.

Infine il package.jsonfile principale ha i seguenti script per l'uso da parte del sistema di compilazione (si assume shsia usato come shell).

"scripts": {
    "compile": "tsc",
    "clean": "rm -rf dist",
    "prebuildpackage": "npm run clean && npm run compile && node dist/SetupPackage.js",
    "buildpackage": "cd dist && npm pack"
  },

Per creare il pacchetto, il sistema di compilazione clona il repository, lo fa npm installe quindi esegue npm run buildpackageche a sua volta:

  • Elimina la distdirectory garantendo una compilazione pulita.
  • Compila il codice dattiloscritto in javascript.
  • Esegue il SetupPackage.jsfile che prepara distper il packaging.
  • cds nella distdirectory e vi compila il pacchetto.

Uso il version.txtfile come un modo semplice per ottenere la versione in package.json e per taggare il mio repository. Ci sono innumerevoli altri modi per farlo o potresti voler incrementare automaticamente la versione. Rimuovilo da SetupPackage.tse .npmignorese non ti è utile.


Questa risposta sembra la migliore, ma hai una soluzione pronta a parte la teoria?
yumaa

3
@yumaa Ho modificato la mia risposta con un esempio concreto. Spero sia utile.
Eli Algranti

1
Ha funzionato per me con alcune modifiche. Il SetupPackage.tsfile corrente copia i file nella srcdirectory anziché in dist. Grazie 👍
Harinder Singh

15

Se il tuo progetto ha git puoi usare small hack. Aggiungi gli script successivi a package.json

    "prepublishOnly": "npm run build && cp -r ./lib/* . && rm -rf ./lib",
    "postpublish": "git clean -fd",

ora quando esegui il publishcomando npm coinvolgi prepublishOnly. Crea file e li salva nella libcartella (uno script di compilazione dipende dal progetto). Il comando successivo copia i file nella cartella principale e rimuove lib. Dopo la pubblicazione, lo postpublishscript riporta il progetto a uno stato precedente.


1
Sono un fan di questa soluzione!
DanMad

7

Ti consiglio vivamente di usare .npmignoreinvece di spostare o copiare cose, specialmente se stai usando un elemento della configurazione per le distribuzioni, e aggiungi semplicemente lì i file che non vuoi pubblicare.

https://docs.npmjs.com/misc/developers#keeping-files-out-of-your-package

Esempio:

#tests
test
coverage

#build tools
.travis.yml
.jenkins.yml
.codeclimate.yml

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

Aggiornare:

Se vuoi dividere il tuo codice in diversi pacchetti npm usando lo stesso repository, mi sono imbattuto in questo progetto di recente: Lerna e sembra davvero buono.

Forse dovresti dare un'occhiata


9
Dovremmo comunque emettere i nostri file compilati nella directory principale del pacchetto. Forse ammissibile per CI. Osserva il post dal blog di Isaac a cui mi sono collegato e dimmi come la tua soluzione consentirebbe require('mypackage/foo')invece direquire('mypackage/dist/foo')
scvnc

Non stavo cercando di risolvere quel problema qui. Se vuoi dividere il tuo codice, mi sono imbattuto in questo progetto di recente: lernajs.io e sembra davvero buono
Thram

Ho trovato un altro strumento che vale la pena dare un'occhiata :) github.com/philcockfield/msync
Thram

yeh material UI lo uso e l'ho usato nella mia ultima azienda, l'ho trovato ok
nick

6

Questo funziona bene per me.

cd TMPDIR; npm pack/path/to/package.json

Tarball creerà all'interno della directory TMPDIR.


^ Questa risposta è sottovalutata. npm packinoltre il filescampo package.json (o .npmignore) funziona meravigliosamente.
Jefftopia

1

Se stai (e ti consiglio) usando il rilascio semantico , aggiungi l' pkgRootopzione nel .releaserc.jsonfile:

{
  "pkgRoot": "dist",
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    [
      "@semantic-release/exec",
      {
        "prepareCmd": "npx rjp package.json version nextRelease.version"
      }
    ],
    [
      "@semantic-release/git",
      {
        "assets": ["package.json"]
      }
    ],

  ],
}

Questo risolverà il problema. Assicurati solo che la tua distcartella contenga un package.jsonfile. Puoi farlo facilmente aggiungendo un cpal tuo postbuildscript. Installa anche rjp


0

Devi pubblicare la distcartella

Il modo naturale per ottenere ciò, secondo l'approccio npm, è pubblicare la cartella che deve essere la radice. Ci sono diversi modi per farlo, dipende dall'ambiente finale con cui vuoi lavorare:

  1. npm pubblica <folder> dal repository dei pacchetti in un registro npm e quindi installa il pacchetto in un altro progetto mentre si installano altri pacchetti. Nel tuo caso lo sarebbe npm publish dist.
  2. npm installa <folder> in qualche altro progetto se vuoi usare il tuo pacchetto solo localmente. Nel tuo caso vai all'altro progetto e corrinpm install relative/path/to/dist
  3. npm collega la tua cartella localmente alla tua node_modulesin un altro progetto nel caso in cui desideri che le modifiche nel tuo pacchetto originale si riflettano istantaneamente in un altro progetto. Nel tuo caso prima cd distcorri npm linke poi vai all'altro progetto e corri npm link robsonrosa-ui-alert.

Prerequisito : in ogni caso sopra, prima della pubblicazione / installazione / collegamento, devi mettere nella tua distcartella almeno un package.jsonfile appropriato . Nel tuo caso, devi avere il nome del pacchetto definito nel tuo file package.json come "name": "robsonrosa-ui-alert". In genere, ti serviranno anche altri file come README.md o LICENSE.

Note ai metodi 2 e 3

In genere si verificano problemi con le dipendenze dei pacchetti quando si utilizza il pacchetto installato in questo modo. Per evitarlo, prima comprimere il pacchetto con npm pack diste poi installare il pacchetto nel progetto di destinazione dal tarball compresso, cioè npm install path/to/package-tarball.tgz.

Esempio di automazione

È possibile automatizzare il processo di pubblicazione utilizzando lo preparescript , combinato con lo buildscript. Inoltre, puoi proteggere il tuo pacchetto da una pubblicazione accidentale della cartella principale del pacchetto con il "private": truecampo inserito in package.json, situato nella directory principale del repository del pacchetto. Ecco un esempio:

  "private": true,
  "scripts": {
    "build": "rm -rf dist && gulp build && cat ./package.json | grep -v '\"private\":' > dist/package.json",
    "prepare": "npm run build"
  },

In questo modo non pubblicherai la cartella principale e otterrai il pacchetto compilato e package.json copiato distautomaticamente nella cartella, durante il processo di pubblicazione.


-1

Ecco un altro approccio che penso sia il più pulito. È tutto basato sulla configurazione senza la necessità di spostare file o specificare percorsi negli script di compilazione e pacchetto:

package.json Specifica il file principale.

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

Alcune opzioni aggiuntive per il dattiloscritto:

  • Specifica il file rootDir. Questa directory avrà tutto il codice sorgente e dovrebbe contenere un indexfile (o qualche altro file che puoi usare come main in package.json).
  • Specifica il file outDir. Qui è dove verrà costruito il tuo comando tsc

tsconfig.json

{
    "compilerOptions": {
        "rootDir": "src",
        "outDir": "lib",
    },
    ...

}

Non è lo stesso di quello che aveva originariamente l'OP, tranne cambiare il nome da dist a lib?
Bob9630

-1

opzione 1: vai alla cartella ed esegui "npm publish". comando

opzione 2: eseguire npm publish / path / directory


-4

Basta creare un .npmignorefile e aggiungere quanto segue:

*.*
!dist/*

1
fa ciò come richiesto dall'OP? Non sono riuscito a farlo funzionare. L'idea era di fare in modo che il pacchetto pubblicato contenesse solo il contenuto della directory dist senza includere la directory stessa. Ciò per assicurarci di non includere nulla che non sia nella directory dist che può già essere fatto con l'elenco dei "file" di package.json.
Bob9630
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.