如何npm发布特定文件夹但作为包根目录

rob*_*osa 46 package npm node-modules package.json

我有一个项目,包括一个gulp任务,用于构建和打包源和发布在一个名为的目录中dist.我的目标是将它作为npm包发布,但只发布我的dist文件夹.在NPM文件说,我可以使用files标签来指定文件输出.有用.但是,文档还说:

如果您在数组中命名文件夹,那么它还将包含该文件夹中的文件

结果是一个npm包,node_modules看起来像:

生成的npm包

但是我想在包的根目录下看到我的所有文件(没有该dist文件夹).我的index.js文件在dist文件夹中,但应该是root文件.我试图将标签设置files为/dist/**/*但不起作用.

我怎样才能实现它?

scv*_*vnc 27

我有同样的愿望,但我认为只有使用npm工具才能实现这一目标.可以使用另一个脚本/工具来安排您的包.

替代方案

目前我正在将我复制package.json到该dist文件夹中,然后npm pack在该dist文件夹中运行.我认为这基本上提供了我们的包装的理想安排.

以下是关于此npm设计的一些相关阅读:为什么Node中没有Directories.lib.

值得注意的是,jspm 在解析npm包时会尊重directories.lib选项package.json并重新排列文件.这一切都是为了我,因为我想构建一个可以被jspm或npm/webpack使用的公共库.

  • 我相信这个答案已经过时了。作为下面的响应,使用npm pack,package.json的files和main字段以及.npmignore可以为开发人员提供从特定的可安装目录创建软件包所需的一切。 (2认同)
  • 有人可以发布如何使用 npmignore、files 和 package.json 中的 main 属性来实现的解决方案吗?我想将所有文件移动到根目录并且没有 dist 文件夹 (2认同)
  • (为什么没有 Directory.lib...)作者的主张“做一件丑陋的事情应该看起来很丑”冒犯了所有 TypeScript 开发人员,并且一般来说,冒犯了所有使用编译器的开发人员。多年来,C++、.Net、Java 开发人员都将他们的项目编译到 lib/target/dist 文件夹,然后 JS 社区认为这个概念丑陋,这就是 npm 不支持它的原因。极好的。(那里没有评论部分,很抱歉在这里发布) (2认同)

Eli*_*nti 22

我有一个与原始海报(@robsonrosa)类似的问题。在我的情况下,我使用编译到dist目录的typecript 。虽然我可以让 typescript 编译到根目录,但我认为最好的解决方案是package.json在 dist 目录中生成一个单独的文件。
这类似于@scvnc 的复制建议,package.json但有一点不同:

作为打包过程的一部分,您应该package.json为包生成一个基于但不同于package.json根目录中的主文件的文件

理由:

  • 根package.json文件是开发文件。它可能包含对包用户无用的脚本或开发依赖项,但可能会给您带来安全问题。您的包装程序可能包含从生产中剥离该信息的代码package.json。
  • 您可能希望将您的包部署到不同的环境,这可能需要不同的包文件(例如,您可能希望拥有不同的版本或依赖项)。

- - 编辑 - -

我在评论中被要求提供解决方案。所以这是我正在使用的一些代码。这应该被视为一个例子,它并不意味着是通用的,而是特定于我的项目。

我的设置:

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.
Run Code Online (Sandbox Code Playgroud)

我只想打包dist目录,目录应该是包中的根目录。

该文件SetupPackage.ts在我的src目录将被编译为SetupPackage.js在dist由打字稿目录:

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();
Run Code Online (Sandbox Code Playgroud)

这个文件:

  • 复制根目录,package.json但删除包中不需要的脚本和开发依赖项。它还修复了包的主要入口点。
  • 将包的版本写入package.json一个名为version.txt.
  • .npmignore从根复制文件。

.npmignore 的内容是:

*.map
*.spec.*
SetupPackage.*
version.txt
Run Code Online (Sandbox Code Playgroud)

即单元测试(规范文件)和打字稿映射文件以及SetupPackage.js文件和version.txt它创建的文件被忽略。这留下了一个干净的包。

最后,主package.json文件具有以下脚本供构建系统使用(假设sh用作 shell)。

"scripts": {
    "compile": "tsc",
    "clean": "rm -rf dist",
    "prebuildpackage": "npm run clean && npm run compile && node dist/SetupPackage.js",
    "buildpackage": "cd dist && npm pack"
  },
Run Code Online (Sandbox Code Playgroud)

要构建包,构建系统会克隆 repo,执行npm install并依次运行npm run buildpackage:

  • 删除dist目录以确保干净的编译。
  • 将打字稿代码编译为 javascript。
  • 执行SetupPackage.js准备dist打包的文件。
  • cds 到dist目录并在那里构建包。

我使用该version.txt文件作为在 package.json 中获取版本并标记我的 repo 的一种简单方法。有无数其他方法可以做到这一点,或者您可能想要自动增加版本。如果它对您没有用处SetupPackage.ts,.npmignore请将其删除。

  • @yumaa我用一个具体的例子编辑了我的答案。希望它有用。 (3认同)

Thr*_*ram 9

我强烈建议您使用.npmignore而不是移动或复制东西,特别是如果您使用 CI 进行部署,并且只需在那里添加您不想发布的文件。

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

例子:

#tests
test
coverage

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

#linters
.jscsrc
.jshintrc
.eslintrc*

#editor settings
.idea
.editorconfig
Run Code Online (Sandbox Code Playgroud)

更新:

如果您想使用相同的 repo 将代码拆分为不同的 npm 包,我最近遇到了这个项目:Lerna,看起来非常好。

也许你应该看看

  • 我们仍然必须在包的根目录中发出我们构建的文件。或许对于 CI 是允许的。观察我链接到的 Isaac 博客中的帖子,并告诉我您的解决方案如何允许使用 `require('mypackage/foo')` 而不是 `require('mypackage/dist/foo')` (10认同)

Jac*_*k J 9

您需要发布该dist文件夹

根据 npm 方法,实现这一目标的自然方法是发布要成为根的文件夹。有多种方法可以做到这一点,具体取决于您想要使用的最终环境:

  1. npm 将 <folder>从您的软件包存储库发布到 npm 注册表,然后在安装其他软件包时将您的软件包安装在其他项目中。在你的情况下,它会是npm publish dist。
  2. 如果您只想在本地使用您的包,请在其他项目中npm install <folder> 。在你的情况下,你转到另一个项目并运行npm install relative/path/to/dist
  3. npm 将您的文件夹本地链接到node_modules另一个项目中的文件夹,以防您希望原始包中的更改立即反映在其他项目中。在您的情况下,您首先cd dist运行npm link,然后转到另一个项目并运行npm link robsonrosa-ui-alert。

先决条件:在上述任何情况下,在发布/安装/链接之前,您必须在dist文件夹中至少放入一个适当的package.json文件。在您的情况下,您必须将 package.json 文件中的包名称定义为"name": "robsonrosa-ui-alert"。通常,您还需要一些其他文件,例如 README.md 或 LICENSE。

方法 2 和 3 的备注

当您使用以这种方式安装的软件包时,通常会出现软件包依赖性问题。为了避免这种情况,请首先使用 打包软件包npm pack dist,然后从打包的 tarball(即npm install path/to/package-tarball.tgz.

自动化示例

prepare您可以使用script与 script 结合来自动化发布过程build。"private": true此外,您可以通过将字段放入 package.json(位于包存储库的根目录中)中来保护您的包,防止意外发布包根文件夹。这是一个例子:

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

这样,您就不会dist在发布过程中发布根文件夹并自动构建包并将 package.json 复制到该文件夹​​。

  • `npm 发布 ./dist` 有效 (5认同)
  • 当我执行“npmpublish dist”时,它会尝试推送名为“dist”的包,而不是使用“dist”文件夹。 (3认同)

Vah*_*hid 9

如果您(并且我推荐)使用语义发布,请pkgRoot在.releaserc.json文件中添加该选项。(您还应该安装rjp):

{
  "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",
      {
        "message": "Release <%= nextRelease.version %> [skip ci]",
        "assets": ["package.json", "CHANGELOG.md"]
      }
    ],
    "@semantic-release/changelog"
  ],
}
Run Code Online (Sandbox Code Playgroud)

这样就能解决问题了。只需确保您的dist文件夹包含一个package.json文件。您可以通过cp在postbuild脚本中添加 a 轻松做到这一点:

{
  "scripts": {
    "postbuild": "cp package.json dist"
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 8

cd TMPDIR
npm pack /path/to/package.json
Run Code Online (Sandbox Code Playgroud)

tarball 将在 TMPDIR 目录中创建。

  • ^这个答案被低估了。`npm pack` 加上 package.json `files` 字段(或 `.npmignore`)效果非常好。 (3认同)
  • 这如何回答OP问题? (3认同)

Den*_*Den 6

如果您的项目有git,则可以使用小型技巧。将下一个脚本添加到package.json

    "prepublishOnly": "npm run build && cp -r ./lib/* . && rm -rf ./lib",
    "postpublish": "git clean -fd",
Run Code Online (Sandbox Code Playgroud)

现在,当您运行publish命令npm涉及时prepublishOnly。它生成文件并将其保存到lib文件夹(生成脚本取决于您的项目)。下一条命令将文件复制到根文件夹并删除lib。发布postpublish脚本后,项目将返回到先前的状态。

  • 我是这个解决方案的粉丝! (2认同)