Como publicar npm uma pasta específica, mas como raiz do pacote

91

Eu tenho um projeto que inclui uma tarefa gulp para compilar e empacotar os códigos-fonte e liberar em um diretório chamado dist. Meu objetivo é publicá-lo como um pacote npm, mas apenas minha pasta dist. A documentação do npm diz que posso usar a filestag para especificar os arquivos a serem exportados. Funciona. Mas, a documentação também diz que:

Se você nomear uma pasta na matriz, ela também incluirá os arquivos dentro dessa pasta

O resultado é um pacote npm, cujo node_modules se parece com:

pacote npm gerado

Mas gostaria de ver todos os meus arquivos na raiz do pacote (sem essa distpasta). Meu index.jsarquivo está dentro da distpasta, mas deve estar na raiz. Tentei definir a tag filescomo, /dist/**/*mas não funcionou.

Como posso conseguir isso?

robsonrosa
fonte

Respostas:

45

Eu tenho o mesmo desejo, mas acho que não há como conseguir isso usando apenas o NPM Tooling . Outro script / ferramenta pode ser usado para organizar seu pacote.

Solução alternativa

Atualmente estou copiando meu package.jsonpara a distpasta e executando npm packdentro da distpasta. Acho que isso fornece essencialmente a disposição desejada de nosso pacote.

Aqui estão algumas leituras relevantes sobre o design do npm: Por que nenhum Directories.lib no Node .

Também é interessante notar que jspm respeita a directories.libopção em package.jsone reorganiza os arquivos ao resolver o pacote npm. Tudo isso aconteceu para mim porque estou querendo construir uma biblioteca comum que pode ser consumida por jspm ou npm / webpack.

scvnc
fonte
1
(Por que nenhum Directories.lib ...) é um link morto
Shanimal
1
Por que nenhum Directories.lib em Node está dizendo, se você não fizer do nosso jeito, você deve sentir dor. Tudo isso cria a necessidade de ferramentas para contornar esse problema.
Brian Takita
6
Eu acredito que esta resposta está desatualizada. Conforme as respostas abaixo, observe, usando npm pack, o package.json filese os maincampos, e .npmignorefornece ao desenvolvedor tudo o que é necessário para criar um pacote a partir de um diretório instalável específico.
Jefftopia
1
Fiz alguns scripts para otimizar / aplicar o padrão "publicar subdir"
micimize
2
Alguém pode postar a solução de como ela pode ser alcançada usando npmignore, arquivos e propriedade principal em package.json. Quero mover todos os arquivos para a raiz e não ter a pasta dist
Angad
17

Tenho um problema semelhante ao do autor da postagem original (@robsonrosa). No meu caso, eu uso o typecript que compila em um distdiretório. Embora eu possa fazer a compilação do typescript para o diretório raiz, acho que a melhor solução é gerar um package.jsonarquivo separado no diretório dist.
Isso é semelhante à sugestão @scvnc de copiar o, package.jsonmas com uma torção:

Como parte do processo de empacotamento, você deve gerar um package.jsonpara o pacote que se baseia, mas é diferente do package.jsonarquivo principal no diretório raiz

A justificativa:

  • O package.jsonarquivo raiz é o arquivo de desenvolvimento. Ele pode conter scripts ou dependências de desenvolvimento que não são úteis para o usuário do pacote, mas podem representar questões de segurança para você. Seu procedimento de embalagem pode incluir um código que retira essas informações da produção package.json.
  • Você pode querer implantar seu pacote em ambientes diferentes que podem exigir arquivos de pacote diferentes (por exemplo, você pode querer ter versões ou dependências diferentes).

--- EDITAR ---

Pediram-me uma solução nos comentários. Portanto, aqui está um código que estou usando. Isso deve ser considerado como um exemplo, não se destina a ser genérico e é específico para meus projetos.

Minha configuração:

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.

Desejo empacotar apenas o distdiretório e o diretório deve ser o diretório raiz do pacote.

O arquivo SetupPackage.tsem meu srcdiretório será compilado SetupPackage.jsno distdiretório por typescript:

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 ficheiro:

  • Copia a raiz, package.jsonmas remove os scripts e dependências de desenvolvimento que não são necessários no pacote. Ele também corrige o principal ponto de entrada do pacote.
  • Grava a versão do pacote package.jsonem um arquivo chamado version.txt.
  • Copia o .npmignorepacote da raiz.

O conteúdo .npmignore é:

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

Ou seja, os testes de unidade (arquivos de especificação) e os arquivos de mapa de digitação são ignorados, assim como o SetupPackage.jsarquivo e o version.txtarquivo que ele cria. Isso deixa um pacote limpo.

Finalmente, o package.jsonarquivo principal tem os seguintes scripts para uso pelo sistema de compilação (assume que shé usado como o 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 construir o pacote, o sistema de compilação clona o repo, faz npm installe, em seguida, executa o npm run buildpackageque, por sua vez:

  • Exclui o distdiretório garantindo uma compilação limpa.
  • Compila o código typescript para javascript.
  • Executa o SetupPackage.jsarquivo que prepara distpara empacotamento.
  • cds para o distdiretório e cria o pacote lá.

Eu uso o version.txtarquivo como uma maneira fácil de obter a versão em package.json e marcar meu repo. Existem inúmeras outras maneiras de fazer isso ou você pode querer incrementar automaticamente a versão. Remova isso de SetupPackage.tse .npmignorese não for útil para você.

Eli Algranti
fonte
Esta resposta parece ser a melhor, mas você tem uma solução pronta além da teoria?
yumaa
3
@yumaa Eu editei minha resposta com um exemplo concreto. Espero que seja útil.
Eli Algranti
1
Funcionou para mim com algumas mudanças. O SetupPackage.tsarquivo atual copia os arquivos para o srcdiretório em vez de dist. Obrigado 👍
Harinder Singh
15

Se seu projeto tem git, você pode usar o pequeno hack. Adicione os próximos scripts a package.json

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

agora, quando você executa o publishcomando npm envolve prepublishOnly. Ele cria arquivos e os salva em uma libpasta (um script de construção depende do seu projeto). O próximo comando copia os arquivos para a pasta raiz e os remove lib. Após a publicação, o postpublishscript retorna o projeto a um estado anterior.

Den
fonte
1
Sou fã dessa solução!
DanMad
7

Eu recomendo fortemente que você use ao .npmignoreinvés de mover ou copiar coisas, especialmente se você estiver usando um CI para implantações, e apenas adicionar lá os arquivos que você não deseja publicar.

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

Exemplo:

#tests
test
coverage

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

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig

Atualizar:

Se você quiser dividir seu código em diferentes pacotes npm usando o mesmo repo, me deparei com este projeto recentemente: Lerna e parece realmente bom.

Talvez você devesse dar uma olhada

Thram
fonte
9
Ainda teríamos que emitir nossos arquivos construídos no diretório raiz do pacote. Talvez permitido para CI. Observe a postagem do blog de Isaac que eu require('mypackage/foo')require('mypackage/dist/foo')
vinculei
Eu não estava tentando resolver esse problema aqui. Se você quiser dividir seu código, me deparei com este projeto recentemente: lernajs.io e parece muito bom
Thram
Encontrei outra ferramenta que vale a pena dar uma olhada :) github.com/philcockfield/msync
Thram
yeh material IU use-o e eu usei isso em minha última empresa, achei ok
nick
6

Este trabalho é bom para mim.

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

O Tarball criará dentro do diretório TMPDIR.

Nadeeshan Gimana
fonte
^ Esta resposta é subestimada. npm packmais o filescampo package.json (ou .npmignore) funciona maravilhosamente bem.
Jefftopia
1

Se você estiver (e eu recomendo) usando liberação semântica , adicione a pkgRootopção no .releaserc.jsonarquivo:

{
  "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"]
      }
    ],

  ],
}

Isso resolverá o problema. Apenas certifique-se de que sua distpasta contém um package.jsonarquivo. Você pode fazer isso facilmente adicionando um cpao seu postbuildscript. Também instale o rjp

Vahid
fonte
0

Você precisa publicar a distpasta

A maneira natural de conseguir isso, de acordo com a abordagem do npm, é publicar a pasta que será a raiz. Existem várias maneiras de fazer isso, dependendo do ambiente final com o qual você deseja trabalhar:

  1. npm publicar <pasta> de seu repositório de pacotes para um registro npm e, em seguida, instalar seu pacote em outro projeto à medida que instala outros pacotes. No seu caso, seria npm publish dist.
  2. npm install <folder> em algum outro projeto se você quiser usar seu pacote apenas localmente. No seu caso, você vai para o outro projeto e executanpm install relative/path/to/dist
  3. npm vincule sua pasta localmente à sua node_modulesem outro projeto, caso deseje que as alterações no pacote original sejam refletidas instantaneamente em outro projeto. No seu caso, você primeiro cd distexecuta npm linke depois vai para o outro projeto e executa npm link robsonrosa-ui-alert.

Pré - requisito : em qualquer caso acima, antes de publicar / instalar / vincular, você deve colocar em sua distpasta pelo menos um package.jsonarquivo adequado . No seu caso, você deve ter o nome do pacote definido em seu arquivo package.json como "name": "robsonrosa-ui-alert". Normalmente, você também desejará alguns outros arquivos como README.md ou LICENSE.

Observações aos métodos 2 e 3

Normalmente, há problemas com dependências de pacote quando você usa o pacote instalado dessa maneira. Para evitá-lo, primeiro empacote o pacote npm pack diste depois instale-o no projeto de destino a partir do tarball compactado, ou seja npm install path/to/package-tarball.tgz.

Exemplo de automação

Você pode automatizar o processo de publicação usando o preparescript , combinado com o buildscript. Além disso, você pode proteger seu pacote contra uma publicação acidental da pasta raiz do pacote com o "private": truecampo colocado em package.json, localizado no diretório raiz de seu repo de pacote. Aqui está um exemplo:

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

Dessa forma, você não publicará a pasta raiz e obterá o pacote criado e o package.json copiado para a distpasta automaticamente, dentro do processo de publicação.

Jacek J
fonte
-1

Aqui está mais uma abordagem que considero a mais limpa. É tudo baseado em configuração, sem a necessidade de mover arquivos ou especificar caminhos nos scripts de compilação e pacote:

package.json Especifique o arquivo principal.

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

Algumas opções adicionais de datilografia:

  • Especifique o rootDir. Este diretório terá todo o código fonte e deverá conter um indexarquivo (ou algum outro arquivo que você possa usar como principal no package.json).
  • Especifique o outDir. É aqui que o seu comando tsc será construído para

tsconfig.json

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

}
Scottmgerstl
fonte
Não é o mesmo que o OP tinha originalmente, exceto alterar o nome de dist para lib?
Bob9630
-1

opção 1: navegue até a pasta e execute "npm publish." comando

opção 2: execute npm publicar / caminho / diretório

Sasi Kumar M
fonte
-4

Basta criar um .npmignorearquivo e adicionar o seguinte a ele:

*.*
!dist/*
Maurice
fonte
1
isso faz como o OP solicitou? Eu não fui capaz de fazer isso funcionar. A ideia era fazer com que o pacote publicado contivesse apenas o conteúdo do diretório dist sem incluir o próprio diretório. Isso para garantir que não incluamos nada que não esteja no diretório dist, o que já pode ser feito com a lista de "arquivos" package.json
Bob9630