简短的回答。
“这有可能在发布包之前删除脚本吗?”
npm 不包含用于从package.json
.
解决方案的长答案。
“这可行吗?还是我该想别的办法?”
有几个称为Pre 和 Post 挂钩的内置功能可用于满足您的要求,尽管是以一种相当自定义的方式。相关的钩子在文档prepublish
中描述如下:postpublish
prepublish:在打包和发布包之前运行,以及在本地运行,npm install
不带任何参数...
postpublish:在包发布后运行。
解决方案的概要是:
prepublish
在您的项目中使用脚本package.json
来调用自定义nodejs脚本。此nodejs脚本执行以下操作:
- 读取原始
package.json
数据并将其缓存。
- 从.
scripts
_package.json
- 将修改后的数据写回原来的
package.json
.
postpublish
在您的项目中使用脚本package.json
来调用另一个自定义nodejs脚本。此辅助nodejs脚本执行以下操作:
代码示例/要点。
以下nodejs脚本将执行上述第一点中提到的任务。让我们命名它cleanse-pkg.js
。
清理-pkg.js
const fs = require('fs');
const path = require('path');
// Define absolute paths for original pkg and temporary pkg.
const ORIG_PKG_PATH = path.resolve(__dirname, '../package.json');
const CACHED_PKG_PATH = path.resolve(__dirname, '../../cached-package.json');
// Obtain original `package.json` contents.
const pkgData = require(ORIG_PKG_PATH);
if (process.argv.length <= 2) {
throw new Error('Missing npm scripts key/name argument(s)');
}
// Get list of arguments passed to script.
const scriptsToRemove = process.argv[2].split(',');
const devDepsToRemove = process.argv[3] ? process.argv[3].split(',') : [];
// Write/cache the original `package.json` data to `cached-package.json` file.
fs.writeFile(CACHED_PKG_PATH, JSON.stringify(pkgData), function (err) {
if (err) throw err;
});
// Remove the specified named scripts from the scripts section.
scriptsToRemove.forEach(function (scriptName) {
delete pkgData.scripts[scriptName];
});
// Remove the specified named pkgs from the devDependencies section.
devDepsToRemove.forEach(function (pkgName) {
delete pkgData.devDependencies[pkgName];
});
// Overwrite original `package.json` with new data (i.e. minus the specific data).
fs.writeFile(ORIG_PKG_PATH, JSON.stringify(pkgData, null, 2), function (err) {
if (err) throw err;
});
以下辅助nodejs脚本将执行上述第二点中提到的任务。让我们命名这个restore-pkg.js
。
恢复-pkg.js
const fs = require('fs');
const path = require('path');
// Define absolute paths for original pkg and temporary pkg.
const ORIG_PKG_PATH = path.resolve(__dirname, '../package.json');
const CACHED_PKG_PATH = path.resolve(__dirname, '../../cached-package.json');
// Obtain original/cached contents from `cached-package.json`.
const pkgData = JSON.stringify(require(CACHED_PKG_PATH), null, 2) + '\n';
// Write data from `cached-package.json` back to original `package.json`.
fs.writeFile(ORIG_PKG_PATH, pkgData, function (err) {
if (err) throw err;
});
// Delete the temporary `cached-package.json` file.
fs.unlink(CACHED_PKG_PATH, function (err) {
if (err) throw err;
});
实施和使用。
和脚本在项目中定义prepublish
如下:postpublish
package.json
人为的原始 package.json
{
...
"scripts": {
"keep": ... ,
"a": ... ,
"b": ... ,
"prepublish": "node .scripts/cleanse-pkg \"a,b,prepublish,postpublish\"",
"postpublish": "node .scripts/restore-pkg"
},
...
}
注意脚本\"a,b,prepublish,postpublish\"
中的部分。prepublish
这定义了要传递给的参数cleanse-pkg.js
(即它列出了在发布之前要删除的每个脚本的名称)。每个要删除的命名脚本必须是;作为单个字符串提供,用逗号分隔,并且不得包含空格。
两者cleanse-pkg.js
和restore-pkg.js
都位于一个名为 的隐藏文件夹中.scripts
,该文件夹本身位于项目目录的顶层(即与项目处于同一级别package.json
)。两个nodejs脚本都可以根据需要重新定位,并在各自的npm-script中根据需要重新定义它们的路径。
鉴于上述人为设计,最终发布的 tarball 中package.json
的实际package.json
内容如下:
结果/发布的 package.json
{
...
"scripts": {
"keep": ...
},
...
}
devDependencies 部分中的包。
devDependencies
也许您的项目部分中列出了package.json
您还希望在已发布的package.json
.
(注意:当用户通过 npm-registry 安装时,不会下载devDependencies部分中列出的任何包) 。
但是,也许您还是想删除它们。如果这是一个要求,那么cleanse-pkg.js
也接受可选的第二个参数。这个参数类似于第一个参数,其中每个要从该devDependencies
部分中删除的命名包必须是;作为单个字符串提供,用逗号分隔,并且不得包含空格。
我们假设这次的原文package.json
如下:
人为的原始 package.json
{
...
"scripts": {
"keep": ... ,
"a": ... ,
"b": ... ,
"prepublish": "node .scripts/cleanse-pkg \"a,b,prepublish,postpublish\" \"x,z\"",
"postpublish": "node .scripts/restore-pkg"
},
"devDependencies": {
"x": "^1.0.2",
"y": "^0.8.1",
"z": "^0.8.1"
},
...
}
\"x,z\"
请注意添加到脚本中的附加第二个参数,prepublish
以指定要从该devDependecies
部分中省略哪些包。
这一次,考虑到上面的人为,最终发布的 tarball 中package.json
的实际package.json
内容如下:
结果/发布的 package.json
{
...
"scripts": {
"keep": ...
},
"devDependencies": {
"y": "^0.8.1"
},
...
}
跑步
此解决方案假定npm publish将使用以下方法之一运行:
- 从项目目录中不带任何参数。例如
npm publish
。
- 指定项目的路径
package.json
。例如npm publish path/to/package.json
。
这将无法通过为包含单个文件夹的 gzip 压缩 tar 存档提供 url 或文件路径来工作,其中包含一个package.json
文件。
补充说明
为了防止两个实用程序nodejs脚本 (cleanse-pkg.js
和restore-pkg.js
) 被发布,它们应该被添加到您的项目.npmignore文件中。鉴于上面解释的这两个文件的位置,您可以.scripts
在.npmignore
.
实用程序nodejs脚本cleanse-pkg.js
和restore-pkg.js
定义:
- 原始
package.json
文件的绝对路径。
cached-package.json
应写入临时文件的绝对路径。目前,这是从项目目录中向上/外部保存的,以避免它被发布)。
如果您选择存储cleanse-pkg.js
和存储restore-pkg.js
到与上述位置不同的位置,则需要在两个文件中根据需要重新定义以下代码片段中的路径。
const ORIG_PKG_PATH = path.resolve(__dirname, '../package.json');
const CACHED_PKG_PATH = path.resolve(__dirname, '../../cached-package.json');