Cómo npm publicar una carpeta específica pero como raíz del paquete

86

Tengo un proyecto que incluye una tarea de trago para construir y empaquetar las fuentes y publicarlas en un directorio llamado dist. Mi objetivo es publicarlo como un paquete npm, pero solo mi carpeta dist. La documentación de npm dice que puedo usar la filesetiqueta para especificar archivos para exportar. Funciona. Pero, la documentación también dice que:

Si nombra una carpeta en la matriz, también incluirá los archivos dentro de esa carpeta

El resultado es un paquete npm, que node_modules se ve así:

paquete npm generado

Pero me gustaría ver todos mis archivos en la raíz del paquete (sin esa distcarpeta). Mi index.jsarchivo está dentro de la distcarpeta, pero debería estar en la raíz. Intenté configurar la etiqueta filescomo /dist/**/*pero no funcionó.

¿Cómo puedo lograrlo?

robsonrosa
fuente

Respuestas:

44

Tengo el mismo deseo, pero creo que no hay forma de lograr esto con solo usar herramientas npm . Se podría utilizar otro script / herramienta para organizar su paquete.

Solución alternativa

Actualmente estoy copiando mi package.jsonen la distcarpeta y luego ejecutándolo npm packdentro de la distcarpeta. Creo que esto esencialmente proporciona la disposición deseada de nuestro paquete.

Aquí hay algunas lecturas relevantes sobre este diseño de npm: ¿Por qué no Directories.lib en Node .

También es interesante notar que jspm SÍ respeta la directories.libopción package.jsony reorganiza los archivos al resolver el paquete npm. Todo esto ha sucedido para mí porque quiero construir una biblioteca común que pueda ser consumida por jspm o npm / webpack.

scvnc
fuente
1
(Why no Directories.lib ...) es un enlace muerto
Shanimal
1
Por qué no Directories.lib en Node dice, si no lo haces a nuestra manera, deberías sentir dolor. Todo esto crea la necesidad de herramientas para solucionar este problema.
Brian Takita
6
Creo que esta respuesta está desactualizada. Como se indica en las respuestas a continuación, el uso de npm packpackage.json filesy maincampos, y .npmignorele da al desarrollador todo lo necesario para crear un paquete desde un directorio instalable específico.
Jefftopia
1
Hicimos algunos scripts para optimizar / hacer cumplir el patrón "publicar subdirectorio"
micimize el
2
¿Alguien puede publicar la solución sobre cómo se puede lograr usando npmignore, files y la propiedad principal en package.json? Quiero mover todos los archivos a la raíz y no tener la carpeta dist
Angad
16

Tengo un problema similar al del cartel original (@robsonrosa). En mi caso, uso mecanografiado que se compila en un distdirectorio. Si bien podría compilar mecanografiado en el directorio raíz, creo que la mejor solución es generar un package.jsonarchivo separado en el directorio dist.
Esto es similar a la sugerencia de @scvnc de copiar el package.jsonpero con un giro:

Como parte del proceso de empaquetado, debe generar un archivo package.jsonpara el paquete que se base en el package.jsonarchivo principal del directorio raíz pero sea distinto del mismo.

Lo racional:

  • El package.jsonarchivo raíz es el archivo de desarrollo. Puede contener scripts o dependencias de desarrollo que no son útiles para el usuario del paquete, pero pueden plantearle problemas de seguridad. Su procedimiento de empaque puede incluir un código que elimine esa información de la producción package.json.
  • Es posible que desee implementar su paquete en diferentes entornos que pueden requerir diferentes archivos de paquete (por ejemplo, es posible que desee tener diferentes versiones o dependencias).

--- EDITAR ---

Se me pidió una solución en los comentarios. Así que aquí hay un código que estoy usando. Esto debe considerarse como un ejemplo, no pretende ser genérico y es específico de mis proyectos.

Mi configuración:

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.

Quiero empaquetar solo el distdirectorio y el directorio debe ser el directorio raíz del paquete.

El archivo SetupPackage.tsen mi srcdirectorio se compilará SetupPackage.jsen el distdirectorio por mecanografiado:

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

Este archivo:

  • Copia la raíz package.jsonpero elimina los scripts y las dependencias de desarrollo que no son necesarios en el paquete. También corrige el punto de entrada principal al paquete.
  • Escribe la versión del paquete package.jsonen un archivo llamado version.txt.
  • Copia el .npmignorepaquete desde la raíz.

El contenido .npmignore es:

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

Es decir, las pruebas unitarias (archivos de especificaciones) y los archivos de mapas mecanografiados se ignoran, así como el SetupPackage.jsarchivo y el version.txtarchivo que crea. Esto deja un paquete limpio.

Finalmente, el package.jsonarchivo principal tiene los siguientes scripts para que los utilice el sistema de compilación (se supone que shse utiliza como shell).

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

Para compilar el paquete, el sistema de compilación clona el repositorio, lo hace npm instally luego lo ejecuta, lo npm run buildpackageque a su vez:

  • Elimina el distdirectorio asegurando una compilación limpia.
  • Compila el código mecanografiado en javascript.
  • Ejecuta el SetupPackage.jsarchivo que prepara distpara empaquetar.
  • cds al distdirectorio y compila el paquete allí.

Utilizo el version.txtarchivo como una manera fácil de obtener la versión en package.json y etiquetar mi repositorio. Hay muchas otras formas de hacer esto o puede que desee incrementar automáticamente la versión. Elimínelo de SetupPackage.tsy .npmignoresi no le resulta útil.

Eli Algranti
fuente
Esta respuesta parece la mejor, pero ¿tiene una solución lista aparte de la teoría?
yumaa
3
@yumaa He editado mi respuesta con un ejemplo concreto. Espero que sea de utilidad.
Eli Algranti
13

Si su proyecto tiene git, puede usar un pequeño truco. Agregue los siguientes scripts a package.json

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

ahora, cuando ejecute el publishcomando npm involucre prepublishOnly. Crea archivos y los guarda en una libcarpeta (un script de construcción depende de su proyecto). El siguiente comando copia archivos a la carpeta raíz y los elimina lib. Después de publicar, el postpublishscript devuelve el proyecto a un estado anterior.

Guarida
fuente
1
¡Soy fanático de esta solución!
DanMad
6

Le recomiendo encarecidamente que use en .npmignorelugar de mover o copiar cosas, especialmente si está usando un CI para implementaciones, y simplemente agregue allí los archivos que no desea publicar.

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

Ejemplo:

#tests
test
coverage

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

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

Actualizar:

Si desea dividir su código en diferentes paquetes npm usando el mismo repositorio, me topé con este proyecto recientemente: Lerna y se ve muy bien.

Tal vez deberías echar un vistazo

Thram
fuente
9
Aún tendríamos que emitir nuestros archivos construidos en el directorio raíz del paquete. Quizás permitido para CI. Observe la publicación del blog de Isaac al que me require('mypackage/foo')require('mypackage/dist/foo')
vinculé
No estaba tratando de resolver ese problema aquí. Si desea dividir su código, me topé con este proyecto recientemente: lernajs.io y se ve muy bien
Thram
Encontré otra herramienta que vale la pena echarle un vistazo :) github.com/philcockfield/msync
Thram
yeh material UI lo uso y lo usé en mi última compañía, lo encontré bien
nick
5

Esto funciona bien para mi.

cd TMPDIR; npm pack/ruta/a/paquete.json

Tarball creará dentro del directorio TMPDIR.

Nadeeshan Gimhana
fuente
^ Esta respuesta está subestimada. npm packademás, el filescampo package.json (o .npmignore) funciona maravillosamente.
Jefftopia
0

opción 1: Navegue a la carpeta y ejecute "npm publish". mando

opción 2: Ejecute npm publish / path / directory

Sasi Kumar M
fuente
0

Necesitas publicar la distcarpeta

La forma natural de lograrlo, según el enfoque de npm, es publicar la carpeta que será la raíz. Hay varias formas de hacerlo, dependiendo del entorno final con el que desee trabajar:

  1. npm publique <carpeta> desde su repositorio de paquetes en un registro de npm y luego instale su paquete en otro proyecto mientras instala otros paquetes. En tu caso lo sería npm publish dist.
  2. npm instala <carpeta> en algún otro proyecto si quieres usar tu paquete solo localmente. En su caso, vaya al otro proyecto y ejecutenpm install relative/path/to/dist
  3. npm vincula tu carpeta localmente a tu node_modulesen otro proyecto en caso de que quieras que los cambios en tu paquete original se reflejen instantáneamente en otro proyecto. En su caso, primero cd disty ejecute npm linky luego vaya al otro proyecto y ejecute npm link robsonrosa-ui-alert.

Requisito previo: en cualquier caso anterior, antes de publicar / instalar / enlace, debe colocar en su distcarpeta al menos un package.jsonarchivo adecuado . En su caso, debe tener el nombre del paquete definido en su archivo package.json como "name": "robsonrosa-ui-alert". Normalmente, querrá que haya otros archivos como README.md o LICENSE.

Ejemplo de automatización

Puede automatizar el proceso de publicación utilizando el preparescript , combinado con el buildscript. Además, puede proteger su paquete contra una publicación accidental de la carpeta raíz del paquete con el "private": truecampo incluido en el paquete.json, ubicado en el directorio raíz de su repositorio de paquetes. Aquí hay un ejemplo:

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

De esta forma, no publicará la carpeta raíz y obtendrá el paquete compilado y package.json copiado en la distcarpeta automáticamente, dentro del proceso de publicación.

Jacek J
fuente
-1

Aquí hay un enfoque más que creo que es el más limpio. Todo se basa en la configuración sin necesidad de mover archivos o especificar rutas en los scripts de compilación y paquete:

package.json Especifique el archivo principal.

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

Algunas opciones adicionales de mecanografiado:

  • Especifique el rootDir. Este directorio tendrá todo el código fuente y debería tener un indexarchivo en él (o algún otro archivo que pueda usar como principal en el package.json).
  • Especifique el outDir. Aquí es donde se construirá su comando tsc

tsconfig.json

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

}
scottmgerstl
fuente
¿No es esto lo mismo que tenía originalmente el OP excepto cambiar el nombre de dist a lib?
Bob9630
-3

Simplemente cree un .npmignorearchivo y agregue lo siguiente:

*.*
!dist/*
Maurice
fuente
1
¿Esto hace lo que pidió el OP? No pude hacer que esto funcionara. La idea era hacer que el paquete publicado contuviera solo el contenido del directorio dist sin incluir el directorio en sí. Esto para asegurarnos de que no incluyamos nada que no esté en el directorio dist que ya se pueda hacer con la lista de "archivos" de package.json.
Bob9630