papiro
papiro

Reputation: 2365

package-lock.json contains non-exact versions

According to package-lock.json's documentation

It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.

I'm looking at a package-lock.json file which contains versions like:

"less": "^3.0.4",
"less-loader": "^4.1.0",
"license-webpack-plugin": "^1.3.1",
"lodash": "^4.17.4",
"memory-fs": "^0.4.1

in the requires block of one of the dependencies.

While the child dependencies of the main project are "locked down" in that there is no version ambiguity, these transitive dependencies are not. But how is npm "able to generate identical trees, regardless of intermediate dependency updates" if any of the dependencies in the tree are subject to interpretation?

Upvotes: 3

Views: 807

Answers (1)

papiro
papiro

Reputation: 2365

According to this thread, in npm@6 there was a change to how the package-lock.json represents dependency versions internally in that it records the originally requested ranged dependency, yet still locks down a specific version.

Previously, the package-lock did not record what version was originally requested by a dependency, only which version it resolved it to at the time of its creation.

Here's example: package-lock.json

// OLD npm format
// Notice that ajv.requires contains specific version for 'fast-json-stable-stringify'
// also notice that 'fast-json-stable-stringify' entry **mentions for the second time** specific version
{ 
    ...
    "dependencies": {
       ... 
        "ajv": {
                "version": "6.11.0",
                "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
                "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
                "dev": true,
                "requires": {
                    "fast-deep-equal": "3.1.1",
                    "fast-json-stable-stringify": "2.1.0",
                    "json-schema-traverse": "0.4.1",
                    "uri-js": "4.2.2"
                }
        },  
        ... 
        "fast-json-stable-stringify": {
            "version": "2.1.0",
            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
            "dev": true
        },
        ... 
    }
    ...
}
  

And here's npm6 approach


// "new" npm format (as of npm@6)
// Notice that ajv.requires is not showing specific versions
// but instead shows same values as package.json contains
// However 'fast-json-stable-stringify' entry contains 
// SPECIFIC version to have reproducible build
 
{ 
    ...
    "dependencies": {
       ... 
        "ajv": {
                "version": "6.11.0",
                "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz",
                "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==",
                "dev": true,
                "requires": {
                    "fast-deep-equal": "^3.1.1",
                    "fast-json-stable-stringify": "^2.0.0",
                    "json-schema-traverse": "^0.4.1",
                    "uri-js": "^4.2.2"
                }
        },  
        ... 
        "fast-json-stable-stringify": {
            "version": "2.1.0",
            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
            "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
            "dev": true
        },
        ... 
    }
    ...
}
  

Upvotes: 2

Related Questions