我有一个项目,其中包含一个 gulp 任务,用于在名为 dist
的目录中构建和打包源代码和发布。我的目标是将它发布为一个 npm 包,但只发布我的 dist 文件夹。 npm documentation 表示我可以使用 files
标记来指定要导出的文件。有用。但是,文档还说:
如果您在数组中命名一个文件夹,那么它还将包括该文件夹内的文件
结果是一个 npm 包,它的 node_modules 看起来像:
https://i.stack.imgur.com/qWzv7.png
但我想在包的根目录(没有那个 dist
文件夹)查看我的所有文件。我的 index.js
文件位于 dist
文件夹中,但应该位于根目录下。我尝试将标签 files
设置为 /dist/**/*
,但没有成功。
我怎样才能实现它?
我有同样的愿望,但我认为仅使用 npm 工具是无法实现的。另一个脚本/工具可用于安排您的包裹。
替代解决方案
目前我正在将我的 package.json
复制到 dist
文件夹中,然后在 dist
文件夹中运行 npm pack
。我认为这基本上提供了我们所需的包装安排。
以下是有关此 npm 设计的一些相关阅读:Why no Directories.lib in Node。
有趣的是,jspm 确实尊重 package.json
中的 directories.lib
选项,并在解析 npm 包时重新排列文件。这一切对我来说都是因为我想构建一个可以被 jspm 或 npm/webpack 使用的通用库。
我与原始海报(@robsonrosa)有类似的问题。在我的情况下,我使用编译到 dist
目录的打字稿。虽然我可以将 typescript 编译到根目录,但我认为最好的解决方案是在 dist 目录中生成一个单独的 package.json
文件。
这类似于复制 package.json
的@scvnc 建议,但有一点不同:
作为打包过程的一部分,您应该为包生成一个 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
目录,该目录应该是包中的根目录。
我的 src
目录中的文件 SetupPackage.ts
将通过 typescript 编译为 dist
目录中的 SetupPackage.js
:
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
用作 shell)。
"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。
执行为打包准备 dist 的 SetupPackage.js 文件。
cds 到 dist 目录并在那里构建包。
我使用 version.txt
文件作为获取 package.json 中的版本并标记我的存储库的简单方法。有无数其他方法可以做到这一点,或者您可能希望自动增加版本。如果对您没有用,请将其从 SetupPackage.ts
和 .npmignore
中删除。
SetupPackage.ts
文件将文件复制到 src
目录而不是 dist
。谢谢👍
如果你的项目有 git,你可以使用 small hack。将下一个脚本添加到 package.json
"prepublishOnly": "npm run build && cp -r ./lib/* . && rm -rf ./lib",
"postpublish": "git clean -fd",
现在,当您运行 publish
命令时,npm 涉及 prepublishOnly
。它构建文件并将它们保存到 lib
文件夹(构建脚本取决于您的项目)。下一个命令将文件复制到根文件夹并删除 lib
。发布后 postpublish
脚本将项目返回到以前的状态。
git clean -fd
。
如果您(并且我建议)使用 semantic-release,请在 .releaserc.json
文件中添加 pkgRoot
选项。 (您还应该安装 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"
],
}
那会解决问题的。只需确保您的 dist
文件夹包含一个 package.json
文件。您可以通过将 cp
添加到 postbuild
脚本来轻松做到这一点:
{
"scripts": {
"postbuild": "cp package.json dist"
}
}
npm --no-git-tag-version version <%= nextRelease.version %>
。这将更改 package.json 和 package-lock.json 中的版本。通过添加 --no-git-tag-version
标签,它不会创建 git 标签,也不会提交文件。
我强烈建议您使用 .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
更新:
如果您想使用相同的 repo 将代码拆分为不同的 npm 包,我最近遇到了这个项目:Lerna,看起来非常好。
也许你应该看看
require('mypackage/foo')
而不是 require('mypackage/dist/foo')
cd TMPDIR
npm pack /path/to/package.json
tarball 将在 TMPDIR 目录中创建。
npm pack
加上 package.json files
字段(或 .npmignore
)非常有效。
您需要发布 dist 文件夹
根据 npm 方法,实现这一目标的自然方法是发布作为根的文件夹。有几种方法可以做到这一点,具体取决于您要使用的最终环境:
npm publish
先决条件:在上述任何情况下,在发布/安装/链接之前,您必须在您的 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 和 build
脚本自动执行发布过程。此外,您可以使用 package.json 中的 "private": true
字段来保护您的包免受意外发布包根文件夹的影响,该字段位于包存储库的根目录中。这是一个例子:
"private": true,
"scripts": {
"build": "rm -rf dist && gulp build && cat ./package.json | grep -v '\"private\":' > dist/package.json",
"prepare": "npm run build"
},
这样,您将不会在发布过程中发布根文件夹并自动将构建的包和 package.json 复制到 dist
文件夹。
npm publish dist
时,它会尝试推送名称为 dist
的包,而不是使用 dist
文件夹。
package.json
复制到您的 diist
文件夹中?
我有一个 Typescript 项目,它编译到一个名为 dist
的文件夹中,并且我找到了适用于 Windows 的解决方案。
在我的项目根目录的 package.json
中:
"scripts": {
"prepub": "copy package.json dist",
"pub": "cd dist & npm publish",
"postpub": "cd dist & del package.json"
}
这些脚本允许我通过运行 npm run pub
将我的 dist
文件夹发布为我的包的根目录。
prepub 将我的 package.json 复制到 dist 文件夹中。
pub 将工作目录更改为 dist/ 然后运行 npm publish
postpub 从我的 dist 文件夹中删除 package.json 以确保每次都进行干净的发布。
这样,我仍然可以在我的项目根目录中拥有所有相关的配置文件,但我可以在发布之前将它们复制到 dist
。
同样的方法可能适用于 Mac 或 Linux。
这是简单的 package.json
解决方案:
{
"scripts": {
"pack": "mkdir -p dist && cp package.json dist/package.json && npm pack ./dist",
"pub": "npm publish $(node -p \"p=require('./package.json');p.name+'-'+p.version+'.tgz'\")"
}
}
这对我有用
npm run build
cp package.json dist
cp .npmrc dist
cd dist
npm publish
我正在使用 Jenkins 的这些命令来发布包。
我通过执行以下操作来实现这一点:
我将 package.json 设置为私有。所以我不能用 npm publish 发布我的包我用以下步骤创建了一个 gulpfile:
从'gulp'导入gulp;从“gulp-shell”导入外壳;从“gulp-replace”导入替换; const compile = () => gulp.src('package.json').pipe(shell('npm run compile')); const copy = () => gulp.src(['readme.md']).pipe(gulp.dest('dist')); const update = () => gulp.src('package.json').pipe(replace('"private": true,', '"private": false,')).pipe(gulp.dest('dist ')); const publish = () => gulp.src('package.json').pipe(shell('cd dist && npm publish'));导出默认 gulp.series(编译、复制、更新、发布);
我的情况类似,但同时也更麻烦,因为它涉及通过 CI 管道进行发布,这几乎不受我的控制,并且只有它通过它在执行期间下载的 .npmrc
文件具有发布权限。而且由于它必须与无数其他团队和存储库共享,它必须与每个存储库的细节无关。
在浪费了大量时间试图将 .npmrc
文件复制到 npm 的全局根目录后,通常以权限警告结束,然后尝试在 package.json
中使用不同的脚本来调用全局 npm 并获得 403 HTTP错误,解决方案终于让我明白了,如果我尝试过,它再简单不过了。
它所要做的只是在应用程序中包含一个 shell 脚本(如果容器运行 Windows,也可以是一个批处理文件),检查它在管道中的存在并运行它而不是 npm publish
。
由于现在存在 npm publish [folder]
语法,因此我的脚本非常简单,但我可以看到它在不同时期可能看起来像 @Eli Algranti's 脚本。
所以这就是它最终的样子:
发布.sh
# DO NOT EDIT THIS FILE
# THIS OVERRIDES THE DEFAULT PIPELINE PUBLISH SCRIPT TO BE RUN
# IT EXISTS SO ONLY THE BUILD OUTPUT FOLDER GETS PUBLISHED
npm publish ./dist
npm-build.yml
npm run build --if-present
if [ -f "./publish.sh" ]; then
echo "'publish.sh' script has been found. Overriding the publishing with it"
sh publish.sh
else
npm publish
fi
这在本地运行,使用当前用户和已复制的 .npmrc
文件,并且可以在必要时封装许多其他逻辑
这是我认为最干净的另一种方法。它全部基于配置,无需在构建和打包脚本中移动文件或指定路径:
package.json
指定主文件。
{
"main": "lib/index.js",
}
一些额外的打字稿选项:
指定根目录。该目录将包含所有源代码,并且其中应该有一个索引文件(或您可以在 package.json 中用作 main 的其他文件)。
指定 outDir。这是您的 tsc 命令将构建到的位置
tsconfig.json
{
"compilerOptions": {
"rootDir": "src",
"outDir": "lib",
},
...
}
选项 1:导航到文件夹并执行“npm publish”。命令
选项 2:运行 npm publish /path/directory
您可以指定要发布的目录。这就是我在 Linux 上为 Typescript 提出的。
"scripts": {
"prepub": "rm -rf dist && tsc && cp package*.json dist",
"pub": "npm publish ./dist"
}
感谢@EnderShadow8 的启发。
只需创建一个 .npmignore
文件并将以下内容添加到其中:
*.*
!dist/*
npm pack
、package.jsonfiles
和main
字段以及.npmignore
为开发人员提供了从特定的可安装目录创建包所需的一切。