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


85

我有一个项目,其中包含一个gulp任务,用于构建和打包源并将其发布在名为的目录中dist。我的目标是将其发布为npm软件包,但仅发布dist文件夹。在NPM文件说,我可以使用files标签来指定文件导出。有用。但是,文档还说:

如果您在阵列中命名一个文件夹,那么它还将包括该文件夹中的文件

结果是一个npm包,其node_modules如下所示:

生成的npm包

但我想在软件包的根目录(没有该dist文件夹)中查看我的所有文件。我的index.js文件在dist文件夹中,但应位于根目录。我尝试将标签设置files为,/dist/**/*但没有成功。

我该如何实现?

Answers:


43

我有同样的愿望,但我认为仅使用npm工具是无法实现这一目标的。可以使用其他脚本/工具来安排您的包裹。

替代解决方案

当前,我将我复制package.json到该dist文件夹中,然后npm pack在该dist文件夹中运行。我认为这实质上提供了我们软件包的所需安排。

这是有关此npm设计的一些相关读物:为什么Node中没有Directories.lib

有趣的是,在解析npm包时,jspm确实尊重该directories.lib选项package.json并重新排列文件。这一切对我来说都是因为我想建立一个可以被jspm或npm / webpack使用的公共库。


1
(为什么没有Directories.lib ...)是固定链接
Shanimal

1
为什么Node中没有Directories.lib会说,如果不按照我们的方式去做,您会感到痛苦。所有这一切都需要工具来解决此问题。
Brian Takita

6
我相信这个答案已经过时了。作为下面的响应,请使用npm pack,package.jsonfilesmain字段,并.npmignore为开发人员提供了从特定的可安装目录创建软件包所需的一切。
Jefftopia

1
制作了一些脚本来简化/执行“ publish subdir”模式
最小化

2
有人可以发布解决方案如何使用package.json中的npmignore,文件和main属性来实现。我想对所有的文件移动到根,而不必DIST文件夹
•安格德

16

我有与原始海报(@robsonrosa)类似的问题。在我的情况下,我使用typecript编译到dist目录。虽然我可以使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.

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

SetupPackage.tssrc目录中的文件将通过打字稿编译到SetupPackage.jsdist目录中:

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

这个文件:

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

.npmignore内容是:

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

即,单元测试(规范文件)和打字稿映射文件以及该SetupPackage.js文件及其version.txt创建的文件都将被忽略。这样就留下了干净的包装。

最后,主package.json文件具有以下供构建系统使用的脚本(假定sh用作外壳程序)。

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

要构建软件包,构建系统会克隆存储库,npm install然后执行npm run buildpackage,然后依次运行:

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

我使用该version.txt文件作为在package.json中获取版本并标记存储库的简便方法。有许多其他方法可以执行此操作,或者您可能想自动增加版本。从删除此SetupPackage.ts.npmignore如果不是对你有用。


这个答案似乎是最好的答案,但是除了理论之外,您还有现成的解决方案吗?
yumaa

3
@yumaa我用一个具体的例子编辑了我的答案。希望它是有用的。
伊莱·阿格兰提

13

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

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

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


1
我是这个解决方案的粉丝!
DanMad

6

我强烈建议您使用.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

更新:

如果您想使用同一存储库将代码拆分为不同的npm软件包,我最近碰到了这个项目:Lerna,看起来非常不错。

也许你应该看看


9
我们仍然必须在包的根目录中发出构建的文件。CI可能是允许的。查看我链接到的Isaac博客中的帖子,并告诉我您的解决方案将允许require('mypackage/foo')代替require('mypackage/dist/foo')
scvnc

我不是要在这里解决这个问题。如果您想拆分您的代码,我最近碰到了这个项目:lernajs.io,看起来非常不错
Thram

找到了另一个值得一看的工具:) github.com/philcockfield/msync
Thram

这些材料UI使用了它,我用了它。在我的上一家公司,我觉得还好
尼克

4

这对我来说很好。

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

Tarball将在TMPDIR目录中创建。


^这个答案被低估了。npm pack加上package.jsonfiles字段(或.npmignore)效果很好。
Jefftopia


0

您需要发布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。

自动化实例

您可以使用自动化的出版过程prepare脚本,结合build脚本。此外,您可以保护您的软件包,以防意外发布软件包根文件夹,而该软件包的根文件夹"private": true位于package repo根目录中的package.json中。这是一个例子:

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

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


-1

我认为这是最干净的另一种方法。都是基于配置的,无需移动文件或在build和pack脚本中指定路径:

package.json 指定主文件。

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

一些其他打字稿选项:

  • 指定rootDir。该目录将包含所有源代码,并且其中应包含一个index文件(或您可以在中用作主文件的其他文件package.json)。
  • 指定outDir。这是您的tsc命令生成的地方

tsconfig.json

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

}

除了将名称从dist更改为lib之外,这是否与OP最初的功能相同?
Bob9630 '19

-3

只需创建一个.npmignore文件,然后向其中添加以下内容:

*.*
!dist/*

1
这是否符合OP的要求?我无法使它正常工作。想法是使已发布的程序包仅包含dist目录的内容,而不包含目录本身。我这样做是为了确保我们不会在dist目录中包含任何可以通过package.json“文件”列表完成的内容。
Bob9630 '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.