使用 npm 安装或更新所需的包,就像 rubygems 的 bundler
Posted
技术标签:
【中文标题】使用 npm 安装或更新所需的包,就像 rubygems 的 bundler【英文标题】:Using npm to install or update required packages just like bundler for rubygems 【发布时间】:2011-06-19 19:21:01 【问题描述】:我喜欢Bundler,它非常擅长依赖管理。我爱npm,安装节点包很容易!我有一个 nodejs 应用程序,并且希望能够能够指定我的应用程序依赖项并轻松安装/更新它们,无论我在哪里部署我的应用程序。这不是我要发布的库,而是一个成熟的网络应用程序。
我知道npm bundle
命令,但这似乎只是简单地覆盖了安装包的目录。
我习惯于以这种方式使用 bundler:
# Gemfile
gem "rails", "3.0.3"
仅当主机上不存在 rails v3.0.3 和任何其他必需的 gem 时才安装它
> bundle install
如何使用 npm 实现类似的功能?
【问题讨论】:
我的回答不是你想知道的吗? 【参考方案1】:从 npm 1.0 开始(如果您按照 README 文件中的步骤操作,现在默认情况下会得到该版本),“捆绑包”不再是一个隔离的东西——它只是“它是如何工作的”。
所以:
-
将
package.json
文件放在项目的根目录中
在该文件中列出您的部门
"name" : "my-project"
, "version" : "1.0.0"
, "dependencies" : "express" : "1.0.0"
npm install
因为你是在没有参数的情况下调用它,而不是在全局模式下,所以它只会在本地安装你所有的 dep。
require("express")
开心就好。
【讨论】:
在生产环境中,我强烈建议将本地your_app/node_modules
目录更改为应用目录之外的符号链接。您不希望每次部署时都必须下载、构建和安装每个依赖项。
好的。如果我忘记更新我的 package.json 怎么办?有什么方法可以强制 NPM 不查找 package.json 而是查找我在代码中使用的包?
这不太正确。 NPM 将在./node_modules/my-project/node_modules
中安装上述my-project
的所有依赖项。我不确定是否有一种方便的方法可以让它在./node_modules
Anyone 中安装所有依赖项?
@DanielBeardsley 我不认为 npm 是这样工作的。如果您看到这种行为,并且可以重现它,请在 npm github 页面上发布问题。
同意@DanielBeardsley。即使使用 npm 1.1.70,我也会遭受这种行为的困扰【参考方案2】:
在我看来,最简单的解决方案是使用package.json
文件,并将private
标志(上个月才添加到npm)设置为true
。这样,您可以运行 npm install
或 npm bundle
来获取项目的依赖项,但可以防止任何人意外发布您的非公开项目。
这是一个例子package.json
:
"name": "yourProject"
,"version": "1.0.0"
,"dependencies": "express" : ">=2.1.0"
,"private": true
运行npm install
将在本地系统上安装express
(如果它尚不存在);由于"private": true
,运行npm publish
会出错。
您和您的团队可以在内部使用版本标签来跟踪依赖项随时间的变化——每次您更改依赖项时,都会更新版本。要查看您安装的版本,请使用npm ls installed
。
【讨论】:
我认为你不应该引用true
,它只是因为字符串是真实值(即!!"false" === true
)才起作用。【参考方案3】:
从 Npm 版本 1.1.2 开始,有一个新命令 npm shrinkwrap
创建一个 npm-shrinkwrapped.json
文件,类似于 Gemfile.lock
。制作一个很重要,以防止软件腐烂(请参阅Bundler's rationale)。尤其是 Nodejs 拥有如此快速发展的社区。p>
虽然bundle install
会自动创建Gemfile.lock
,但npm install
不会创建npm-shrinkwrapped.json
(但会在它存在时使用它)。因此,您需要记住使用npm shrinkwrap
。
在http://blog.nodejs.org/2012/02/27/managing-node-js-dependencies-with-shrinkwrap/阅读完整指南
【讨论】:
【参考方案4】:编辑:这仅适用于 npm 版本
很难弄清楚这一点,但 NPM 使这成为可能。
你需要三个组件
-
存储库中的子目录(即
deps/
)
上述目录中列出依赖项的package.json
文件
上述目录中的index.js
文件需要您的依赖项
示例
想象express 是你唯一的依赖
deps/package.json
注意:每次修改依赖时增加版本号
"name": "myapp_dependencies",
"version": "0.0.1",
"engines":
"node": "0.4.1"
,
"dependencies":
"express": "2.0.0beta2"
deps/index.js
export.modules =
express: require('express')
//add more
现在您应该可以使用 npm 安装依赖项了。您甚至可以将此作为部署过程的一部分
cd deps
npm install
然后在您的应用代码中,您可以像这样访问特定版本的 express:
var express = require('myapp_dependencies').express;
【讨论】:
谢谢,这是迄今为止我见过的最好的方法。但是,deps/index.js 中的require('express')
不会只是导入最新的 express 版本,而不一定是我们安装的那个?我是 nodeJS 菜鸟,所以请多多包涵。
不,这就是npm install
的魔力,它将已安装包目录中的符号链接添加到依赖包的正确版本。当需要依赖包时,require('express')
首先检查本地目录并找到指向正确版本 express 的符号链接。【参考方案5】:
您应该阅读 Isaacs(作者 npm)博客中的这两篇文章。我觉得他们真的很好,我相信会告诉你如何实现你的目标:
-
http://blog.izs.me/post/1675072029/10-cool-things-you-probably-didnt-realize-npm-could-do
http://foohack.com/2010/08/intro-to-npm/
我相信链接 #1(点 #11)解释了这一点:
11:将所有依赖项捆绑到包本身中
当您使用 npm bundle 命令,npm 会将所有 你的依赖项 包中的 node_modules 文件夹。 但这并不止于此。
如果你想依赖某些东西 那不在注册表上,你可以做 那。只需这样做:
npm 捆绑安装 http://github.com/whoever/whatever/tarball/master 这将安装该内容 tarball 到包中,然后你 可以将其列为依赖项,并且 当你的时候不会尝试安装它 安装包。
如果你有你的 自己的东西的叉子,并且会 不想改名字。
事实上,你几乎可以运行任何 npm 捆绑包中的命令。看看是什么 在里面,你可以做 npm bundle ls。到 删除一些东西,做 npm bundle rm 事物。而且,当然,您可以安装 多个版本并激活一个 你想要的。
【讨论】:
这很有用,虽然它不是我想要的。也许我需要补充说明。我正在寻找一种方法来自动安装或更新(在目标机器上)我的应用程序在部署时所依赖的 NPM 包。看起来npm bundle
用于将所有依赖项收集到默认目录以外的特定目录中。我可能会想出我自己的解决方案,其性能类似于bundle install
(bundler
for ruby)
请注意,因为npm
1.0+ 版,npm bundle
已被删除。相反,只需使用不带包名的 npm install
命令,它将读取 package.json 并下拉所需的包。【参考方案6】:
也使用npm
发布您的应用,并在您的 package.json 文件中列出其依赖项。
当有人使用npm
安装您的包时,npm
将负责解决其依赖关系。
包规格:http://wiki.commonjs.org/wiki/Packages/1.0
【讨论】:
是的,但这是一个非开源网络应用程序。如果您有不涉及发布应用的想法,请编辑您的答案或创建另一个答案。 然后发布一个像“myapp-dependencies”这样的包,您的用户可以在安装您的应用程序之前使用npm
进行安装。我认为 node.js 没有其他 gem
等价物。以上是关于使用 npm 安装或更新所需的包,就像 rubygems 的 bundler的主要内容,如果未能解决你的问题,请参考以下文章
NPM - 如何在不更新或添加 package.json 中描述的包的情况下安装新包