6

在发布我的脚本之前,我在 package.json 下有许多脚本来编译 coffeescript、typescript 和仅限开发人员的命令——一旦发布就毫无意义。

我想知道是否有删除 package.json 下某些脚本的程序?考虑到在发布你的包时,它也会发布 package.json。

这可以在发布包之前删除脚本吗?

一旦我发布了我的脚本,我就会删除很多 typescript 和 coffeescript 源文件(因为它们已经被编译),所以我用来构建的脚本对于发布的包没有意义。

这可行吗?还是我应该考虑另一种方式?

4

3 回答 3

11

简短的回答。

“这有可能在发布包之前删除脚本吗?”

npm 不包含用于从package.json.


解决方案的长答案。

“这可行吗?还是我该想别的办法?”

有几个称为Pre 和 Post 挂钩的内置功能可用于满足您的要求,尽管是以一种相当自定义的方式。相关的钩子在文档prepublish中描述如下:postpublish

prepublish:在打包和发布包之前运行,以及在本地运行,npm install不带任何参数...

postpublish:在包发布后运行。

解决方案的概要是:

  1. prepublish在您的项目中使用脚本package.json来调用自定义nodejs脚本。此nodejs脚本执行以下操作:

    • 读取原始package.json数据并将其缓存。
    • 从. scripts_package.json
    • 将修改后的数据写回原来的package.json.
  2. postpublish在您的项目中使用脚本package.json来调用另一个自定义nodejs脚本。此辅助nodejs脚本执行以下操作:

    • 将内容package.json恢复到其原始状态。

代码示例/要点。

  1. 以下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;
    });
    
  2. 以下辅助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;
    });
    

实施和使用。

  1. 和脚本在项目中定义prepublish如下:postpublishpackage.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.jsrestore-pkg.js都位于一个名为 的隐藏文件夹中.scripts,该文件夹本身位于项目目录的顶层(即与项目处于同一级别package.json)。两个nodejs脚本都可以根据需要重新定位,并在各自的npm-script中根据需要重新定义它们的路径。

  2. 鉴于上述人为设计,最终发布的 tarball 中package.json的实际package.json内容如下:

    结果/发布的 package.json

    {
      ...
      "scripts": {
        "keep": ...
      },
      ...
    }
    

devDependencies 部分中的包。

devDependencies也许您的项目部分中列出了package.json您还希望在已发布的package.json.

(注意:当用户通过 npm-registry 安装时,不会下载devDependencies部分中列出的任何包) 。

但是,也许您还是想删除它们。如果这是一个要求,那么cleanse-pkg.js也接受可选的第二个参数。这个参数类似于第一个参数,其中每个要从该devDependencies部分中删除的命名包必须是;作为单个字符串提供,用逗号分隔,并且不得包含空格。

  1. 我们假设这次的原文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部分中省略哪些包。
  2. 这一次,考虑到上面的人为,最终发布的 tarball 中package.json的实际package.json内容如下:

    结果/发布的 package.json

    {
      ...
      "scripts": {
        "keep": ...
      },
      "devDependencies": {
        "y": "^0.8.1"
      },
      ...
    }
    

跑步

此解决方案假定npm publish将使用以下方法之一运行:

  1. 从项目目录中不带任何参数。例如npm publish
  2. 指定项目的路径package.json。例如npm publish path/to/package.json

这将无法通过为包含单个文件夹的 gzip 压缩 tar 存档提供 url 或文件路径来工作,其中包含一个package.json文件。


补充说明

  1. 为了防止两个实用程序nodejs脚本 (cleanse-pkg.jsrestore-pkg.js) 被发布,它们应该被添加到您的项目.npmignore文件中。鉴于上面解释的这两个文件的位置,您可以.scripts.npmignore.

  2. 实用程序nodejs脚本cleanse-pkg.jsrestore-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');
    
于 2018-02-16T08:54:56.037 回答
2

你也可以考虑这个包。https://www.npmjs.com/package/clean-publish

具体来说,它们提供了一个仅用于处理packakge.json.

$ npm run clear-package-json package.json -o package/package.json --fields scripts name
# or
$ npm run clear-package-json package.json > package/package.json
# or
$ cat package.json | npm run clear-package-json
# `fields` also will be getted from config file

它似乎完全符合您的要求,但也做得更多。它看起来确实是高度可配置的。


更新

这是我创建的一个包,它可以满足您的要求,但方式截然不同。

https://www.npmjs.com/package/clean-package

$ clean-package --remove scripts
于 2020-08-07T14:59:37.270 回答
0

从 开始npm@7,命令 npm-pkg 可以执行删除密钥,package.json并且不需要任何外部包来下载或执行。

# entire scripts dictionary
$ npm pkg delete scripts

# delete specific script using the subkey syntax
$ npm pkg delete scripts.build

该命令的文档是: https ://docs.npmjs.com/cli/v8/commands/npm-pkg

如果您想要备份,则clean-package可以提供此自动备份,或者只需手动执行:

$ cp package.json package.json.bkup
于 2022-01-17T00:18:01.197 回答