Skip to content

[RRFC] Opt-in solution to support comments in package.json (among other features) #291

@TheJaredWilcurt

Description

@TheJaredWilcurt

Edit: I simplified this section and incorporated all comments and concerns up to this point. In hopes that this can finally proceed to be implemented.

Motivation

It is now common for modern frontend/backend applications using Node to have dozens of dependencies and npm scripts, and even configurations for tools like ESLint, Jest, etc. stored in the package.json directly.

This can make the maintenance of a project more difficult when it comes to how and were to document things related to the package.json file. Most commonly things around why dependencies were added, how dependencies are related, why a dependency is pinned to a specific version, and reasons for specific npm scripts. Currently package.json auto-alphabetizes dependencies, removing any intentional grouping of like-items (Example: babel-jest, jest, vue-jest would logically be grouped and related to unit testing, but with a single npm install they are mixed in with the rest).

There is a need for a more permissive format for writing a manifest file.

Opt-in, Backwards compatible, Solution

When the npm executable is called and needs to access the package.json (such as npm i, npm run, npm publish, npm start, npm t, npm audit, etc) it will first check for a package.json5 file. If it exists, it will process it and override the existing package.json file, then proceed as usual.

Benefits:

  • Fully opt-in - Projects that need the additional capabilities of json5 have easy access to them, while those that don't need them can continue using package.json as they always have.
  • Fully backwards compatible - Since the package.json is always kept in sync with the package.json5, nothing needs to change for Node, or any other tooling. Everything still works.
    • All existing tooling that reads from the package.json continues to work exactly the same.
  • People seem to miss that last bullet point, so I'm repeating it here: NO CHANGES TO NODE OR JAVASCRIPT OR BROWSERS ARE REQUIRED. This is a change npm can make unilaterally.
  • Features:
    • Complete control over the file
    • Single (//) and Multi-line comments (/**/)
    • Order of dependencies is preserved
    • Allows for empty lines to add visual white space between sections
    • Unquoted keys (scripts: {)
    • Use of single quotes (lint: 'eslint')
    • Trailing commas
    • and more
  • A brighter and happier future for all 😃

Edge-cases

  • Users of older versions of npm working in repos using this feature would need to either:
    • Use a tool like Volta to automatically ensure their node/npm version matches what the repo expects
    • Manually upgrade to a newer npm version that handles json5 automatically
    • Manually run npx json5 package.json5 to process the file by hand

Downsides (these are all very minor)

  • npm would need to ship with an additional dependencies (json5). It already ships with over 400, so this is a non-issue.
  • Tooling that writes to the package.json directly would require repo maintainers to manually move those changes over to the package.json5 file. Though updating these tools to support the new format would be very easy in almost all scenarios. Example:
     // Start of file
     const fs = require('fs');
    +const JSON5 = require('json5');
    
    -const manifest = require('package.json');
    +const newManifestFormat = fs.existsSync('./package.json5');
    +const manifest = newManifestFormat ? JSON5.parse(fs.readFileSync('package.json5')) : require('package.json');
    
     // No other code changes until the end of the file
    +const stringify = newManifestFormat ? JSON5.stringify : JSON.stringify;
    -const output = JSON.stringify(manifest, null, 2);  
    +const output = stringify(manifest, null, 2);  
     fs.writeFileSync('./package.json', output);
  • If Node ever officially adopts a new format to replace the package.json; they may pick something other than JSON5 (TOML, HJSON, YML, whatever). npm would then need to deprecate JSON5 support as the community transitions over to the same format. I don't forsee Node ever doing this, and if they do npm's use of JSON5 would likely drive them to adopting the same format, avoiding this unlikely downside alltogether.

References

  • pnpm has allowed the usage of package.json5 as a replacement for a package.json. However it does not compile a package.json during use, leading to members of the community to decry it as breaking backward compatibility. Thus it exists, but is not recommended by the docs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions