如何禁止包贡献者使用Yarn安装依赖且不影响外部项目引入?
限制包贡献者使用Yarn,允许外部项目通过Yarn引入该包
我正在维护一个曾使用Yarn进行依赖管理的包,现计划转回npm。希望贡献者尝试用Yarn安装依赖时能看到错误提示(代码审查阶段也会标记相关问题,但提前告知可减少不必要的困扰)。但必须确保其他项目仍可通过Yarn引入该包,此限制仅适用于本包的贡献者。
已尝试方案
- 使用
package.json中的engines字段无法满足需求,会导致包无法被其他项目作为依赖安装。 - 在preinstall脚本中检查npm execpath变量也不可行,因为该脚本在外部项目安装包时也会执行,破坏其安装流程。
需求
需要在preinstall脚本中区分本地贡献者和包作为依赖的安装场景,实现如下代码中的isLocalDev函数:
// 该脚本在npm "preinstall"钩子阶段运行 const isYarn = () => process.env.npm_execpath.includes('yarn'); const isLocalDev = () => /* ??? */; if (isYarn() && isLocalDev()) { console.error('本项目依赖管理禁止使用Yarn,请使用npm!'); process.exit(1); }
实现方案
以下几种方法可实现isLocalDev函数,精准区分两种场景:
方法1:检查.git目录(最可靠)
贡献者克隆仓库后,本地项目根目录会存在.git文件夹;而包作为依赖被安装到外部项目的node_modules时,不会包含该目录。代码实现:
const fs = require('fs'); const path = require('path'); const isLocalDev = () => { return fs.existsSync(path.join(process.cwd(), '.git')); };
方法2:验证包根目录
通过读取当前目录的package.json,验证其包名是否与你的包一致,判断是否处于本地开发场景:
const fs = require('fs'); const path = require('path'); const isLocalDev = () => { try { const pkgPath = path.join(process.cwd(), 'package.json'); const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); // 替换为你的包实际名称 return pkg.name === 'your-package-name'; } catch (err) { return false; } };
方法3:利用npm环境变量
借助npm的npm_config_local_prefix环境变量,判断当前工作目录是否为包的根目录:
const path = require('path'); const isLocalDev = () => { // 本地开发时,执行install命令的目录就是包根目录,与当前工作目录一致 return process.env.npm_config_local_prefix === process.cwd(); };
内容的提问来源于stack exchange,提问作者Duncan Thacker
相关产品推荐
相关产品推荐

