patch-package Not Available in pnpm

Introduction

In the process of front-end development, we often encounter bugs in third-party open source libraries. Usually we have the following ways to deal with them.

  1. Fork a source code modification by yourself. After repairing, you can package it locally and use it directly. If you want to share your research results with others, you can upload it to the npm repository or submit a PR to the source repository. The disadvantage of this method is that it is difficult to keep the notes synchronized with the official library.
  2. Wait for the library author to fix it. This method is not very reliable, because open source authors are generally busy, and your needs may not be ranked first.

Some friends don't know, there is another solution to patch the local npm package. It means that when your project normally installs an npm dependency, by adding a patch file to the project, the changes to the npm package can be persisted to the project. This enables bug fixes for open source libraries to be applied directly to the project.

I learned that there is an open source library called patch-package, which can easily patch the node_modules library. Next, let's take a look at how to use patch-package and what are the problems with using it.

How to use patch-package

By referring to the official tutorial, you can quickly patch the local npm package in a few simple steps.

  1. Find the source code of the npm dependency package from node_modules and fix the errors in the dependency package
vim node_modules/my-package/common.js
  1. Run patch-package to create a .patch file, the .patch file can be automatically recognized and applied by npm
npx patch-package my-package
  1. Submit the patch file to share the fix with your team
git add patches/my-package+3.14.15.patch
git commit -m "fix common.js in my-package"
  1. Install the dependencies
npm i -D patch-package
  1. Add a script postinstall to package.json, which will automatically execute patch-package after npm i to make the patch take effect
"scripts": {
    "postinstall": "patch-package"
 }

Due to the pnpm package manager used by me, an error was reported when executing npx patch-package my-package

**ERROR** No package-lock.json, npm-shrinkwrap.json, or yarn.lock file.

You must use either npm@>=5, yarn, or npm-shrinkwrap to manage this project's
dependencies.

It probably means that npm, yarn package managers are supported, but pnpm is not supported.

The official also does have a bug. As of June 18, 2022, the issue has not been fixed.

Someone has filed a bug with patch-package, see issue :How to execute patch to dependencies in other dependencies, when using pnpm #338

However, my ability is limited, so I can only find another way and take a workaround.

pnpm patch

The idea of patching npm dependencies under the pnpm package manager is to copy the modified source files and put them in the project. After each execution of npm i to install dependencies, use the nodejs script to copy the modified files to the source code directory, overwrite the source code, and achieve the purpose of modifying the code.

  1. Modify the source file of the dependency package in node_modules and copy it to the patches directory of the root directory
vim node_modules/my-package/common.js
cp node_modules/my-package/common.js patches/my-package
  1. Create a new script postinstall.js in the project to realize the operation of overwriting the source code file
copyFileSync('./patches/my-package/common.js', './node_modules/my-package/common.js');

function copyFileSync(source, target) {
    var targetFile = target;

    // If target is a directory, a new file with the same name will be created
    if (fs.existsSync(target)) {
        if (fs.lstatSync(target).isDirectory()) {
            targetFile = path.join(target, path.basename(source));
        }
    }

    fs.writeFileSync(targetFile, fs.readFileSync(source));
}
  1. Add a postinstall command to package.json pointing to our script
"scripts": {
    "postinstall": "node scripts/postinstall.js"
 }

Conclusion

The above is the solution that I implemented to patch npm packages in a project using pnpm package manager. If you have better solutions, please share them.

Reference

Comments