Search code examples
javascriptnpmyarnpkg

Substitute an npm package with own implementation


In my package.json I have a dependency "protractor": "2.1.0". That package in turn depends on "jasminewd2": "0.0.5".

That jasminewd2 package has some behavior which I want to modify. I downloaded its sources and made the changes I need. Yarn's documentation tells about a possibility to use a local source for packages:

yarn add file:/path/to/local/folder installs a package that is on your local file system. This is useful to test out other packages of yours that haven’t been published to the registry.

When I execute that command

  1. "jasminewd2": "file:\\CustomNodeModules\\jasminewd2" gets added to my package.json.
  2. And this to my yarn.lock file:

    "file:\\CustomNodeModules\\jasminewd2", jasminewd2@0.0.5:
      name jasminewd2
      version "0.0.5"
      resolved "https://registry.yarnpkg.com/jasminewd2
         /-/jasminewd2-0.0.5.tgz#528609a124dfc688c1e3f434a638e047066cd63e"
    

As a result, node_modules/jasminewd2 contains the original version from the npm repository. How can I make yarn install my version instead?


Solution

  • I believe your solution doesn't work because jasminewd2 is a transitive dependency (of protractor) and not a direct one. So when you add it directly, the transitive one isn't affected.

    You can work around that using 3 approaches:

    1. In case your change is temporary (meant for development or troubleshooting), you should yarn link as described in the documentation.
    2. Otherwise, you can fork both protractor and jasminewd2 packages and reference them in the respective package.jsons. package.jsons syntax for that is "protractor": "<githubUser>/<githubRepo>".
    3. Using yarn's resolutions field: "resolutions": { "jasminewd2": "desired-version-or-url-or-path" }. I know that PNPM has an equivalent feature too (but haven't used it myself).

    From my experience, options 2 and 3 have a caveat in the form of the package manager cache: your git repo's HEAD is only pulled when that dependency is first installed. After that, it is kept cached and reinstalled every time - even when your repo's HEAD has changed.

    The workaround is to reference a commit hash as part of the dependency like so: "dependency": "user/repo.git#aef38fb2adc73304ae1ea87b0d607ad7fadc4d0g".