So veröffentlichen Sie einen bestimmten Ordner, aber als Paketstamm

86

Ich habe ein Projekt, das eine Schluckaufgabe zum Erstellen und Packen der Quellen und zur Veröffentlichung in einem Verzeichnis namens enthält dist. Mein Ziel ist es, es als npm-Paket zu veröffentlichen, aber nur meinen dist-Ordner. Die npm-Dokumentation besagt, dass ich das filesTag verwenden kann, um zu exportierende Dateien anzugeben. Es klappt. In der Dokumentation heißt es aber auch:

Wenn Sie einen Ordner im Array benennen, enthält er auch die Dateien in diesem Ordner

Das Ergebnis ist ein npm-Paket, das wie node_modules aussieht:

generiertes npm-Paket

Aber ich möchte alle meine Dateien im Stammverzeichnis des Pakets sehen (ohne diesen distOrdner). Meine index.jsDatei befindet sich im distOrdner, sollte sich aber im Stammverzeichnis befinden. Ich habe versucht, das Tag filesals festzulegen , /dist/**/*aber es hat nicht funktioniert.

Wie kann ich das erreichen?

robsonrosa
quelle

Antworten:

44

Ich habe den gleichen Wunsch, aber ich denke, es gibt keine Möglichkeit, dies nur mit npm-Werkzeugen zu erreichen . Ein anderes Skript / Tool könnte verwendet werden, um Ihr Paket zu arrangieren.

Alternative Lösung

Derzeit kopiere ich meine package.jsonin den distOrdner und laufe dann npm packinnerhalb des distOrdners. Ich denke, dies bietet im Wesentlichen die gewünschte Anordnung unseres Pakets.

Hier ist eine relevante Lektüre zu diesem npm-Design: Warum keine Directories.lib im Knoten .

Es ist auch interessant festzustellen, dass jspm die directories.libOption in berücksichtigt package.jsonund die Dateien beim Auflösen des npm-Pakets neu anordnet . Dies alles ist für mich entstanden, weil ich eine gemeinsame Bibliothek erstellen möchte, die von jspm oder npm / webpack verwendet werden kann.

scvnc
quelle
1
(Warum keine Directories.lib ...) ist ein toter Link
Shanimal
1
Warum keine Directories.lib in Node sagt, wenn Sie es nicht auf unsere Weise tun, sollten Sie Schmerzen fühlen. Dies führt lediglich dazu, dass Tools erforderlich sind, um dieses Problem zu umgehen.
Brian Takita
6
Ich glaube, diese Antwort ist veraltet. Wie die folgenden Antworten zeigen, verwenden Sie npm packdie Datei package.json filesund die mainFelder und .npmignoregeben einem Entwickler alles, was zum Erstellen eines Pakets aus einem bestimmten installierbaren Verzeichnis erforderlich ist.
Jefftopia
1
Einige Skripte erstellt , um das "Publish Subdir" -Muster zu optimieren / durchzusetzen
Micimize
2
Kann jemand die Lösung posten, wie sie mit npmignore, files und main property in package.json erreicht werden kann? Ich möchte alle Dateien in das Stammverzeichnis verschieben und habe keinen dist-Ordner
Angad
16

Ich habe ein ähnliches Problem wie das Originalposter (@robsonrosa). In meinem Fall verwende ich typecript, das in ein distVerzeichnis kompiliert wird . Obwohl ich Typoskript in das Stammverzeichnis kompilieren lassen könnte, denke ich, dass die beste Lösung darin besteht, eine separate package.jsonDatei im dist-Verzeichnis zu generieren .
Dies ähnelt dem Vorschlag von @scvnc, das zu kopieren, package.jsonjedoch mit einer Wendung:

Als Teil des Verpackungsprozesses sollten Sie eine package.jsonfür das Paket generieren , die auf der Hauptdatei package.jsonim Stammverzeichnis basiert, sich jedoch von dieser unterscheidet

Das Grundprinzip:

  • Die Stammdatei package.jsonist die Entwicklungsdatei. Es kann Skripte oder Entwicklungsabhängigkeiten enthalten, die für den Paketbenutzer nicht von Nutzen sind, aber Sicherheitsbedenken für Sie aufwerfen können. Ihr Verpackungsverfahren kann Code enthalten, der diese Informationen aus der Produktion entfernt package.json.
  • Möglicherweise möchten Sie Ihr Paket in verschiedenen Umgebungen bereitstellen, für die möglicherweise unterschiedliche Paketdateien erforderlich sind (z. B. möchten Sie möglicherweise unterschiedliche Versionen oder Abhängigkeiten haben).

--- BEARBEITEN ---

Ich wurde in den Kommentaren nach einer Lösung gefragt. Hier ist ein Code, den ich verwende. Dies sollte als Beispiel betrachtet werden, es ist nicht generisch gedacht und ist spezifisch für meine Projekte.

Mein Setup:

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.

Ich möchte nur das distVerzeichnis verpacken und das Verzeichnis sollte das Stammverzeichnis im Paket sein.

Die Datei SetupPackage.tsin meinem srcVerzeichnis wird per Typoskript SetupPackage.jsin das distVerzeichnis kompiliert :

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();

Diese Datei:

  • Kopiert das Stammverzeichnis package.json, entfernt jedoch die Skripte und Entwicklungsabhängigkeiten, die im Paket nicht benötigt werden. Außerdem wird der Haupteinstiegspunkt für das Paket festgelegt.
  • Schreibt die Version des Pakets aus package.jsonin eine aufgerufene Datei version.txt.
  • Kopiert das .npmignorePaket aus dem Stammverzeichnis.

Der .npmignore-Inhalt lautet:

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

Dh Unit-Tests (Spezifikationsdateien) und Typoskript-Map-Dateien werden ebenso ignoriert wie die SetupPackage.jsDatei und die version.txtDatei, die sie erstellt. Dies hinterlässt ein sauberes Paket.

Schließlich enthält die Hauptdatei package.jsondie folgenden Skripts zur Verwendung durch das Build-System (vorausgesetzt, sie shwird als Shell verwendet).

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

Um das Paket zu erstellen, klont das Build-System das Repo, führt es aus npm installund führt es dann aus, npm run buildpackagewas wiederum:

  • Löscht das distVerzeichnis, um eine saubere Kompilierung zu gewährleisten.
  • Kompiliert den Typoskript-Code in Javascript.
  • Führt die SetupPackage.jsDatei aus, die das distVerpacken vorbereitet .
  • CDs in das distVerzeichnis und erstellt das Paket dort.

Ich benutze die version.txtDatei als einfache Möglichkeit, die Version in package.json zu erhalten und mein Repo zu markieren. Es gibt unzählige andere Möglichkeiten, dies zu tun, oder Sie möchten die Version automatisch inkrementieren. Entfernen Sie dies aus SetupPackage.tsund .npmignorewenn es für Sie nicht nützlich ist.

Eli Algranti
quelle
Diese Antwort sieht aus wie die beste, aber haben Sie neben der Theorie eine Lösung parat?
Yumaa
3
@yumaa Ich habe meine Antwort mit einem konkreten Beispiel bearbeitet. Hoffe es ist nützlich.
Eli Algranti
13

Wenn Ihr Projekt Git hat, können Sie einen kleinen Hack verwenden. Fügen Sie die nächsten Skripte zu package.json hinzu

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

jetzt, wenn Sie den publishBefehl npm ausführen, einbeziehen prepublishOnly. Es erstellt Dateien und speichert sie in einem libOrdner (ein Build-Skript hängt von Ihrem Projekt ab). Der nächste Befehl kopiert Dateien in den Stammordner und entfernt sie lib. Nach dem Veröffentlichen des postpublishSkripts wird das Projekt auf einen vorherigen Status zurückgesetzt.

Den
quelle
1
Ich bin ein Fan dieser Lösung!
DanMad
6

Ich empfehle Ihnen dringend .npmignore, Dinge zu verwenden, anstatt sie zu verschieben oder zu kopieren, insbesondere wenn Sie ein CI für Bereitstellungen verwenden, und dort einfach die Dateien hinzuzufügen, die Sie nicht veröffentlichen möchten.

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

Beispiel:

#tests
test
coverage

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

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

Aktualisieren:

Wenn Sie Ihren Code mit demselben Repo in verschiedene npm-Pakete aufteilen möchten, bin ich kürzlich auf dieses Projekt gestoßen: Lerna und sieht wirklich gut aus.

Vielleicht solltest du einen Blick darauf werfen

Thram
quelle
9
Wir müssten unsere erstellten Dateien immer noch im Stammverzeichnis des Pakets ausgeben. Möglicherweise für CI zulässig. Beobachten Sie den Beitrag aus Isaacs Blog, auf den ich verlinkt habe, und sagen Sie mir, wie Ihre Lösung dies ermöglichen würde, require('mypackage/foo')anstattrequire('mypackage/dist/foo')
scvnc
Ich habe hier nicht versucht, dieses Problem zu lösen. Wenn Sie Ihren Code teilen möchten, bin ich kürzlich auf dieses Projekt gestoßen: lernajs.io und sieht wirklich gut aus
Thram
Fand ein anderes Tool, das einen Blick wert ist :) github.com/philcockfield/msync
Thram
yeh Material UI verwenden es und ich habe es in verwendet. Meine letzte Firma, ich fand es ok
Nick
5

Das funktioniert gut für mich.

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

Tarball wird im TMPDIR-Verzeichnis erstellt.

Nadeeshan Gimhana
quelle
^ Diese Antwort wird unterschätzt. npm packAußerdem funktioniert das filesFeld package.json (oder .npmignore) wunderbar.
Jefftopia
1

Sie müssen den distOrdner veröffentlichen

Der natürliche Weg, dies zu erreichen, besteht nach dem npm-Ansatz darin, den Ordner zu veröffentlichen, der das Stammverzeichnis sein soll. Es gibt verschiedene Möglichkeiten, dies zu tun, abhängig von der endgültigen Umgebung, mit der Sie arbeiten möchten:

  1. npm veröffentlicht <Ordner> von Ihrem Paket-Repo in einer npm-Registrierung und installiert Ihr Paket dann in einem anderen Projekt, während Sie andere Pakete installieren. In deinem Fall wäre es npm publish dist.
  2. npm installiert <Ordner> in einem anderen Projekt, wenn Sie Ihr Paket nur lokal verwenden möchten. In Ihrem Fall gehen Sie zum anderen Projekt und führen es ausnpm install relative/path/to/dist
  3. npm verknüpfen Sie Ihren Ordner lokal mit Ihrem Ordner node_modulesin einem anderen Projekt, falls Sie möchten, dass die Änderungen in Ihrem Originalpaket sofort in einem anderen Projekt übernommen werden. In Ihrem Fall führen Sie zuerst cd distaus npm linkund gehen dann zum anderen Projekt und führen es aus npm link robsonrosa-ui-alert.

Voraussetzung : In jedem Fall müssen Sie vor dem Veröffentlichen / Installieren / Verknüpfen distmindestens eine ordnungsgemäße package.jsonDatei in Ihren Ordner einfügen . In Ihrem Fall muss der Paketname in Ihrer Datei package.json als definiert sein "name": "robsonrosa-ui-alert". Normalerweise möchten Sie dort auch einige andere Dateien wie README.md oder LICENSE.

Automatisierungsbeispiel

Sie können den Veröffentlichungsprozess mithilfe des prepareSkripts in Kombination mit dem buildSkript automatisieren . Darüber hinaus können Sie Ihr Paket vor einer versehentlichen Veröffentlichung des Paketstammordners schützen. Das "private": trueFeld befindet sich in der Datei package.json im Stammverzeichnis Ihres Paketrepos. Hier ist ein Beispiel:

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

Auf diese Weise veröffentlichen Sie den Stammordner nicht und erhalten das Paket erstellt und package.json wird während distdes Veröffentlichungsprozesses automatisch in den Ordner kopiert .

Jacek J.
quelle
0

Option 1: Navigieren Sie zum Ordner und führen Sie "npm Publish" aus. Befehl

Option 2: Führen Sie npm Publish / Path / Directory aus

Sasi Kumar M.
quelle
-1

Hier ist noch ein Ansatz, den ich für den saubersten halte. Es ist alles konfigurationsbasiert, ohne dass Dateien verschoben oder Pfade in den Build- und Pack-Skripten angegeben werden müssen:

package.json Geben Sie die Hauptdatei an.

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

Einige zusätzliche Typoskriptoptionen:

  • Geben Sie die an rootDir. Dieses Verzeichnis enthält den gesamten Quellcode und sollte eine indexDatei enthalten (oder eine andere Datei, die Sie als Hauptdatei in der verwenden können package.json).
  • Geben Sie die an outDir. Hier wird Ihr tsc-Befehl erstellt

tsconfig.json

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

}
scottmgerstl
quelle
Ist das nicht dasselbe wie das, was das OP ursprünglich hatte, außer dass der Name von dist in lib geändert wurde?
Bob9630
-3

Erstellen Sie einfach eine .npmignoreDatei und fügen Sie Folgendes hinzu:

*.*
!dist/*
Maurice
quelle
1
Funktioniert dies wie vom OP angefordert? Ich konnte das nicht zum Laufen bringen. Die Idee war, dass das veröffentlichte Paket nur den Inhalt des dist-Verzeichnisses enthält, ohne das Verzeichnis selbst einzuschließen. Damit stellen wir sicher, dass wir nichts in das dist-Verzeichnis aufnehmen, was bereits mit der Liste "files" von package.json möglich ist.
Bob9630