一、前面的话
最近开发的过程中,发现公司的部分依赖采用了私有依赖,直接采用 npm i
的方式没办法安装,因此记录下解决的过程
二、先删后增法
目前npm镜像配置已经全局配置为淘宝镜像,所以,对于除了私有依赖(后面以lowcode.fsd.frontend代表私有依赖)之外的其他依赖,我们可以直接使用npm i
进行快速安装,因此,我将lowcode.fsd.frontend
先从package.json
文件中删除,执行一次 npm i
,待依赖安装完毕后,单独安装lowcode.fsd.frontend
shell
npm i -S lowcode.fsd.frontend --registry https://xxxx.xxx.com
依赖是成功装上了,package.json
dependences中也有了新加了这一项
json
{
"dependencies": {
"lowcode.fsd.frontend": "^1.0.180"
}
}
但是问题来了,后面有人重新拉取依赖后,也得这样安装,不够方便,有没有办法直接通过 npm i
一次性安装成功呢?
三、配置镜像法
通过查阅 npm文档 可知,当依赖通过scope方式注册时,可以为单个依赖单独配置镜像设置(辅助阅读文档npm指定依赖包私有源问题记录 - 掘金 (juejin.cn)),
我以@vue/cli
和@ant-design/colors
进行了测试,测试过程中,.npmrc
文件内容如下
shell
#设置项目所用的npm镜像
registry=http://192.168.x.xxx:xxxx/
#设置@vue范围包镜像,对诸如@vue/cli,@vue/compiler-sfc等生效
@vue:registry=http://mirrors.cloud.tencent.com/npm/ #腾讯云镜像
#设置@ant-design范围包镜像
@ant-design:registry=http://registry.npmmirror.com #淘宝镜像
package.json
内容如下:
json
{
"dependencies": {
"lowcode.fsd.frontend": "^1.0.180",
"@ant-design/colors": "^7.0.2",
"vant": "2.13.1",
"mockjs": "1.1.0",
"moment": "2.29.1"
},
"devDependencies": {
"@vue/compiler-sfc": "^3.4.21"
}
}
执行npm i
之后,在生成的package-lock.json
中,可以发现镜像生效
但是问题来了,我这里的私有包也没有定义范围啊,该方法行不通!!! [苦涩.jpg]
三、直接指定法
在npm文档关于dependencies的描述中,对于依赖的写法可以设置为 版本号、git、本地路径、tarball等形式,如图
从给出的示例可以看到,当采用http的方式代替依赖版本范围时(示例中 asd 依赖),需要给出依赖tar.gz的地址,这个地址怎么获取呢,这里给出两个方案
- 方案一: 采用npm命令的形式
shell
# npm info 包名,我的包是lowcode.fsd.frontend
npm info lowcode.fsd.frontend
命令结果返回如上图,在图中可以看到dist下的tarball
字段,该字段后面的路径对应的就是依赖包地址。当然,因为是私有包,可能会出现下面的报错
遇到这种错误时,可以在项目根目录下临时新建.npmrc
文件,在里面定义项目npm采用的镜像地址,如下
shell
#设置项目所用的npm镜像
registry=http://192.168.x.xxx:xxxx/
然后再执行info或者view命令就可以了
- 方案二:从
package-lock.json
中获取。如果采用先删后增法安装过该依赖,可以搜索依赖名,依赖下resolved
字段对应的路径即为tarball
路径,示例如图
改写后的package.json
如下
json
"dependencies": {
"lowcode.fsd.frontend": "http://192.168.xx.xxxx:xxxx/lowcode.fsd.frontend/-/lowcode.fsd.frontend-1.0.180.tgz"
},
当然,这个方法虽然解决了直接通过npm i
安装依赖报错的问题,但是,却没办法自动更新版本了,需要手动更新版本号
ps:因为项目采用svn的管理方式,因此,验证时采用http的方式改写version
四、脚本注入
在npm i
执行的过程中,会执行 package.json
的scripts
中定义的preinstall
构子,因此,我们可以通过该钩子实现自动更新tarball
地址,脚本代码示例如下,这里以vant作为演示示例
js
// script.js
const fs = require('fs');
const path = require('path');
const http = require('https');
const pkgPath = path.join(__dirname, 'package.json');
const moduleName = 'vant'
const tarballUrl = 'https://registry.npmmirror.com/' + moduleName;
// 获取package.json内容
let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
const oldUrl = pkg.dependencies[moduleName];
// oldUrl = https://registry.npmmirror.com/vant/-/vant-1.6.28.tgz 或者^4.1.8
// 更新名为 moduleName 的tarball依赖项
async function updateTarballDependency() {
// 这里是逻辑去获取新版本tarball的URL,比如通过API请求
const latestVersion = await getLatestVersion();
pkg.dependencies[moduleName] = getNewUrl(latestVersion);
// 更新package.json,并格式化
const updatedPkgJson = JSON.stringify(pkg, null, 2);
fs.writeFileSync(pkgPath, updatedPkgJson);
}
// 获取latest对应的版本号
function getLatestVersion() {
return new Promise((resolve, reject) => {
const req = http.request(tarballUrl, (res) => {
res.setEncoding('utf-8');
const list = [];
res.on('data', (chunk) => {
list.push(chunk);
});
res.on('end', () => {
try {
const json = JSON.parse(list.join(''));
resolve(json['dist-tags'].latest);
} catch (error) {
reject(error);
}
});
});
req.end();
});
}
// 返回的是对应版本号的tarball地址
function getNewUrl(version) {
if (oldUrl.startsWith('http')) {
// tarball写法
let urlStrs = oldUrl.split('-');
let lastItem = urlStrs.pop();
urlStrs.push(version + lastItem.substring(lastItem.length - 4));
return urlStrs.join('-');
} else {
return tarballUrl + `/-/${moduleName}-${version}.tgz`
}
}
updateTarballDependency()
.then(() => console.log('Successfully updated tarball dependency'))
.catch((err) => console.error('Error updating dependency:', err));
package.json
中的修改如下,新增一个脚本
json
"scripts": {
"preinstall": "node ./scripts.js"
},
最后,依赖下载完之后,查看package-lock.json
,可以看到,vant的版本更新为了latest对应的版本
这里附上之前的package.json
json
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"preinstall": "node ./scripts.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"vant": "https://registry.npmmirror.com/vant/-/vant-1.6.28.tgz"
}
}
五、写在最后
文中使用的node版本为14.16.0,对应的npm版本为6.14.11,不同的npm版本可能结果不一致,如有错误,欢迎大家指出。