475

我有一个简单的 package.json 文件,我想添加评论。有没有办法做到这一点,或者有任何黑客可以做到这一点?

{
  "name": "My Project",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "express": "3.x",
    "mongoose": "3.x"
  },
  "devDependencies" :  {
    "should": "*"
    /* "mocha": "*" not needed as should be globally installed */
  }
}

上面的示例注释在 npm 中断时不起作用。我也尝试过 // 样式注释。

4

20 回答 20

523

这最近在Node.js 邮件列表中进行了讨论。

根据创建 npm 的 Isaac Schlueter 的说法:

...“//”键永远不会被 npm 用于任何目的,并保留用于注释 ...如果要使用多行注释,可以使用数组或多个“//”键。

使用常用工具(npm、yarn 等)时,将删除多个“//”键。这幸存下来:

{ "//": [
  "first line",
  "second line" ] }

这将无法生存:

{ "//": "this is the first line of a comment",
  "//": "this is the second line of the comment" }
于 2013-01-08T18:36:43.673 回答
188

在复杂和 hacky 解决方案上浪费了一个小时后,我找到了简单而有效的解决方案来评论我在package.json. 像这样:

{
  "name": "package name",
  "version": "1.0",
  "description": "package description",
  "scripts": {
    "start": "npm install && node server.js"
  },
  "scriptsComments": {
    "start": "Runs development build on a local server configured by server.js"
  },
  "dependencies": {
    "ajv": "^5.2.2"
  },
  "dependenciesComments": {
    "ajv": "JSON-Schema Validator for validation of API data"
  }
}

当以相同的方式排序时,我现在可以很容易地在 Git 提交差异或编辑器中跟踪这些依赖项/注释对,同时使用 file package.json

并且不涉及额外的工具,只是简单有效的 JSON。

于 2017-08-22T10:38:46.707 回答
125

免责声明:你可能不应该使用这个黑客。请参阅下面的评论。


这是在 JSON 中添加评论的另一个技巧。自从:

{"a": 1, "a": 2}

相当于

{"a": 2}

您可以执行以下操作:

{
  "devDependencies": "'mocha' not needed as should be globally installed",
  "devDependencies" :  {
    "should": "*"
  }
}
于 2013-08-04T22:18:33.233 回答
46

我一直在这样做:

{
  ...
  "scripts": {
    "about": "echo 'Say something about this project'",
    "about:clean": "echo 'Say something about the clean script'",
    "clean": "do something",
    "about:build": "echo 'Say something about building it'",
    "build": "do something",
    "about:watch": "echo 'Say something about how watch works'",
    "watch": "do something",
  }
  ...
}

这样,我既可以阅读脚本本身中的“伪注释”,可以运行以下内容,以在终端中查看某种帮助:

npm run about
npm run about:watch

如果您使用yarn.

yarn about:clean

此外,正如@Dakota Jang 在评论中指出的那样,您可以使用 like 键//something来更清楚地表明这是一条评论。
像这样:

{
  ...
  "scripts": {
    "//clean": "echo 'Say something about the clean script'",
    "clean": "do something",
    "//build": "echo 'Say something about building it'",
    "build": "do something",
    "//watch": "echo 'Say something about how watch works'",
    "watch": "do something",
  }
  ...
}

然后运行:

npm run //build
# or
yarn //build

您的终端中将有一个辅助输出,并且您的 package.json 中也会有一个“注释”。

于 2018-06-15T14:55:51.233 回答
22

NPS(节点包脚本)为我解决了这个问题。它允许您将 NPM 脚本放入单独的 JavaScript 文件中,您可以在其中添加大量注释和任何其他所需的 JavaScript 逻辑。 https://www.npmjs.com/package/nps

package-scripts.js我的一个项目的样本

module.exports = {
  scripts: {
    // makes sure e2e webdrivers are up to date
    postinstall: 'nps webdriver-update',

    // run the webpack dev server and open it in browser on port 7000
    server: 'webpack-dev-server --inline --progress --port 7000 --open',

    // start webpack dev server with full reload on each change
    default: 'nps server',

    // start webpack dev server with hot module replacement
    hmr: 'nps server -- --hot',

    // generates icon font via a gulp task
    iconFont: 'gulp default --gulpfile src/deps/build-scripts/gulp-icon-font.js',

    // No longer used
    // copyFonts: 'copyfiles -f src/app/glb/font/webfonts/**/* dist/1-0-0/font'
  }
}

我刚刚进行了本地安装npm install nps -save-dev并将其放入我的package.json脚本中。

"scripts": {
    "start": "nps",
    "test": "nps test"
}
于 2017-07-14T12:24:32.430 回答
22

受此线程的启发,这是我们正在使用的内容:

{
  "//dependencies": {
    "crypto-exchange": "Unified exchange API"
  },
  "dependencies": {
    "crypto-exchange": "^2.3.3"
  },
  "//devDependencies": {
    "chai": "Assertions",
    "mocha": "Unit testing framwork",
    "sinon": "Spies, Stubs, Mocks",
    "supertest": "Test requests"
  },
  "devDependencies": {
    "chai": "^4.1.2",
    "mocha": "^4.0.1",
    "sinon": "^4.1.3",
    "supertest": "^3.0.0"
  }
}
于 2019-05-12T10:42:42.443 回答
14

您总是可以滥用重复键被覆盖的事实。这是我刚刚写的:

"dependencies": {
  "grunt": "...",
  "grunt-cli": "...",

  "api-easy": "# Here is the pull request: https://github.com/...",
  "api-easy": "git://..."

  "grunt-vows": "...",
  "vows": "..."
}

但是,尚不清楚 JSON 是否允许重复键(请参阅 JSON 语法是否允许在对象中重复键?。它似乎与 npm 一起工作,所以我冒险。

推荐的 hack 是使用"//"密钥(来自nodejs 邮件列表)。但是,当我对其进行测试时,它不适用于“依赖项”部分。此外,帖子中的示例使用了多个"//"键,这意味着 npm 不会拒绝具有重复键的 JSON 文件。换句话说,上面的 hack 应该总是没问题的。

更新:重复密钥破解的一个恼人的缺点是它会npm install --save默默地消除所有重复项。不幸的是,它很容易被忽视,你善意的评论也不见了。

"//"看起来,黑客仍然是最安全的。但是,多行注释也将被删除npm install --save

于 2014-05-21T18:32:57.743 回答
11

由于大多数开发人员都熟悉基于标签/注释的文档,因此我开始使用的约定是相似的。这是一个味道:

{
  "@comment dependencies": [
    "These are the comments for the `dependencies` section.",
    "The name of the section being commented is included in the key after the `@comment` 'annotation'/'tag' to ensure the keys are unique.",
    "That is, using just \"@comment\" would not be sufficient to keep keys unique if you need to add another comment at the same level.",
    "Because JSON doesn't allow a multi-line string or understand a line continuation operator/character, just use an array for each line of the comment.",
    "Since this is embedded in JSON, the keys should be unique.",
    "Otherwise JSON validators, such as ones built into IDEs, will complain.",
    "Or some tools, such as running `npm install something --save`, will rewrite the `package.json` file but with duplicate keys removed.",
    "",
    "@package react - Using an `@package` 'annotation` could be how you add comments specific to particular packages."
  ],
  "dependencies": {
    ...
  },
  "@comment scripts": {
    "build": "This comment is about the build script.",
    "start": [
      "This comment is about the `start` script.",
      "It is wrapped in an array to allow line formatting.",
      "When using npm, as opposed to yarn, to run the script, be sure to add ` -- ` before adding the options.",
      "",
      "@option {number} --port - The port the server should listen on."
    ],
    "test": "This comment is about the test script.",
  },
  "scripts": {
    "build": "...",
    "start": "...",
    "test": "..."
  }
}

注意:对于dependencies,devDependencies等部分,注释注释不能直接添加到配置对象内的单个包依赖项之上,因为npm期望键是 npm 包的名称。因此@comment dependencies.

我喜欢向 JSON 添加注释的注释/标签样式方式,因为该@符号从普通声明中脱颖而出。

较早的建议

以下是我之前的推荐。它内嵌了脚本的注释,但我开始意识到这些注释在某些工具中显示为“命令”(在 VS Code > Explorer > NPM 脚本部分)。最新的建议不受此问题的影响,但脚本注释不再位于同一位置。

{
  "@comment dependencies": [
    ...
  ],
  "dependencies": {
    ...
  },
  "scripts": {
    "@comment build": "This comment is about the build script.",
    "build": "...",

    "@comment start": [
      "This comment is about the `start` script.",
      "It is wrapped in an array to allow line formatting.",
      "When using npm, as opposed to yarn, to run the script, be sure to add ` -- ` before adding the options.",
      "",
      "@option {number} --port - The port the server should listen on."
    ],
    "start": "...",

    "@comment test": "This comment is about the test script.",
    "test": "..."
  }
}

注意:在某些上下文中,例如在"scripts"对象中,一些编辑器/IDE 可能会抱怨数组。在脚本上下文中,VS Code 需要一个字符串作为值,而不是数组。

于 2019-10-15T00:00:24.373 回答
10

我有一个有趣的黑客想法。

例如,在文件package.json中适当地创建一个 npm 包名称作为注释分隔符dependencies和块devDependenciesx----x----x

{
    "name": "app-name",
    "dependencies": {
        "x----x----x": "this is the first line of a comment",
        "babel-cli": "6.x.x",
        "babel-core": "6.x.x",
        "x----x----x": "this is the second line of a comment",
        "knex": "^0.11.1",
        "mocha": "1.20.1",
        "x----x----x": "*"
    }
}

注意:您必须添加具有有效版本的最后一个注释分隔线,就像*在块中一样。

于 2016-05-13T10:07:55.240 回答
10

到目前为止,这里的大多数“黑客”都建议滥用 JSON。但是,为什么不滥用底层脚本语言呢?

编辑最初的反应是把描述放在右边# add comments here用来包装它;但是,这在 Windows 上不起作用,因为标志(例如npm run myframework -- --myframework-flags)将被忽略。我更改了我的回复以使其适用于所有平台,并添加了一些缩进以提高可读性。

{
 "scripts": {
    "help": "       echo 'Display help information (this screen)';          npm run",
    "myframework": "echo 'Run myframework binary';                          myframework",
    "develop": "    echo 'Run in development mode (with terminal output)';  npm run myframework"
    "start": "      echo 'Start myFramework as a daemon';                   myframework start",
    "stop":  "      echo 'Stop the myFramework daemon';                     myframework stop"
    "test": "echo \"Error: no test specified\" && exit 1"
  }
}

这会:

  1. 不破坏 JSON 合规性(或者至少它不是一个 hack,你的 IDE 不会因为你做了奇怪、危险的事情而给你警告)
  2. 跨平台工作(在 macOS 和 Windows 上测试,假设它可以在 Linux 上正常工作)
  3. 不妨碍跑步npm run myframework -- --help
  4. 运行时将输出有意义的信息npm run(这是运行以获取有关可用脚本信息的实际命令)
  5. 提供更明确的帮助命令(以防某些开发人员不知道 npm run 提供此类输出)
  6. 运行命令本身时将显示命令及其描述
  7. 刚打开时有点可读性package.json(使用less或您最喜欢的 IDE)
于 2017-04-04T05:03:19.700 回答
7

这是我对package.json/中的评论的看法bower.json

我有package.json.js一个文件,其中包含一个导出实际package.json. 运行脚本会覆盖旧的package.json并告诉我它做了哪些更改,非常适合帮助您跟踪所做的自动更改npm。这样我什至可以以编程方式定义我想要使用的包。

最新的 Grunt 任务在这里: https ://gist.github.com/MarZab/72fa6b85bc9e71de5991

于 2015-02-07T09:27:23.150 回答
6

总结所有这些答案:

  1. 添加一个名为的顶级字段//,其中包含注释字符串。这行得通,但它很糟糕,因为你不能把评论放在他们评论的东西附近。

  2. 添加多个以 开头的顶级字段,例如包含注释字符串。这更好,但它仍然只允许您进行顶级评论。您不能评论单个依赖项。 ////dependencies

  3. echo命令添加到您的scripts. 这行得通,但很糟糕,因为你只能在scripts.

这些解决方案也都不是很可读。它们添加了大量的视觉噪音,并且 IDE 不会在语法上将它们突出显示为注释。

我认为唯一合理的解决方案是package.json从另一个文件生成。最简单的方法是将 JSON 编写为 JavaScript 并使用 Node.js 将其写入package.json. 将此文件另存为package.json.mjs,chmod +x它,然后您可以运行它来生成您的package.json.

#!/usr/bin/env node

import { writeFileSync } from "fs";

const config = {
  // TODO: Think of better name.
  name: "foo",
  dependencies: {
    // Bar 2.0 does not work due to bug 12345.
    bar: "^1.2.0",
  },
  // Look at these beautify comments. Perfectly syntax highlighted, you
  // can put them anywhere and there no risk of some tool removing them.
};

writeFileSync("package.json", JSON.stringify({
    "//": "This file is \x40generated from package.json.mjs; do not edit.",
    ...config
  }, null, 2));

它使用//密钥警告人们不要对其进行编辑。\x40generated是故意的。它变成@generatedpackage.json意味着一些代码审查系统默认情况下会折叠该文件。

这是构建系统中的一个额外步骤,但它击败了这里的所有其他黑客。

于 2020-05-20T16:48:39.567 回答
3

我最终得到了scripts这样的结果:

  "scripts": {
    "//-1a": "---------------------------------------------------------------",
    "//-1b": "---------------------- from node_modules ----------------------",
    "//-1c": "---------------------------------------------------------------",
    "ng": "ng",
    "prettier": "prettier",
    "tslint": "tslint",
    "//-2a": "---------------------------------------------------------------",
    "//-2b": "--------------------------- backend ---------------------------",
    "//-2c": "---------------------------------------------------------------",
    "back:start": "node backend/index.js",
    "back:start:watch": "nodemon",
    "back:build:prod": "tsc -p backend/tsconfig.json",
    "back:serve:prod": "NODE_ENV=production node backend/dist/main.js",
    "back:lint:check": "tslint -c ./backend/tslint.json './backend/src/**/*.ts'",
    "back:lint:fix": "yarn run back:lint:check --fix",
    "back:check": "yarn run back:lint:check && yarn run back:prettier:check",
    "back:check:fix": "yarn run back:lint:fix; yarn run back:prettier:fix",
    "back:prettier:base-files": "yarn run prettier './backend/**/*.ts'",
    "back:prettier:fix": "yarn run back:prettier:base-files --write",
    "back:prettier:check": "yarn run back:prettier:base-files -l",
    "back:test": "ts-node --project backend/tsconfig.json node_modules/jasmine/bin/jasmine ./backend/**/*spec.ts",
    "back:test:watch": "watch 'yarn run back:test' backend",
    "back:test:coverage": "echo TODO",
    "//-3a": "---------------------------------------------------------------",
    "//-3b": "-------------------------- frontend ---------------------------",
    "//-3c": "---------------------------------------------------------------",
    "front:start": "yarn run ng serve",
    "front:test": "yarn run ng test",
    "front:test:ci": "yarn run front:test --single-run --progress=false",
    "front:e2e": "yarn run ng e2e",
    "front:e2e:ci": "yarn run ng e2e --prod --progress=false",
    "front:build:prod": "yarn run ng build --prod --e=prod --no-sourcemap --build-optimizer",
    "front:lint:check": "yarn run ng lint --type-check",
    "front:lint:fix": "yarn run front:lint:check --fix",
    "front:check": "yarn run front:lint:check && yarn run front:prettier:check",
    "front:check:fix": "yarn run front:lint:fix; yarn run front:prettier:fix",
    "front:prettier:base-files": "yarn run prettier \"./frontend/{e2e,src}/**/*.{scss,ts}\"",
    "front:prettier:fix": "yarn run front:prettier:base-files --write",
    "front:prettier:check": "yarn run front:prettier:base-files -l",
    "front:postbuild": "gulp compress",
    "//-4a": "---------------------------------------------------------------",
    "//-4b": "--------------------------- cypress ---------------------------",
    "//-4c": "---------------------------------------------------------------",
    "cy:open": "cypress open",
    "cy:headless": "cypress run",
    "cy:prettier:base-files": "yarn run prettier \"./cypress/**/*.{js,ts}\"",
    "cy:prettier:fix": "yarn run front:prettier:base-files --write",
    "cy:prettier:check": "yarn run front:prettier:base-files -l",
    "//-5a": "---------------------------------------------------------------",
    "//-5b": "--------------------------- common ----------------------------",
    "//-5c": "---------------------------------------------------------------",
    "all:check": "yarn run back:check && yarn run front:check && yarn run cy:prettier:check",
    "all:check:fix": "yarn run back:check:fix && yarn run front:check:fix && yarn run cy:prettier:fix",
    "//-6a": "---------------------------------------------------------------",
    "//-6b": "--------------------------- hooks -----------------------------",
    "//-6c": "---------------------------------------------------------------",
    "precommit": "lint-staged",
    "prepush": "yarn run back:lint:check && yarn run front:lint:check"
  },

我在这里的目的不是澄清一行,只是为了在我的后端、前端、所有等脚本之间有某种分隔符。

我不是 1a, 1b, 1c, 2a 的忠实拥护者……但是按键不同,我完全没有这样的问题。

于 2018-03-04T14:43:43.327 回答
3

正如这个答案所解释的,//密钥是保留的,因此它可以按惯例用于评论。注释的问题//在于它不实用,因为它不能多次使用。package.json自动更新时会删除重复的键:

"//": "this comment about dependencies stays",
"dependencies": {}
"//": "this comment disappears",
"devDependencies": {}

另一个问题是//不能在内部使用注释dependenciesdevDependencies因为它被视为常规依赖项:

"dependencies": {
  "//": "comment"
}

npm 错误!代码 EINVALIDPACKAGENAME

npm 错误!无效的包名“//”:名称只能包含 URL 友好字符

一种适用于 NPM 但不适用于 Yarn 的解决方法是使用非字符串值:

"dependencies": {
  "foo": ["unused package"],
}

在 NPM 和 Yarn 中有效的解决方法是作为语义版本控制的一部分添加的注释:

"dependencies": {
  "bar": "^2",
  "foo": "^2 || should be removed in 1.x release"
}

请注意,如果之前的第一部分OR不匹配,则可以解析来自评论的版本,例如1.x.

需要注释但未安装的软件包应移至另一个键,例如dependencies //

"dependencies //": {
  "baz": "unused package",
}
于 2019-02-18T10:47:57.570 回答
1

由于运行 package.json 工具(npm、yarn 等)删除了重复的注释键,我开始使用散列版本,它允许更好地读取多行和键,例如:

"//": {
  "alpaca": "we use the bootstrap version",
  "eonasdan-bootstrap-datetimepicker": "instead of bootstrap-datetimepicker",
  "moment-with-locales": "is part of moment"
},

根据我的 IDE 作为根键,这是“有效的”,但在dependencies其中抱怨期望字符串值。

于 2018-06-06T07:36:12.230 回答
1

对于 npm 的 package.json,我找到了两种方法(阅读此对话后):

  "devDependencies": {
    "del-comment": [
      "some-text"
    ],
    "del": "^5.1.0 ! inner comment",
    "envify-comment": [
      "some-text"
    ],
    "envify": "4.1.0 ! inner comment"
  }

但是使用“--save”或“--save-dev”更新或重新安装软件包时,会出现“^4.1.0 之类的评论!相应位置的“评论”将被删除。这一切都会破坏 npm 审计。

于 2020-01-30T11:02:58.083 回答
1

我做了一些你们可能喜欢的事情:

名称中的 // 这个 // 意味着它是对我的评论:

  "//":"Main and typings are used till ES5",
  "//main": "build/index",
  "//typings": "build/index",
于 2020-07-03T18:43:46.433 回答
0

另一个黑客

我创建了一个脚本来读取文件package.json作为车把模板的上下文。

代码如下,以防有人发现这种方法有用:

const templateData = require('../package.json');
const Handlebars = require('handlebars');
const fs = require('fs-extra');
const outputPath = __dirname + '/../package-json-comments.md';
const srcTemplatePath = __dirname + '/package-json-comments/package-json-comments.hbs';

Handlebars.registerHelper('objlist', function() {
  // The first argument is an object, and the list is a set of keys for that obj
  const obj = arguments[0];
  const list = Array.prototype.slice.call(arguments, 1).slice(0,-1);

  const mdList = list.map(function(k) {
    return '* ' + k + ': ' + obj[k];
  });

  return new Handlebars.SafeString(mdList.join("\n"));
});

fs.readFile(srcTemplatePath, 'utf8', function(err, srcTemplate){
  if (err) throw err;
  const template = Handlebars.compile(srcTemplate);
  const content = template(templateData);

  fs.writeFile(outputPath, content, function(err) {
    if (err) throw err;
  });
});

车把模板文件package-json-comments.hbs

### Dependency Comments
For package: {{ name }}: {{version}}

#### Current Core Packages
should be safe to update
{{{objlist dependencies
           "@material-ui/core"
           "@material-ui/icons"
           "@material-ui/styles"
}}}

#### Lagging Core Packages
breaks current code if updated
{{{objlist dependencies
           "amazon-cognito-identity-js"
}}}

#### Major version change
Not tested yet
{{{objlist dependencies
           "react-dev-utils"
           "react-redux"
           "react-router"
           "redux-localstorage-simple"

}}}
于 2019-03-03T20:18:07.280 回答
0

我喜欢这个:

  "scripts": {
    "⏬⏬⏬ Jenkins Build - in this order ⏬⏬⏬                                                                                                  ": "",
    "purge": "lerna run something",
    "clean:test": "lerna exec --ignore nanana"
}

命令名称中有多余的空格,因此在 Visual Studio Code 的NPM Scripts插件中您可以更好地查看。

于 2020-06-18T19:25:02.300 回答
-1

我对 JSON 中没有评论感到沮丧。我创建了新节点,以它们引用的节点命名,但带有下划线前缀。这是不完美的,但很实用。

{
  "name": "myapp",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.3.2",
    "react-dom": "^16.3.2",
    "react-scripts": "1.1.4"
  },
  "scripts": {
    "__start": [
        "a note about how the start script works"
    ],
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  },
  "__proxy": [
    "A note about how proxy works",
    "multilines are easy enough to add"
  ],
  "proxy": "http://server.whatever.com:8000"
}
于 2018-05-30T22:30:55.037 回答