Specifying precise versions is sufficient to ensure that the packages in your package.json are installed in the pinned versions. The problem solved by lockfiles is second, third and n-order dependencies. Just because you pinned precise versions does not mean react or vue or whatever random package you installed did as well.

That's where the lockfile comes in, it pins the dependencies of the dependencies.

The lockfile also handles the first-order dependencies, though. Pinning them in the manifest doesn't enforce this -- the lockfile does. And yes, I agree that the lockfile _also_ handles pinning dependencies-of-dependencies.

Lockfiles serve multiple purposes. For example, some include hashes so you aren't served altered packages from the package registry. I agree with you otherwise, though.