npm中的可选依赖项?


23

对此有类似的问题,但不完全相同。

我想让我的应用程序用户以其想要使用它的方式安装所需的任何依赖项。因此,例如,如果他们要保留到MongoDB,则仅安装与Mongo相关的库,但是如果他们要保留到Redis,则仅安装与Redis相关的库。我不想让他们下载并安装他们不会使用的库。

我知道我可以使用进行开发devDependencies,但这远不止于此。就像以上问题的答案所说,这与Python setuptools extras_require和Clojure的leiningen配置文件更紧密相关。在npm中有类似的内容吗?我真的觉得devDependencies应该是dev一种更加广泛的指定依赖项的方式。


只是一个想法,但是您可以使用多个软件包。MyPackage-Core MyPackage-Db-Mongo MyPackage-Db-Redis等等...人们采用了很多方式来扩展Bower模块,这些模块旨在扩展angularjs
2014年

@Mike:谢谢,我会考虑的。我仍然认为这是package.json其他软件包管理器已解决的局限性。
2014年

1
这是一个很好的问题,但我认为这是题外话,因为它与使用某种工具有关。仅当这些问题涵盖了该工具如何集成到某些开发过程中时,这些问题才是主题。毕竟,该站点是有关软件工程的。有关详情,请参见我们的帮助中心。请阅读:我的工具问题去哪儿了?开发工具(例如NPM)的使用将成为Stack Overflow的主题。
amon

Answers:


9

相互依赖模块可能是你正在寻找的东西,或任何有类似的功能来:

  • 声明可选依赖于package.json不会自动安装npm install,比方说optionalPeerDependencies
  • 一个自定义require样式的函数,该函数知道optionalPeerDependencies并执行正确的操作,包括在未找到满足要求的模块类的任何内容时抛出/警告(例如redis,未安装mongo,,,或mysql等)。
  • 记录期望该模块的使用者安装至少一个可选对等模块

一种变化是,如果模块的核心功能在没有任何可选依赖项(例如,插件模式)的情况下工作,并且在没有发现任何满足对等依赖项的情况下没有错误/警告。

另一个变化是干什么的上方,而占生产与发展依赖列表,即用于模拟dependenciesdevDependencies

也许与按需require结合在一起,使得懒惰地需要可选模块,例如:

exports = {
    Core : require('./core'),
    get redis(){ return require('./redis'); },
    get mongo(){ return require('./mongo'); }
}

我已经有一段时间不需要了,但是我认为它可以解决我遇到的问题。谢谢!
2015年

2
是的,我认为您可能已经想出或继续前进了几个月。我在寻找答案的同时发现了您的问题,所以这主要是为了后代。我不止一次地进行搜索,却发现自己几年前写的答案。因此,请考虑这种开明的自我利益。另外,更新了答案以大致描述codependency模块在NPM蒸发并且由于没有摘录的链接是错误的SO格式时模块提供的内容。
toolbear 2015年

9

如果您想要简单的可选依赖项(例如插件),例如,如果您安装foo,它将以彩色运行,但如果未安装,则没有任何问题,并以灰色显示,则可以在package.json中使用optionalDependecies

{
  "name": "watchit",
  "version": "1.2.3",
  "optionalDependencies": {
    "foo": "^2.0.0"
  }
}

并在代码中:

try {
  var foo = require('foo')
  var fooVersion = require('foo/package.json').version
} catch (er) {
  foo = null
}
if ( notGoodFooVersion(fooVersion) ) {
  foo = null
}

// .. then later in your program ..

if (foo) {
  foo.doFooThings()
}

package.json文档中提取。


1

我要做的是在package.json中的内部配置安装脚本scripts,如下所示:

"install": "node ./my-tools/my-install.js",

它将在npm install完成后立即运行。我主要将其用于自动生成.env具有默认值的文件。

my-install.js脚本可以运行不同的命令,创建文件,询问用户输入,因此您可以在此处说“ Want Redis还是Mongo?”:

const exec = require('child_process').exec;
const readline = require('readline');

// Insert "Ask question script" here
// using readline core module

if ( option == 'mongo' )
  exec('npm install mongoose');

if ( option == 'redis' )
  exec('npm install redis');

这是一个非常快速的答案,请检出readline以正确读取用户输入,并使用子进程运行命令并处理输出等。

还要注意,安装脚本可以是您想要的任何内容(python,bash等)


2
要求用户输入将破坏自动构建。npm install在安装脚本中再次运行可能还会触发意外行为。我不推荐这种解决方案。
Lambda Fairy,

1

npm确实不是为此而设计的,因为依赖管理中最难的部分之一就是确保快速,可复制的构建既简单又相对故障安全。但是我相信有一个用例,对我来说肯定有。因此,我写了一个程序包来完全满足您的要求。

我的软件包是install-subset,可以通过以下方式全局安装npm install -g install-subset

https://www.npmjs.com/package/install-subset

首先,在package.json中为命名安装子集构建白名单和黑名单,如下所示:

"subsets": {
    "build": {
        "whitelist": [
            "babel-cli",
            "dotenv"
        ]
    },
    "test": {
        "blacklist": [
            "eslint",
            "lint-rules",
            "prettier"
        ]
    }
}

然后用,例如 install-subset test

这将临时重写您的package.json,以不安装那些列入黑名单的软件包,然后将其还原,这取决于软件包可以节省大量时间和带宽。

也可与纱线一起使用,是开源的,欢迎发布/ PR。

在许多情况下,我在ci服务器上使用它来缩短构建时间,而在最新的React Native项目中,典型的新开发人员安装时间从72秒减少到了20秒左右。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.