仿nrm功能的npm镜像源切换工具

287 阅读4分钟

这是一个用于切换 NPM 镜像源的脚本,可以旨在无需手动配置的情况下切换到合适的镜像源。这个脚本完全使用 Node.js 和主流的包,如 commanderinquirer 来实现交互功能。

脚本代码

#!/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库,这样子很麻烦),这边建议还是抽离出来单独进行维护和版本控制

功能说明

该脚本提供了下列功能:

  1. ls:查看当前使用的镜像源。
  2. all:查看所有可用的镜像源。
  3. use:切换到指定的镜像源。
  4. ping:测试所有镜像源的响应速度。

使用步骤(暂时只是将这个脚本发到了我的npm私库)

  1. 全局安装npm install lwpm -g --registry=http://47.112.183.237:4873/
  2. 在命令行中运行lwpm即可进行相关的操作

与 nrm 的对比

nrm 是一个非常流行的 NPM 镜像源管理工具,它提供了类似的功能,如查看、添加、删除和切换镜像源。

相似之处

  • 功能:两者都可以列出所有镜像源、查看当前镜像源以及切换镜像源。
  • 使用方式:都是通过命令行工具来进行操作。

区别

  • 定制性:由于本脚本是自定义的,用户可以根据需要修改代码来添加或更改功能,而 nrm 是一个封闭的工具,定制性较低。
  • 依赖管理:本脚本依赖于 commanderinquirer,需要自行安装依赖,而 nrm 是一个独立的工具,安装后即可使用。
  • 镜像源配置:本脚本可以从远程仓库动态获取最新的镜像源配置,而 nrm 使用本地配置。

commander 介绍

commander 是一个用于构建 Node.js 命令行界面的流行库。它提供了易于使用的 API 来定义命令和选项,并自动生成帮助信息。

特点

  • 简单易用的 API。
  • 支持嵌套子命令。
  • 自动生成帮助和版本信息。
  • 支持参数验证和默认值。

image.png

inquirer 介绍

inquirer 是一个用于构建交互式命令行用户界面的库。它提供了多种类型的提示,例如单选、多选、输入等,用户可以通过这些提示与程序进行交互。

特点

  • 提供多种提示类型,如输入、确认、列表等。
  • 支持异步操作。
  • 可扩展的提示类型。

image.png

📢 关于作者
嗨!我是头发秃头小宝贝,一名热爱技术分享的开发者,专注于Vue / 前端工程化 / 实战技巧等领域。
如果这篇文章对你有所帮助,别忘了 点赞 👍收藏 ⭐ 和 关注 👏,你的支持是我持续创作的最大动力!