用自己的实现替换 npm 包

Substitute an npm package with own implementation

在我的 package.json 我有一个依赖关系 "protractor": "2.1.0"。该包又取决于 "jasminewd2": "0.0.5".

那个 jasminewd2 包有一些我想修改的行为。我下载了它的源代码并进行了我需要的更改。 Yarn's documentation 讲述了使用本地资源包的可能性:

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.

当我执行那个命令时

  1. "jasminewd2": "file:\CustomNodeModules\jasminewd2" 被添加到我的 package.json.
  2. 这是我的 yarn.lock 文件:

    "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"
    

因此,node_modules/jasminewd2 包含来自 npm 存储库的原始版本。我怎样才能让 yarn 安装我的版本?

我认为您的解决方案不起作用,因为 jasminewd2 是(protractor 的)传递依赖,而不是直接依赖。所以当你直接添加它时,传递的不受影响。

您可以使用 3 种方法解决此问题:

  1. 如果您的更改是临时的(用于开发或故障排除),您应该 yarn linkdocumentation 中所述。
  2. 否则,您可以分叉 protractorjasminewd2 包并在各自的 package.json 中引用它们。 package.jsons syntax for that"protractor": "<githubUser>/<githubRepo>".
  3. 使用 yarnresolutions field"resolutions": { "jasminewd2": "desired-version-or-url-or-path" }。我知道 PNPM 也有类似的功能(但我自己没用过)。

根据我的经验,选项 2 和 3 以包管理器缓存的形式存在警告:您的 git 存储库的 HEAD 仅在该依赖项首先 时被拉出安装。之后,它每次都会被缓存并重新安装 - 即使您的回购协议 HEAD 已更改。

解决方法是引用一个提交散列作为依赖的一部分,如下所示:"dependency": "user/repo.git#aef38fb2adc73304ae1ea87b0d607ad7fadc4d0g".

使用 postinstall 和 git

覆盖子模块

npm 方式”需要特定的提交(或 version/tag)才能从 git 存储库安装包,more info on npm install .我通常会创建一个自定义分支并对其进行推送,所以我希望能够克隆一个自定义分支来测试特定功能,或者只留下 master。

为了覆盖一个包,我使用了 npm 的 postinstall hook 钩子。

我在 package.json 中添加脚本到 postinstall:

"scripts": {
  "postinstall": "./postinstall.sh",
  "start": "node index.js"
},

然后我使用 bash 脚本 (postinstall.sh) 删除软件包并从 github:

克隆它们
#!/bin/sh

function override_pkg {
  USER=
  REPO=
  DEST=

  rm -rf node_modules/$DEST

  echo "Overriding $DEST..."

  if [ -d custom_modules/$DEST ]; then
    cd custom_modules/$DEST
    git pull
    cd ../../
  else
    case $REPO in
      *:*)
      REPOBR=(${REPO//:/ })
      git clone -b ${REPOBR[1]} https://github.com/$USER/${REPOBR[0]}.git custom_modules/$DEST
      ;;
      *)
      git clone https://github.com/$USER/$REPO.git custom_modules/$DEST
      ;;
    esac
  fi

  npm install custom_modules/$DEST
}

# func       user    repo   branch dest
override_pkg johndoe myrepo:branch mynpmpackage

该脚本在 custom_modules 文件夹中克隆一个包,然后使用 npm 将本地包安装到 node_modules: 后的分支名称是可选的。

在OP的情况下应该是这样的:

override_pkg johndoe jasminewd:jasminewd2 jasminewd2

然后纱线:

yarn

如果我对 custom_modules\mypackage 中的本地 git 存储库进行一些本地更改,我会再次调用 yarn 以重新覆盖 pacakge。

如果我换了机器并且我已经有了自定义包的本地版本,那么调用 yarn 将从存储库中提取并覆盖包。

PS。 npm install 也可以,但是 yarn 快一点。

用于测试目的的多个环境

这是一个不同的想法,但有时我用它来测试不同的配置。也许人们会发现它有用,或者如果有人知道这样做的工具或东西,请告诉我。

我在本地为 node_modules 创建两个不同的文件夹,如下所示:

首先是原始模块:

yarn --modules-folder=original-modules

标志:

  • --modules-folder <path> 而不是将模块安装到相对于 cwd 的 node_modules 文件夹中,而是在此处输出它们。

然后对于自定义的,我可以简单地复制 original-modules 作为克隆:

cp -r original-modules custom-modules

或者我可以使用 yarn 添加更多自定义模块:

yarn add <modulename> --no-lockfile --modules-folder=custom-modules

标志:

  • --no-lockfile 不读取或生成锁定文件

当我对 custom-modules 文件夹感到满意时,我可以使用 NODE_PATH:

在这样的环境之间切换

对于普通环境:

NODE_PATH=original-modules npm start

自定义环境:

NODE_PATH=custom-modules npm start

重要的是 node_modules 文件夹 不存在 否则覆盖将不起作用,本地 node_modules 文件夹的优先级高于 NODE_PATH.