605

I've got a simple package.json file and I want to add a comment. Is there a way to do this, or are there any hacks to make this work?

{
  "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 */
  }
}

The example comment above doesn't work as npm breaks. I've also tried // style comments.

5
  • 1
    possible duplicate of Can I comment a JSON file? Commented Jan 13, 2013 at 7:21
  • 40
    @YehudaKatz - I don't think it's a duplicate in that this question is specific to package.json files and there is a package.json specific answer on the NodeJS mailing list.
    – Mark Evans
    Commented Feb 11, 2013 at 21:13
  • 8
    One of the core npm developers has refused to consider comments support in package.json. Please comment on that issue - maybe we can show how useful comments can be. Commented Sep 11, 2015 at 8:24
  • 7
    One single tag <sarcasm />. JSON5 supports comments json5.org Commented Sep 7, 2016 at 9:53
  • More generally, Can comments be used in JSON? (the canonical question) Commented Oct 8, 2020 at 18:38

25 Answers 25

610

This has recently been discussed on the Node.js mailing list.

According to Isaac Schlueter who created npm:

... the "//" key will never be used by npm for any purpose, and is reserved for comments ... If you want to use a multiple line comment, you can use either an array, or multiple "//" keys.

When using your usual tools (npm, yarn, etc.), multiple "//" keys will be removed. This survives:

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

This will not survive:

{ "//": "this is the first line of a comment",
  "//": "this is the second line of the comment" }

One must be aware that "//" can only be used at the root of the package.json object. For example

{ 
  "//": "comment!", 
  "dependencies": {...}
} 

is valid but

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

is invalid.

-- @david_p comment

16
  • 82
    is there a way to doc what each entry in the 'dependencies' section is? the "//" trick does not work when its an attr of 'dependencies'.
    – rynop
    Commented Apr 2, 2013 at 20:06
  • 8
    Note that using multiple comments as in the first example { "//": "first", "//": "second"} prevents you from using npm version and other command line utils which usually reparse whole JSON and discard the duplicate keys in process.
    – jakub.g
    Commented Jul 1, 2014 at 11:51
  • 81
    One must be aware that "//" can only be used at the root of the package.json object. For example { "dependencies": { "//": "comment?" }} is invalid but { "//": "comment!", "dependencies":{}} is valid.
    – david_p
    Commented Jul 7, 2015 at 12:12
  • 76
    Even Douglas Crockford has no problem with putting comments in JSON config files. The situation with NPM is silly to say the least. Commented Jul 24, 2016 at 14:06
  • 6
    in my experience the "//" key and its value get wiped eventually. is there a way to have permanent comments?
    – pruett
    Commented Aug 19, 2016 at 19:17
291

After wasting an hour on complex and hacky solutions, I've found both simple and valid solution for commenting my bulky dependencies section in package.json. Just like this:

{
  "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"
  }
}

When sorted the same way, it's now very easy for me to track these pairs of dependencies/comments either in Git commit diffs or in an editor while working with file package.json.

And no extra tools are involved, just plain and valid JSON.

7
  • 13
    Thanks for a non-hacky solution that is technically valid and semantically helpful.
    – Roy Tinker
    Commented Dec 12, 2017 at 1:10
  • 11
    For comments about scripts, why not provide "help" scripts, e.g. "scripts": { "postinstall": "echo postinstall stuff goes here", "help-postinstall": "echo helpful stuff goes here" }
    – peak
    Commented Mar 5, 2018 at 18:44
  • 2
    @peak thanks! The only downside I see is that actual scripts will be blended with comments.
    – gkond
    Commented Mar 6, 2018 at 20:43
  • 2
    Works for me... and I combine it with using an array [] for multi-line comments. Like in @Igor Soarez's answer.
    – Davey
    Commented Feb 8, 2021 at 9:51
  • 1
    Would it be more readable and less likely to conflict if we use "//scripts" instead of "scriptsComments"? Commented Dec 20, 2022 at 3:01
128

DISCLAIMER: you probably should not use this hack. See comments below.


Here is another hack for adding comments in JSON. Since:

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

Is equivalent to:

{"a": 2}

You can do something like:

{
  "devDependencies": "'mocha' is not needed as it should be globally installed",
  "devDependencies" :  {
    "should": "*"
  }
}
9
  • 12
    This works at the specific package level too. For example. "express": "makes routing better so I don't want to gouge my eyes out", "express": "3.x". So, yes, "yuck" as ColinE says, and also "thanks" as ColinE says.
    – juanpaco
    Commented Mar 6, 2014 at 12:44
  • 24
    Note though that this hack prevents you from ever changing the package.json in a programmatic way, say by npm version 1.2.3 to bump the version - the redundant entries will be removed from the resulting JSON.
    – jakub.g
    Commented Jul 1, 2014 at 11:48
  • 21
    This is bad advice, because the order an object is interpreted isn't guaranteed. For example, in some situations, your example might end up with a being 1 instead of 2.
    – Jo Sprague
    Commented May 15, 2015 at 13:31
  • 8
    @mpen The risk is that there is no guarantee that the code parsing the JSON will do it sequentially.
    – Jo Sprague
    Commented Dec 22, 2015 at 16:57
  • 10
    For the record, the RFC explicitly says: " When the names within an object are not unique, the behavior of software that receives such an object is unpredictable. Many implementations report the last name/value pair only. Other implementations report an error or fail to parse the object, and some implementations report all of the name/value pairs, including duplicates. "
    – Alan Tam
    Commented Aug 24, 2017 at 0:27
80

I've been doing this:

{
  ...
  "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",
  }
  ...
}

This way, I can both read the "pseudo-comments" in the script itself, and also run something like the following, to see some kind of help in the terminal:

npm run about
npm run about:watch

Even better if you are using yarn.

yarn about:clean

Also, as pointed out by @Dakota Jang in comments, you can use keys like //something to make it even more clear that this is a comment.
Like so:

{
  ...
  "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",
  }
  ...
}

And then run:

npm run //build
# or
yarn //build

And you will have a helper output in your terminal, and a "comment" in your package.json as well.

2
  • 3
    In my opinion, this is the best option, as it allows users to get info on the commands without needing to actually open the package.json.
    – Rezkin
    Commented Jul 13, 2021 at 22:21
  • 3
    I am doing "//build": "echo 'something about build'". It makes the key a bit more prominent in my opinion... Commented Jan 8, 2022 at 19:49
29

NPS (Node Package Scripts) solved this problem for me. It lets you put your NPM scripts into a separate JavaScript file, where you can add comments galore and any other JavaScript logic you need to. https://www.npmjs.com/package/nps

Sample of the package-scripts.js from one of my projects:

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'
  }
}

I just did a local install npm install nps -save-dev and put this in my package.json scripts.

"scripts": {
   "start": "nps",
   "test": "nps test"
}
1
  • This is my favorite answer. And I use [nps] to do more, can use js code to control the flow of commands .
    – Lancer.Yan
    Commented Jun 29, 2020 at 7:38
28

Inspired by this thread, here's what we are using:

{
  "//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"
  }
}
1
  • 1
    I like this better, although the mailing list said "//" is reserved which means "//<TEXT>" is not reserved Commented Dec 3, 2020 at 10:14
24

Since most developers are familiar with tag/annotation-based documentation, the convention I have been using is similar. I like how the @ symbol stands out from the normal declarations.

Here is a taste:

{
  "@comment dependencies": {
    "@comment": [
      "These are the general/global comments for the `dependencies` section.",
      "They are not specific to a particular package.",
      "See below for how to add comments specific to a package.",
    ],
    "@package express": [
      "Use `@package {package-name}` to make comments specific to a package.",
      "",
      "This is a good place to explain why the version range isn't ", 
      "`^version` or why the latest major version isn't being used, ",
      "e.g., ESM is not supported in the project at the moment."
    ],
    "@package lodash": [
      "Until we add a tool to tree shake unused parts of a lodash, ",
      "only depend on the [per method packages](https://www.npmjs.com/search?q=keywords:lodash-modularized) ",
      "such as `lodash.debounce`."
    ]
  },
  "dependencies": {
    ...
  },
  "@comment scripts": {
    "@comment Use with NPM": [
      "Be sure to add ` -- ` before adding options.",
      "For example, `npm run build -- --opt1 val1`."
    ],
    "@comment Use with Yarn": "...",
    "@script build": "This comment is about the build script.",
    "@script start": [
      "This comment is about the `start` script.",
      "It is wrapped in an array to allow line formatting.",
      "",
      "@option {number} --port - The port the server should listen on."
    ],
    "@script test": "This comment is about the test script.",
  },
  "scripts": {
    "build": "...",
    "start": "...",
    "test": "..."
  }
}

Note: The name of the section being commented is included in the key after the @comment {section-name} 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. If the keys weren't unique, JSON validators, such as ones built into IDEs, will complain, or some tools, such as running npm install something, will rewrite the package.json file but with duplicate keys removed.

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.

It is recommended to use Markdown or something similar to help clarify your comments.

Note: For the dependencies, devDependencies, etc. sections, the comment annotations can't be added directly above the individual package dependencies inside the configuration object since npm is expecting the key to be the name of an npm package. Hence the reason for the @comment dependencies.

Note: For the dependencies, devDependencies, scripts, etc. sections, the embedded @comment keys may or may not contain a section name.

Older dependencies Recommendation

The following was my previous recommendation for the various dependency sections (dependencies, devDependencies, etc).

{
  "@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": {
    ...
  },
  "scripts": {
    ...
  },

Older scripts Recommendation

The following was my previous recommendation. It in-lined comments for the scripts, but I've come to realize that those comments show up as "commands" in some tools (in VS Code > Explorer > NPM Scripts section). The latest recommendation does not suffer from this issue but the script comments are no longer co-located.

{
  "@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": "..."
  }
}

Note: In certain contexts, such as in the "scripts" object, some editors/IDEs may complain about the array. In the scripts context, VS Code expects a string for the value — not an array.

3
  • This is the best solution I've come across, because it allows associating each comment with a specific key. This puts things in context much better than the "//" method, so the the comment can exist outside the object it references without any confusion. That's great for documenting config trees where the tool expects strict rules (eg eslint), and borks if it discovers anything foreign.
    – Andron
    Commented Mar 27, 2021 at 17:39
  • Nice one - I actually just use #, so for example inside scripts: { scripts: { "# my comments for dev go here":"or here", "dev": "npm-run-all build:watch~ serve:watch~ test:watch~" }} without any @tag etc, inside scripts, and it works great! I dont execute scripts from IDE's etc, I prefer the CLI, so it doesn't matter... What's with the tilda~? They start in their own Terminal and return control ;-) Commented Nov 10, 2023 at 9:53
  • Good approach. You can also use $comment instead of @comment, as in the JSON Schema standard
    – Artem
    Commented May 24 at 13:51
16

You can always abuse the fact that duplicated keys are overwritten. This is what I just wrote:

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

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

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

However, it is not clear whether JSON allows duplicated keys (see Does JSON syntax allow duplicate keys in an object?. It seems to work with npm, so I take the risk.

The recommened hack is to use "//" keys (from the nodejs mailing list). When I tested it, it did not work with "dependencies" sections, though. Also, the example in the post uses multiple "//" keys, which implies that npm does not reject JSON files with duplicated keys. In other words, the hack above should always be fine.

Update: One annoying disadvantage of the duplicated key hack is that npm install --save silently eliminates all duplicates. Unfortunately, it is very easy to overlook it and your well-intentioned comments are gone.

The "//" hack is still the safest as it seems. However, multi-line comments will be removed by npm install --save, too.

3
  • 1
    The "//" hack does not work inside devDependencies. NPM tries to resolve a UNC path.
    – Dmitry S.
    Commented Feb 9, 2016 at 4:38
  • Thanks for update sentence but again it cannot comment mocha attribute. Just it can add more than one of it and will be used by npm at the end.
    – vusan
    Commented Jan 4, 2017 at 11:04
  • "When I tested it, it did not work with "dependencies" sections" see this comment, the "//" key only works at the root.
    – icc97
    Commented Feb 1, 2023 at 9:27
11

I have a funny hack idea.

Create an npm package name suitably as a comment divider for dependencies and devDependencies block in file package.json, for example x----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": "*"
    }
}

NOTE: You must add the last comment divider line with a valid version, like * in the block.

3
  • 8
    yay, it's actually available: npmjs.com/package/x----x----x
    – revelt
    Commented Feb 14, 2017 at 14:07
  • 12
    Was thrilled about this answer but after I ran npm install (using npm 5) my duplicate keys were automatically removed :( Commented Jun 24, 2017 at 0:51
  • @EricMajerus oops~, npm5 break my heart also :( Commented Jun 26, 2017 at 2:33
11

So far, most "hacks" here suggest to abuse JSON. But instead, why not abuse the underlying scripting language?

Edit The initial response was putting the description on the right using # add comments here to wrap it; however, this does not work on Windows, because flags (e.g., npm run myframework -- --myframework-flags) would be ignored. I changed my response to make it work on all platforms, and added some indents for readability purposes.

{
 "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"
 }
}

This will:

  1. Not break JSON compliance (or at least it's not a hack, and your IDE will not give you warnings for doing strange, dangerous stuff)
  2. Works cross platform (tested on macOS and Windows, assuming it would work just fine on Linux)
  3. Does not get in the way of running npm run myframework -- --help
  4. Will output meaningful info when running npm run (which is the actual command to run to get information about available scripts)
  5. Presents a more explicit help command (in case some developers are not aware that npm run presents such output)
  6. Will show both the commands and its description when running the command itself
  7. Is somewhat readable when just opening package.json (using less or your favorite IDE)
7
  • Argh, actually on Windows it would just ignore flags, so 3. is not true :/ Commented Apr 4, 2017 at 6:01
  • 1
    Make it windows cmd compatible with: && instead of ; so the first command becomes: "help": "echo 'Display help information (this screen)' && npm run",
    – phil_lgr
    Commented Nov 5, 2017 at 20:53
  • 1
    Yes, thats what I ended up doing. Good catch! Commented Dec 5, 2017 at 2:58
  • 6
    It only works in the scripts section. package.json is many other things.
    – Rolf
    Commented Feb 14, 2018 at 2:33
  • 1
    @MarcTrudel: the reason why I had to add an obscure devDependency, or a TODO to upgrade one after a bug is fixed. Commented May 9, 2020 at 5:10
10

As this answer explains, the // key was reserved, so it can be used conventionally for comments. The problem with // comment is that it's not practical, because it can't be used multiple times. Duplicate keys are deleted on package.json automatic updates:

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

Another problem is that // comment can't be used inside dependencies and devDependencies because it's treated as a regular dependency:

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

npm ERR! code EINVALIDPACKAGENAME

npm ERR! Invalid package name "//": name can only contain URL-friendly characters

A workaround that works in NPM, but not Yarn, is to use a non-string value:

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

A workaround that works in NPM and Yarn is a comment added as a part of semantic versioning:

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

Notice that if the first part before OR doesn't match, versions from a comment can be parsed, e.g. 1.x.

Packages that need to be commented, but not installed, should be moved to another key, e.g. dependencies //:

"dependencies //": {
  "baz": "unused package",
}
4
  • With npm 8.5.2., the syntax "foo": "^2 || should be removed in 1.x release" worked with a local npm install, but in CI it gave me the error "Please update your lock file with npm install before continuing. Invalid: lock file's foo@2 does not satisfy foo@^2 || should be removed in 1.x release". Might be my problem. I did push the lock file.
    – Noumenon
    Commented May 3, 2022 at 16:44
  • @Noumenon Interesting. What happened during CI, was it npm install or npm ci that was used? Commented May 3, 2022 at 17:29
  • It's good to know that you still consider it ought to work. It was npm ci. I would guess then that I have a Node version mismatch on my Jenkins, as per stackoverflow.com/a/71845794/733092. Thanks.
    – Noumenon
    Commented May 4, 2022 at 13:50
  • 1
    @Noumenon Yes, didn't have problems with this approach so far. I'd pay the attention to NPM versions mismatch, it's the first thing to check for lockfile problems Commented May 4, 2022 at 13:57
7

Here's my take on comments within package.json / bower.json:

I have file package.json.js that contains a script that exports the actual package.json. Running the script overwrites the old package.json and tells me what changes it made, perfect to help you keep track of automatic changes npm made. That way I can even programmatically define what packages I want to use.

The latest Grunt task is here: https://gist.github.com/MarZab/72fa6b85bc9e71de5991

3
  • I think this is the "correct" answer in many ways (task to strip comments with diff patching to account for post-strip changes) -- however, I get the sense that the added weight of a grunt task is not what some people are after, For small projects, probably best to keep an external file for commentary and use NPM scrpts (avoids build tasks altogether). For large projects, you're probably using some form of task runner, so this approach seems solid. Between the two, I think maybe adapting the "//" suggestion to taste (avoiding one's particular pain points) is about the best that can be done.
    – Enull
    Commented Nov 1, 2016 at 22:43
  • 2
    I like this idea, but as someone asked on the gist, what about the case where you're modifying the original package.json through npm install --save or --save-dev? Commented Jun 28, 2017 at 16:57
  • yeah I keep missing those comments; theres no good solution, I used to look at git diffs and update my .js file after updating
    – MarZab
    Commented Jun 29, 2017 at 19:04
7

To summarise all of these answers:

  1. Add a single top-level field called // that contains a comment string. This works, but it sucks because you can't put comments near the thing they are commenting on.

  2. Add multiple top-level fields starting with //, e.g. //dependencies that contains a comment string. This is better, but it still only allows you to make top-level comments. You can't comment individual dependencies.

  3. Add echo commands to your scripts. This works, but it sucks because you can only use it in scripts.

These solutions are also all not very readable. They add a ton of visual noise and IDEs will not syntax highlight them as comments.

I think the only reasonable solution is to generate the package.json from another file. The simplest way is to write your JSON as JavaScript and use Node.js to write it to package.json. Save this file as package.json.mjs, chmod +x it, and then you can just run it to generate your 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));

It uses the // key to warn people from editing it. \x40generated is deliberate. It turns into @generated in package.json and means some code review systems will collapse that file by default.

It's an extra step in your build system, but it beats all of the other hacks here.

1
  • 5
    I do like this approach, but then again there comes the problem of running npm i ... and keeping the dependencies up to date in the source file Commented Dec 3, 2020 at 10:18
4

I ended up with a scripts like that:

  "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"
  },

My intent here is not to clarify one line, just to have some sort of delimiters between my scripts for backend, frontend, all, etc.

I'm not a huge fan of 1a, 1b, 1c, 2a, ... but the keys are different and I do not have any problem at all like that.

2

As of pnpm 7.17.1, which was just released, you can switch to pnpm for package management, move your package.json to package.json5, and comments in package.json5 are allowed and will be preserved by pnpm. Note however that for publishing as a package to use on the npm registry (for example), a package.json5 will not be recognized by other package managers and I doubt by all of the registry's processing. So you would have to convert the package.json5 to a package.json before publishing. On the other hand, for "top-level applications" that are unlikely to be included as packages in other projects, a package.json5 seems to work just fine, as long as you then stick with pnpm as your package manager.

1

As duplicate comment keys are removed running package.json tools (npm, yarn, etc.), I came to using a hashed version which allows for better reading as multiple lines and keys like:

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

which is 'valid' according to my IDE as a root key, but within dependencies it complains expecting a string value.

1
  • yeah b/c you can't really but the // key everywhere, it's not really a good substitute for comments, especially when comments can have nice syntax highlighting with an editor etc. Commented Nov 1, 2018 at 19:10
1

I do something that's some of you might like:

This // inside of the name means it's a comment for me:

  "//":"Main and typings are used till ES5",
  "//main": "build/index",
  "//typings": "build/index",
1

Commands in "scripts" are bash code - and we can comment bash:

"dedup": "yarn-deduplicate && yarn # TODO remove this on yarn/npm v2 because integrated"

Bonus: when you run it - you will see the comment too:yarn deduplication comment

0

Another hack

I created a script to read file package.json as the context for a handlebars template.

The code is below, in case someone finds this approach useful:

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

handlebars template file 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"

}}}
0

For npm's package.json, I have found two ways (after reading this conversation):

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

But with the update or reinstall of package with "--save" or "--save-dev, a comment like "^4.1.0 ! comment" in the corresponding place will be deleted. And all this will break npm audit.

1
  • 5
    wouldn't this try to install packages named del-comment and envify-comment ? Commented Mar 31, 2020 at 11:59
0

I like this:

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

There are extra spaces in the command name, so in Visual Studio Code's NPM Scripts plugin you have a better look.

1
  • 2
    Perhaps finally a reasonable way of using emojis? Commented Oct 19, 2020 at 23:40
0

Here is another take on that matter - for commenting scripts in npm.

Consider that scripts are arguments to 'npm run'. So what is the standard way of getting description of some commands passed through arguments?

One is usually typing executable command --help to get help on a command, another common pattern is executable help command. Following the second pattern you can have following code in your npm scripts:

"scripts": {
"help": "node -e \"const {spawn} = require('child_process');spawn('npm', ['run','help '+process.argv[1]],{stdio:'inherit'})\"",

"help some-command":"echo 'some-command executes a command sequence, the command line is: npm run some-command [--some-switch] [--some-parameter=value] '"

"some-command":"execute; command; sequence",
}

Now you can run intuitive command npm run help some-command and it will run the script "help some-command".

The "help" script is for convenience as it's only purpose is to not be forced to type unintuitive npm run "help some-command" with quotes in order to run the "help some-command" script.

0

I add a help script:

  "scripts" {
    "help": "cat ./help.md"
  }
-1

My take on the frustration of no comments in JSON. I create new nodes, named for the nodes they refer to, but prefixed with underscores. This is imperfect, but functional.

{
  "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"
}
1
  • using start_comment would be better, because then it will order alphabetically Commented Nov 1, 2018 at 19:11
-1

In addition to the global // comment (or array of comments), you can use the semver pipe separator for comments on particular dependencies, e.g.

"@types/node": "^16.11.7 || keep-same-major-version-as-node"

1
  • That looks very nice, but it would also lead to npm trying to resolve your comment as a package version / try to download it
    – The Nail
    Commented Jul 5, 2022 at 12:57

Not the answer you're looking for? Browse other questions tagged or ask your own question.