【问题标题】:Installing a local module using npm?使用 npm 安装本地模块?
【发布时间】:2011-12-26 16:34:22
【问题描述】:

我有一个下载的模块存储库,我想在本地安装它,而不是全局安装在另一个目录中?

有什么简单的方法可以做到这一点?

【问题讨论】:

    标签: javascript node.js npm packages npm-install


    【解决方案1】:

    您只需向npm install 提供一个<folder> 参数,参数应指向本地文件夹而不是包名:

    npm install /path
    

    【讨论】:

    • 与链接不同,它使用 .npmignore。
    • @bithavoc 至少从 npm 5 开始,安装文件夹现在会创建一个符号链接,不是副本。见docs.npmjs.com/cli/install
    • 我尝试使用这种方式,但是我的模块找不到它的 peerDependencies。
    • 运行答案脚本之前rm -rf node_modules 和npm install 很好。
    • @FrankTan 是的,但是如何获得旧的行为?我想要副本!
    【解决方案2】:

    来自npm-link documentation:

    在本地模块目录中:

    $ cd ./package-dir
    $ npm link
    

    在项目目录下使用模块:

    $ cd ./project-dir
    $ npm link package-name
    

    或者一次性使用相对路径:

    $ cd ./project-dir
    $ npm link ../package-dir
    

    这相当于在后台使用上面的两个命令。

    【讨论】:

    • 这是迄今为止我见过的唯一看起来很理智的方法 - 为什么 npm 必须如此晦涩/迟钝。关于创建本地包,安装它然后使用它,我不知道......链接有效,(而且它很棒),但术语相当混乱。
    • @Rich Apodaca,感谢您的文档链接。它没有提到撤消该过程。看起来它所做的只是创建符号链接,所以我可以照常删除它们?
    • @TylerCollier npm unlink 似乎是镜像操作stackoverflow.com/a/24940024/54426
    • 请注意,如果您使用 Angular2(或者可能是其他应用程序?),关于 npm 链接作为特定类型问题的根本原因存在一些嗡嗡声。示例 here 和 here
    • 但是请记住,npm link 将创建第二个外部依赖项实例。所以如果你有一个包 A 需要 B 和 C,B 需要 C。链接 B 将导致应用程序 A 有两个 C 实例。
    【解决方案3】:

    由于是同一个人提问和回答的,所以我会添加一个npm link作为替代。

    来自文档:

    这对于安装您自己的东西非常方便,这样您就可以对其进行处理和迭代测试,而无需不断地重新构建。

    cd ~/projects/node-bloggy  # go into the dir of your main project
    npm link ../node-redis     # link the dir of your dependency
    

    [编辑] 从 NPM 2.0 开始,您可以在 package.json 中声明本地依赖项

    "dependencies": {
        "bar": "file:../foo/bar"
      }
    

    【讨论】:

    • 这可能不是问题的初衷,但这可能是大多数通过谷歌找到这个问题的人想要的。
    • 这个答案似乎不完整,您需要对文件夹运行一次npm link(创建全局符号链接),然后在项目文件夹中运行npm link package-name(使用全局符号链接你的项目)。下面的答案是正确的答案。
    • @ThomasPotaire 两个答案都是正确的。如果您查看 npm 链接文档,它会介绍这两种方法,并以这种相对目录方法作为简写。
    • 第二种方法(使用file: 方法)允许我的应用程序和本地模块共享依赖项。我对npm link 的测试导致了重复的依赖项,如果需要将依赖项用作单例,这会破坏事情。
    • 我有一个本地包(比如 package1),package2 有一个依赖关系,其中提到了 package1 的相对路径。当相对路径以 "file:../../package1" 开头时,npm 我没有安装包,当它是 ''../../package1" 时工作,在开头添加文件是否意味着什么?跨度>
    【解决方案4】:

    npm pack + package.json

    这对我有用:

    第一步:在module project中,执行npm pack:

    这将构建一个<package-name>-<version>.tar.gz 文件。

    第 2 步:将文件移动到 consumer project

    理想情况下,您可以将所有此类文件放在您的consumer-project 根目录下的tmp 文件夹中:

    第 3 步:在您的 package.json 中引用它:

    "dependencies": {
      "my-package": "file:/./tmp/my-package-1.3.3.tar.gz"
    }
    

    第 4 步:Install 包:

    npm install 或 npm i 或 yarn

    现在,您的包将在您的 consumer-project's node_modules 文件夹中可用。

    祝你好运……

    【讨论】:

    • 打包前忘记建包了,所以之前npm run build。
    • 这是最好的回复,因为它也安装了子依赖!
    • 是的,如果您在dependencies 中使用file:<package_root_path>(不是包文件的路径)从本地文件系统安装包。本地包不会复制到您的node_modules,而是链接到node_modules。使用npm i,可以自动安装子依赖,但不能与其他包共享子依赖。在这种情况下,如果您想将关键字用于本地项目中的对象,instanceof 关键字可能无法按预期工作。所以,我认为npm pack + package.json 是一个合理的解决方案。
    【解决方案5】:

    如果本地模块具有您只想在项目范围内安装的对等依赖项,则这些方法(npm link 或 package.json 文件依赖项)都不起作用。

    例如:

    /local/mymodule/package.json:
      "name": "mymodule",
      "peerDependencies":
      {
        "foo": "^2.5"
      }
    
    /dev/myproject/package.json:
      "dependencies":
      {
        "mymodule": "file:/local/mymodule",
        "foo": "^2.5"
      }
    

    在这种情况下,npm 像这样设置myproject 的node_modules/:

    /dev/myproject/node_modules/
      foo/
      mymodule -> /local/mymodule
    

    当节点加载mymodule 并执行require('foo') 时,节点解析mymodule 符号链接,然后只在/local/mymodule/node_modules/(及其祖先)中查找foo,但它没有找到。相反,我们希望节点查看 /local/myproject/node_modules/,因为这是运行我们的项目的位置,也是安装 foo 的位置。

    所以,我们要么需要一种方法来告诉 node 在查找 foo 时不解析这个符号链接,要么我们需要一种方法来告诉 npm 安装一个副本 在mymodule 中使用文件依赖语法时package.json。不幸的是,我也没有找到办法:(

    【讨论】:

    • 我找到了一个解决方法,即将NODE_PATH 指向安装了foo 的node_modules/。所以对于上述情况,它会是这样的:NODE_PATH=/dev/myproject/node_modules/ 允许mymodule 找到foo。
    • 有一个解决方案。将依赖模块放入项目根文件夹。在 package.json 中使用通常的 'file:' 前缀定义您的依赖项。执行 npm i 这将在项目的 node_modules 中创建一个符号链接,并且它的依赖项可能会像其他类型的依赖项一样被提升到顶级 node_modules。我的 npm 版本是 v6.14.4 。在花了几个小时解决这个问题后,在这里找到了这个解决方案:(atmos.washington.edu/~nbren12/reports/journal/…)。谢谢 nbren12。
    • 我遇到了同样的麻烦。我找到了这个答案:stackoverflow.com/questions/50807329/…,这解决了我的对等依赖项和本地库的问题。
    【解决方案6】:

    所以到目前为止提到的所有解决方案我都遇到了很多问题......

    我有一个本地包,我想始终引用它(而不是 npm 链接),因为它不会在这个项目之外(目前)使用,也不会上传到 npm 存储库以供广泛使用还没有。

    我还需要它在 Windows 和 Unix 上工作,所以符号链接并不理想。

    指向 (npm package) 的 tar.gz 结果适用于依赖的 npm 包文件夹,但是如果您想更新包,这会导致 npm 缓存出现问题。当你更新它时,它并不总是从引用的 npm 包中拉入新的,即使你吹掉 node_modules 并为你的主项目重新执行你的 npm-install。

    所以..这对我来说很有效!

    主项目的 Package.json 文件片段:

      "name": "main-project-name",
      "version": "0.0.0",
      "scripts": {
        "ng": "ng",
        ...
        "preinstall": "cd ../some-npm-package-angular && npm install && npm run build"
      },
      "private": true,
      "dependencies": {
        ...
        "@com/some-npm-package-angular": "file:../some-npm-package-angular/dist",
        ...
      }
    

    这实现了 3 件事:

    • 避免常见错误(至少对于有角度的 npm 项目)“index.ts 不是编译的一部分。” - 因为它指向 build (dist) 文件夹。
    • 添加一个预安装步骤来构建引用的 npm 客户端包,以确保构建我们依赖包的 dist 文件夹。
    • 避免了在本地引用 tar.gz 文件可能会被 npm 缓存并且在没有大量清理/故障排除/重新构建/重新安装的情况下不会在主项目中更新的问题。

    我希望这很清楚,并且可以帮助某人。

    tar.gz 方法也有点工作..

    npm install(文件路径)也可以。

    这一切都基于从 openapi 规范生成的客户端,我们希望将其保存在单独的位置(而不是对单个文件使用 copy-pasta)

    ====== 更新: ======

    上述解决方案的常规开发流程存在其他错误,因为 npm 的本地文件版本控制方案绝对糟糕。如果您的依赖包频繁更改,则整个方案将中断,因为 npm 将缓存您的项目的最后一个版本,然后当 SHA 哈希与您的 package-lock.json 文件中保存的内容不再匹配时崩溃,以及其他问题.

    因此,我建议使用 *.tgz 方法,每次更改都进行版本更新。这通过做三件事来起作用。

    第一:

    对于您的依赖包,请使用 npm 库“ng-packagr”。这会自动添加到由 OpenAPI 3.0 的 angular-typescript 代码生成器创建的自动生成的客户端包中。

    因此,我引用的项目在 package.json 中有一个“脚本”部分,如下所示:

      "scripts": {
        "build": "ng-packagr -p ng-package.json",
        "package": "npm install && npm run build && cd dist && npm pack"
      },
    

    并且引用此其他项目的项目添加了一个预安装步骤,以确保依赖项目是最新的并在构建自身之前重新构建:

      "scripts": {
        "preinstall": "npm run clean && cd ../some-npm-package-angular && npm run package"
      },
    

    第二

    从你的主项目中引用构建的 tgz npm 包!

      "dependencies": {
        "@com/some-npm-package-angular": "file:../some-npm-package-angular/dist/some-npm-package-angular-<packageVersion>.tgz",
        ...
      }
    

    第三

    每次更新依赖包时更新依赖包的版本。您还必须更新主项目中的版本。

    如果您不这样做,NPM 将阻塞并使用缓存版本,并在 SHA 哈希不匹配时爆炸。 NPM 版本基于文件的包基于文件名的变化。它不会在 package.json 中检查包本身是否有更新版本,NPM 团队表示他们不会解决这个问题,但人们不断提出这个问题:https://github.com/microsoft/WSL/issues/348

    现在,只需更新:

    "version": "1.0.0-build5",
    

    在依赖包的 package.json 文件中,然后在主项目中更新对它的引用以引用新文件名,例如:

    "dependencies": {
           "@com/some-npm-package-angular": "file:../some-npm-package-angular/dist/some-npm-package-angular-1.0.0-build5.tgz",
            ...
    }
    

    你习惯了。只需更新两个 package.json 文件 - 版本然后将 ref 更新为新文件名。

    希望对某人有所帮助...

    【讨论】:

      【解决方案7】:

      缺少主要属性?

      正如以前的人已经回答了npm i --save ../location-of-your-packages-root-directory。 但是,../location-of-your-packages-root-directory 必须具备两个条件才能使其工作。

      1. package.json 在指向的那个目录中

      2. package.json 中的main 属性必须设置并正常工作,例如 "main": "src/index.js", 如果../location-of-your-packages-root-directory 的入口文件是../location-of-your-packages-root-directory/src/index.js

      【讨论】:

      • npm --save?你是说npm i --save? (现在相当于npm i)
      • @AdamJagosz 已修复!
      【解决方案8】:

      对于更新版本的 npm(我在 macOS Big Sur 下使用的是 8.1.3),命令序列更加简单......

      cd /path-where-your-local-project-is/
      npm init
      

      这将要求您提供与您的项目相关的一些数据并正确初始化您的project.json 文件。

      完成后,您可以安装其他模块:

      cd /path-where-your-local-project-is/
      npm install --save-dev some-npm-module .
      

      这就是你所需要的!

      注意:我相信如果你在项目目录中,尾随点不是必需的,但我也认为添加它并没有什么坏处:-)

      (我不知道为什么官方文档仍然没有解释这个......)

      【讨论】:

      • 我做了一些测试,确实,当您已经在其中时,它似乎可以在没有指定当前目录的点的情况下工作。
      猜你喜欢
      • 1970-01-01
      • 2015-02-07
      • 2016-03-27
      • 2019-12-12
      • 1970-01-01
      • 2021-01-09
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多