You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于客户端OS分发不同二进制文件至npm包并通过npx调用?

解决方案:基于操作系统分发npm包二进制文件

一、二进制文件放置位置(支持npx调用)

要让二进制文件能被npx直接调用,需满足两个核心要求:

  • 将下载后的二进制文件存放到npm包的bin目录中
  • 在package.json的bin字段里配置命令与二进制文件的映射关系

示例package.json配置:

{
  "bin": {
    "my-tool": "./bin/my-tool"
  },
  "scripts": {
    "postinstall": "node ./scripts/download-binary.js"
  }
}

注:Windows系统下npm会自动识别.exe后缀,bin字段无需区分系统后缀。

二、跳过重复下载(二进制版本无变化时)

通过记录已下载二进制的版本号,与目标版本对比实现跳过逻辑:

  1. 从你的.version文件的label字段中读取当前要下载的二进制版本
  2. 将该版本号保存到bin/.binary-version标记文件中
  3. 每次执行postinstall时,先读取标记文件的版本:
    • 版本一致则直接跳过下载
    • 版本不一致或标记文件不存在时,执行下载流程

三、修改后的下载脚本示例

import { createWriteStream, readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
import { get } from 'https';
import { platform } from 'os';
import { exit } from 'process';

interface Asset {
    url: string;
    id: number;
    name: 'Windows.exe' | 'Darwin' | 'Linux';
    label: string;
    content_type: string;
    state: 'uploaded';
    size: number;
    download_count: number;
    created_at: string;
    updated_at: string;
    browser_download_url: string;
}

// 确保bin目录存在,避免下载时出错
const binDir = './bin';
if (!existsSync(binDir)) {
    mkdirSync(binDir);
}

const versionFile = './.version';
const binaryVersionMarker = `${binDir}/.binary-version`;

// 解析版本映射表
const assets = JSON.parse(readFileSync(versionFile).toString()) as Asset[];
const versionFromNames = Object.fromEntries(assets.map(dist => [dist.name, dist]));

// 匹配当前系统对应的二进制资源
let targetAsset: Asset | null = null;
let binaryName: string;

switch (platform()) {
    case 'win32': {
        binaryName = 'my-tool.exe';
        targetAsset = versionFromNames['Windows.exe'];
        break;
    }
    case 'darwin': {
        binaryName = 'my-tool';
        targetAsset = versionFromNames['Darwin'];
        break;
    }
    case 'linux': {
        binaryName = 'my-tool';
        targetAsset = versionFromNames['Linux'];
        break;
    }
    default: {
        console.warn(`暂不支持该操作系统: ${platform()}`);
        exit(0);
    }
}

if (!targetAsset) {
    console.error(`未找到当前系统对应的二进制文件`);
    exit(1);
}

// 检查是否需要更新
const currentVersion = existsSync(binaryVersionMarker) ? readFileSync(binaryVersionMarker, 'utf8').trim() : '';
if (currentVersion === targetAsset.label) {
    console.log(`二进制文件已是最新版本 ${targetAsset.label},跳过下载`);
    exit(0);
}

// 下载二进制文件到bin目录
const outputPath = `${binDir}/${binaryName}`;
const file = createWriteStream(outputPath);

console.log(`开始下载版本 ${targetAsset.label} 的二进制文件...`);
get(targetAsset.browser_download_url, function (resp) {
    resp.pipe(file);

    file.on('finish', () => {
        file.close();
        // 给非Windows系统的二进制添加可执行权限
        if (platform() !== 'win32') {
            import('fs/promises').then(fs => fs.chmod(outputPath, 0o755));
        }
        // 保存版本标记
        writeFileSync(binaryVersionMarker, targetAsset.label);
        console.log(`二进制文件下载完成,已保存到 ${outputPath}`);
    });
}).on('error', (err) => {
    console.error(`下载失败: ${err.message}`);
    exit(1);
});

四、额外注意事项

  • 权限处理:非Windows系统下,下载后的二进制文件需要添加可执行权限,脚本中已通过chmod实现
  • npm缓存兼容:即使使用npm ci或缓存安装,postinstall仍会执行,但版本检查逻辑会自动跳过重复下载
  • Linux适配:脚本补充了Linux系统的处理逻辑,可根据你实际的二进制URL调整

内容的提问来源于stack exchange,提问作者Rahul A Ranger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:45:32