-
Notifications
You must be signed in to change notification settings - Fork 251
Description
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
json5have easy access to them, while those that don't need them can continue usingpackage.jsonas they always have. - Fully backwards compatible - Since the
package.jsonis always kept in sync with thepackage.json5, nothing needs to change for Node, or any other tooling. Everything still works.- All existing tooling that reads from the
package.jsoncontinues to work exactly the same.
- All existing tooling that reads from the
- 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
npmversion that handlesjson5automatically - Manually run
npx json5 package.json5to process the file by hand
Downsides (these are all very minor)
npmwould 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.jsondirectly would require repo maintainers to manually move those changes over to thepackage.json5file. 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
pnpmhas allowed the usage ofpackage.json5as a replacement for apackage.json. However it does not compile apackage.jsonduring use, leading to members of the community to decry it as breaking backward compatibility. Thus it exists, but is not recommended by the docs.