Workflow:

  1. Write in package.json (or npm install):

    "dependencies":{"react":"^18.2.0"}
    
  2. Run npm install

  3. npm installs 18.2.0 and also all required sub-packages (like scheduler, object-assign, etc.)

  4. npm auto creates/updates package-lock.json with exact versions

  5. Another developer clones the project and runs npm install → gets exactly the same environment.

package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "dependencies": {
    "react": "^18.2.0"
  },
  "devDependencies": {
    "eslint": "^8.39.0"
  }
  "scripts": {
	  "start": "vite",
	  "build": "vite build",
	  "lint": "eslint ."
}
}

package-lock.json

"node_modules/react": {
  "version": "18.2.0",
  "resolved": "<https://registry.npmjs.org/react/-/react-18.2.0.tgz>",
  "integrity": "sha512-..."
}

Example:

  1. If package.json says "react": "^18.2.0", npm could install 18.2.0 or any 18.x.x version.