When you have to make changes to a third-party npm library, you usually have two choices:

  1. Fork the library and publish it as a new package.
  2. Or vendor the library and copy it into your project.

Both are valid options and depending on the scenario you have to decide which one’s better. In this blog post, I’ll show you how to do the latter.

What’s wrong with copy-and-paste?

The obvious solution is to clone the library into your repository and import the dependencies directly from source. Sometimes that works, but only if you can integrate the third-party code into your build pipeline. That’s not always easy or even possible. What, for example, if you have a JavaScript project but the library is written in TypeScript?

Fortunately, there’s an easier way to vendor a library: clone the library’s repository, make the necessary changes, build the project, and call npm pack to create a .tgz package.

git clone git@github.com/them/example-library.git
cd example-library
npm install
npm run build
npm pack <build-dir>

Then you copy the .tgz file to your project and install it.

cp example-library-1-0-0.tgz /path/to/your/project/vendor/example-library-1-0-0.tgz
cd /path/to/your/project
npm install ./vendor/example-library-1-0-0.tgz

The library has been added as a local dependency to your package.json.

{
  "name": "your-project",
  "dependencies": {
    "example-library": "file:vendor/example-library-1-0-0.tgz"
  }
}

If you’re not building a library yourself, meaning you don’t publish your-project and install it someplace else, that’s all you have to do. Otherwise, there’s one more thing.

When you’re creating your own library

In that case, things are slightly more complex. Now you have two projects:

  • your-library, which vendors the example-library
  • and your-project, which depends on your-library

If you follow the steps above, you’ll come across an issue once you run npm install your-library.

ENOENT: no such file or directory, open /path/to/your-project/node_modules/your-library/vendor/example-library-1-0-0.tgz

The error is telling you that npm is unable to find the vendored dependency when installing your library. The problem is that vendor/example-library-1-0-0.tgz only exists inside your-library/, but not inside your-project/. Therefore npm can’t install it.

To fix that, you have to tell npm to include the vendored dependency with your package. Luckily, that’s easy: just add the example-library as a bundledDependency to the package.json.

{
  "name": "your-library",
  "dependencies": {
    "example-library": "file:vendor/example-library-1-0-0.tgz"
  },
  "bundledDependencies": [
    "example-library"
  ]
}

That’s it! Now you can npm install your-library without any issues.