这是一个用于切换 NPM 镜像源的脚本,可以旨在无需手动配置的情况下切换到合适的镜像源。这个脚本完全使用 Node.js 和主流的包,如 commander 和 inquirer 来实现交互功能。
脚本代码
#!/usr/bin/env node
import { program } from "commander";
import inquirer from "inquirer";
import { execSync } from "child_process";
import chalk from "chalk";
import fs from "fs";
import { fileURLToPath } from "url";
import path from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const registries_local = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "./registries.json"), "utf-8")
);
const PKG = JSON.parse(
fs.readFileSync(path.resolve(__dirname, "./package.json"), "utf-8")
);
program.version(PKG.version);
// 这份地方是你自己的registries仓库地址配置文件
const REGISTRY_URL =
"https://gitee.com/your_address/json-file/raw/master/registries.json";
// 从 Git 仓库获取最新的镜像源配置
async function fetchRegistriesFromGit() {
try {
const response = await fetch(REGISTRY_URL);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error(chalk.yellow("无法从远程获取镜像源配置,将使用本地配置"));
return registries_local;
}
}
const registries = await fetchRegistriesFromGit();
const getOrigin = async () => {
return await execSync("npm get registry", { encoding: "utf-8" });
};
// 查看当前镜像源
program
.command("ls")
.description("查看当前使用的镜像源")
.action(async () => {
const currentRegistry = await getOrigin();
console.log(chalk.green(`当前使用的镜像源: ${currentRegistry.trim()}`));
});
// 查看所有可用的镜像源
program
.command("all")
.description("查看所有可用的镜像源")
.action(() => {
Object.entries(registries).forEach(([name, url]) => {
console.log(chalk.blue(`${name}: ${url}`));
});
});
// 切换镜像源
program
.command("use")
.description("切换镜像源")
.action(async () => {
try {
const choices = Object.entries(registries).map(([name, url]) => ({
name: `${name} (${url})`,
value: url,
}));
const { registry } = await inquirer.prompt([
{
type: "list",
name: "registry",
message: "请选择要使用的镜像源:",
choices,
},
]);
execSync(`npm config set registry ${registry}`);
console.log(chalk.green(`成功切换到镜像源: ${registry}`));
} catch (error) {
// 用户按下 Ctrl+C 时,inquirer 会抛出异常
if (error.isTtyError) {
console.log(chalk.yellow("\n已取消切换操作"));
} else {
console.error(chalk.red("切换镜像源失败:", error.message));
}
// 确保程序正常退出
process.exit(0);
}
});
// 测试镜像源速度
program
.command("ping")
.description("测试所有镜像源的响应速度")
.action(async () => {
console.log(chalk.blue("正在测试镜像源速度..."));
for (const [name, url] of Object.entries(registries)) {
try {
const startTime = Date.now();
await fetch(url);
const endTime = Date.now();
console.log(chalk.green(`${name}: ${endTime - startTime}ms`));
} catch (error) {
console.log(chalk.red(`${name}: 无法连接`));
}
}
});
program.parse(process.argv);
registries.json配置文件
{
"npm": "https://registry.npmjs.org/",
"taobao": "https://registry.npmmirror.com/",
"tencent": "https://mirrors.cloud.tencent.com/npm/",
"cnpm": "https://r.cnpmjs.org/",
"yarn": "https://registry.yarnpkg.com/",
...
}
我们将默认镜像源抽离出来独立维护和版本控制,主项目可以不需要维护默认配置文件,当然如果你没有抽离出你的镜像源配置文件,默认也可以继续使用本地的registries.json文件(只是这样子后面push到npm库后每次更新registries.json文件你都需要去改一次版本号并且重新push到npm库,这样子很麻烦),这边建议还是抽离出来单独进行维护和版本控制
功能说明
该脚本提供了下列功能:
- ls:查看当前使用的镜像源。
- all:查看所有可用的镜像源。
- use:切换到指定的镜像源。
- ping:测试所有镜像源的响应速度。
使用步骤(暂时只是将这个脚本发到了我的npm私库)
- 全局安装
npm install lwpm -g --registry=http://47.112.183.237:4873/ - 在命令行中运行
lwpm即可进行相关的操作
与 nrm 的对比
nrm 是一个非常流行的 NPM 镜像源管理工具,它提供了类似的功能,如查看、添加、删除和切换镜像源。
相似之处
- 功能:两者都可以列出所有镜像源、查看当前镜像源以及切换镜像源。
- 使用方式:都是通过命令行工具来进行操作。
区别
- 定制性:由于本脚本是自定义的,用户可以根据需要修改代码来添加或更改功能,而 nrm 是一个封闭的工具,定制性较低。
- 依赖管理:本脚本依赖于
commander和inquirer,需要自行安装依赖,而 nrm 是一个独立的工具,安装后即可使用。 - 镜像源配置:本脚本可以从远程仓库动态获取最新的镜像源配置,而 nrm 使用本地配置。
commander 介绍
commander 是一个用于构建 Node.js 命令行界面的流行库。它提供了易于使用的 API 来定义命令和选项,并自动生成帮助信息。
特点
- 简单易用的 API。
- 支持嵌套子命令。
- 自动生成帮助和版本信息。
- 支持参数验证和默认值。
inquirer 介绍
inquirer 是一个用于构建交互式命令行用户界面的库。它提供了多种类型的提示,例如单选、多选、输入等,用户可以通过这些提示与程序进行交互。
特点
- 提供多种提示类型,如输入、确认、列表等。
- 支持异步操作。
- 可扩展的提示类型。
📢 关于作者
嗨!我是头发秃头小宝贝,一名热爱技术分享的开发者,专注于Vue / 前端工程化 / 实战技巧等领域。
如果这篇文章对你有所帮助,别忘了 点赞 👍、收藏 ⭐ 和 关注 👏,你的支持是我持续创作的最大动力!