从0开到1搭建
1.背景
- node版本下载极其耗时,主要是国内没有好用的镜像。
- 下载速度堪称龟爬,如果没有好的vpn的情况下,基本得好久
- 自己购买的服务器,都是自带vpn和网络加速的,,于是便萌生了在自己的服务器上搭建node版本管理的服务器
-于是我们下载变成,利用服务器高带宽下载,然后我们在从服务器下载资源
node版本高速下载镜像
2.前期准备
- node历史版本获取(数据扒取)
- node历史版本的大小(计算下载进度)
- 服务器文件大小获取(用来获取当前下载进度)
- ndoe后端服务器的搭建
- web前端交互页面构建
3.版本和大小数据获取
1.版本获取
https://nodejs.org/zh-cn/download/releases/
Array.from(document.getElementsByTagName('tr')).forEach(ele=>{
let el = ele.getElementsByTagName('td')[0]
console.log(el?.innerText)
})
2.版本大小获取
循环获取每个版本的详细信息
let indd = 0;
let vers = {}
let pro = () => new Promise(res => {
request(`https://nodejs.org/download/release/v${nodeVersion[indd]}/`, (error, response, body) => {
let data = formatBody(body);
vers[nodeVersion[indd]] = data;
indd = indd + 1;
if (indd > nodeVersion?.length - 1) {
fs.writeFile("output.json", JSON.stringify(vers), function (err) {
if (err) {
return console.log(err);
}
});
return
}
pro()
})
})
pro()
获取详细的版本大小
function formatBody(a) {
try {
let ccc = [];
let dd = a.replace(/ /g, '').match(/<a[^>]*>[^<]*<\/a>/g)
for (let i = 0; i < dd.length; i++) {
ccc.push(dd[i].match(/(?<=\")(.+?)(?=\")/g, '')[0])
}
let size = a.replace(/ /g, '').replace(/<a[^>]*>[^<]*<\/a>/g, '').match(/<pre[^>]*>[^<]*<\/pre>/g, '')[0].replace('<pre>', '').replace('</pre>', '').split('\r\n');
ccc = ccc.filter(item => {
return !['../', 'docs/', 'win-x64/', 'win-x86/'].includes(item)
})
size = size.reduce((prev, next, index) => {
let ind = next.indexOf(':')
if (next !== '' && next.slice(ind + 3) !== '-') {
prev.push(next.slice(ind + 3))
}
return prev
}, [])
let obj = {}
size.forEach((item, index) => {
obj[ccc[index]] = size[index]
})
return obj
} catch (error) {
return {}
}
}
3.node服务端
1.request模块下载服务api
- request:提供访问url服务,可下载资源
- request.on(‘close’,()=>{}):提供访完成时的回调
- fs.existsSync:检验文件存在不存在
- fs.createWriteStream:创建文件可写流
- 如果检验文件存在,则不触发下载,直接将url返回
/**
*
* @param {*} url 网络文件url地址
* @param {*} fileName 文件名
* @param {*} dir 下载到的目录
*/
function getfileByUrl({ url, fileName, dir }) {
return new Promise((res, rej) => {
try {
console.log(`/www/file/node/${fileName}`, '2222')
var data = fs.existsSync(`/www/file/node/${fileName}`)
if (data) {
res({ code: 0, data: `http://114.215.183.5:88/node/${fileName}` })
return
}
let stream = fs.createWriteStream(path.join(dir, fileName));
request(url).pipe(stream).on("close", function (err) {
if (err) {
rej({ code: 1, msg: "下载失败" })
} else {
res({ code: 0, data: `http://114.215.183.5:88/node/${fileName}` })
}
console.log("文件" + fileName + "下载完毕");
});
} catch (error) {
console('无缓存,下载')
}
})
};
2.读取文件size的api
fs.readFileSyn读取文件,并将大小返回
/**
*
* @param {*} fileName 文件名
*/
function getfileProgress({ fileName }) {
const path_ = `/www/file/node//${fileName}`
return new Promise((res, rej) => {
try {
var data = fs.readFileSync(path_);
res({code:0,data:data.length})
} catch (error) {
res({code:1,data:'读取失败'})
}
})
};
4.web前端
- 技术栈vue+elementt
- 前端api简简单单,利用接口优化即可
- 下载时需要轮训当前文件下载进度,利用递归即可
getFileSize() {
setTimeout(() => {
http.get(`user/getfileProgress?version=${this.version}&type=${this.type}`).then(res => {
if (res.code === 0 && (res.data || res.data === 0)) {
this.nowSize = res.data;
if (Number(res.data) < Number(this.getVersion())) {
this.getFileSize()
} else {
this.nowSize = 0
}
}
}).catch((err) => {
this.$message.error('请求异常' + err);
})
}, 50);
},
结语
- 女朋友总是抱怨,node下载太慢(其实是他没vpn)于是自己搞了个小工具
- 技术的真实意义,在于帮助解决实实在在的生活需求。
- 每天进步一点点,不积跬步无以至千里,不积小流无以成江海
- node版本高速镜像