preface

It has been more than two years since Yarn introduced lock files, and NPM has added similar functionality in version 5.0. Lock files are becoming more and more accepted by developers. This article looks at why we need the Lock file from a front-end perspective, and some of its costs and risks, although some of these ideas apply to the back end as well.

Why do I need the Lock file

I think there are four main reasons for locking files:

Ensure consistency across environment dependent versions

Software development typically has several environments, including a local development environment, an integrated test environment, a pre-release environment, and an online environment. Inconsistent versions of dependencies across environments are often a source of bugs, and you may have encountered the “it’s fine on my computer” problem, which may be caused by inconsistent versions of dependencies. This kind of problem is often difficult to locate because it’s hard to determine if it’s your problem or a dependency problem. This is one of the original reasons for Yarn to introduce lock files. With lock files, you can at least eliminate the dependency version inconsistency factor when troubleshooting problems.

Semantic versions are not infallible

One of the main reasons some developers are reluctant to use lock files is that they want their dependencies to be automatically upgraded based on the semantic version number, believing that as long as the selected dependencies are reliable, they can safely upgrade without changing the large version. In the vast majority of cases this is fine, but there are some unexpected situations, such as:

React tweaked the call timing for getDerivedStateFromProps in V16.4.0. React introduced this API in V16.3.0, which was originally called only during rerenders caused by the parent component. V16.4.0 changed it to be called during all renders. If you (automatically) upgrade React from V16.3.0 to V16.4.0 without your knowledge, your application will suffer in extreme cases.

It’s only in the most extreme cases that you’ll encounter this kind of problem, but it’s one of those things where you’re afraid to take chances.

Controllable upgrade dependencies

It is now a common practice to separate dependencies into vendor.js via Webpack, because dependency changes are relatively infrequent, and with strong caching, users can use cached Vendor.js even when a new version is released without having to re-download it. Often our application has more than one dependency, and these dependencies are definitely not updated at the same time, and leaving them free to update without using the lock file can cause vendor.js cache to invalidate multiple times (each dependency update invalidates the cache). Using a lock file can increase vendor.js cache hit ratio by accumulating time, allowing multiple dependencies to update centrally, and even skipping minor version updates.

Security issues

There was a security incident with ESLint a few months ago when an attacker stole the NPM account of an ESLint maintainer and released malicious versions of ESLint-Scope and ESlint-config-ESLint (both smaller and newer versions), The former is a dependency of babel-esLint and WebPack. If you are not using the lock file, you are most likely to be fooled, and ESLint later advised developers to use the lock file to avoid automatically installing new versions.

The cost of

Using the Lock file naturally adds a bit of maintenance cost to the project, since dependencies are no longer automatically upgraded, requiring the project maintainer to manually upgrade them at regular intervals. In addition, if two people change dependencies at the same time, resolving the lock file conflicts is also very troublesome.

However, there is an added benefit to manually upgrading dependencies. At the very least, you need to look at the change log for each dependency so that you can keep track of each upgrade, which will help you to keep track of the trend of dependencies. In the React example, it’s easy to avoid problems if you look at its change log while upgrading.

risk

The only risk I can think of is versioning. If you use the LOCK file and don’t take the time and effort to maintain it, your project can easily fall into versioning problems. If you go too long without an upgrade dependency, and your current version is too different from the latest version, upgrading will be difficult and, given the realistic cost, may never happen.

But is it possible to completely avoid this problem without using the lock file? I don’t think so. At best, you can only upgrade automatically within the same large version without using lock files. If you rely on upgrading a large version, you will run into the same problem without taking the time to upgrade. The problem just comes to light later than when you don’t use lock files.