npm is forgiving — which means most teams develop bad habits without realizing it. These rules separate teams whose installs 'just work' from teams who debug install issues every other Monday.
Always commit package-lock.json. If a teammate has a different lockfile from yours, you're going to have different bugs. The lockfile is the install — commit it.
Use npm ci in every CI/CD pipeline. npm install updates the lockfile when it finds a better resolution; that's the wrong behavior in CI, where the install should be deterministic.
Run npm audit regularly. Add a weekly cron or a CI job that fails on critical vulnerabilities. Supply-chain attacks against npm are a real and growing risk.
Use npx for one-off tools. Globally installed packages are a maintenance burden; npx create-react-app works once and leaves no trace.
Pin dependencies for libraries; range them for apps. If you're shipping a library, pin exact versions to avoid breaking your consumers. If you're shipping an app, range them so security patches flow in.
Don't ship dev dependencies to production. npm install --omit=dev in production Docker builds keeps image size down and reduces attack surface.