@cosmology/protobufjs

中文文档
7.3.2发布于 2024/06/13BSD-3-ClauseTypeScriptCommonJS近 30 天下载 4.3万

JavaScript( & TypeScript) 协议缓冲器 .

中文使用文档
文档目录19 节
  1. 目录
  2. 安装
  3. 节点.js
  4. 浏览器
  5. 使用量
  6. 有效消息
  7. 工具集
  8. 实例
  9. 使用. proto 文件
  10. 使用 JSON 描述符
  11. 仅使用反射
  12. 使用自定义类
  13. 使用服务
  14. 使用类型脚本
  15. 其他文件
  16. 业绩
  17. 兼容性
  18. 大楼
  19. 浏览整合

protobuf.js
(原始内容存档于2012-10-12). protobuf.js

协议缓冲 是一种语言中和,平台中和,可扩展的串行式结构数据,用于通信协议,数据存储,以及更多,最初由Google设计(见) (中文(简体) ).

(原始内容存档于2012-10-12). protobuf.js 是 JavaScript 纯执行 类型脚本 支持 节点.js 和浏览器。 它很容易使用,不牺牲 性能,有良好的符合 和工作出盒 . proto (中文(简体) ) 档案!

目录

安装

节点.js

npm install protobufjs --save
// Static code + Reflection + .proto parser
var protobuf = require("protobufjs");

// Static code + Reflection
var protobuf = require("protobufjs/light");

// Static code only
var protobuf = require("protobufjs/minimal");

可选 命令行工具 生成静态代码和反射捆绑 protobufjs-cli 软件包,可以单独安装 :

npm install protobufjs-cli --save-dev

浏览器

选择匹配您的需要的变体, 用精确的版本标签替换 释放 您的项目取决于。 例如,要使用精密的全变体:

<script src="//cdn.jsdelivr.net/npm/[email protected]/dist/protobuf.min.js"></script>
分发地点
满https://cdn.jsdelivr.net/npm/protobufjs/dist/ (中文(简体) )
光线https://cdn.jsdelivr.net/npm/protobufjs/dist/light/ (中文(简体) )
最小值https://cdn.jsdelivr.net/npm/protobufjs/dist/minimal/ (中文(简体) )

所有变体都支持通用JS和AMD加载器,并在全球范围内导出为 window.protobuf。 。 。 .

使用量

由于JavaScript是一种动态打字语言,protobuf.js使用a的概念 有效消息 为了尽可能提供最好的 业绩 (作为副产品,适当的打字):

有效消息

有效消息是指(1)不遗漏任何所需的字段和(2)完全由线条格式作者理解的JS类型所组成的对象.

有效的电文有两种可能类型,编码器为了方便,可以和这两种信息一起工作:

  • 信件实例 (在原型上带有默认值的电文类的明显实例)自然满足了有效电文的要求并
  • 普通 Java 脚本对象 也满足了有效信息的要求.

简言之,有线格式写作机理解以下类型: 1

字段类型预期联合来文类型(创建、编码)转换(从对象)
s-/u-/int32 (韩语)
s-/固定32个
number (32位整数)value | 0 如果签名
value >>> 0 未签名的
s-/u-/int 64 (韩语)
s-/固定64个
Long- 喜欢(最佳)
number (53位整数)
Long.fromValue(value) 与长.js
parseInt(value, 10) 否则
浮动
双
numberNumber(value)
嘘booleanBoolean(value)
字符串stringString(value)
字节Uint8Array (优化)
Buffer (节点下最佳)
Array.<number> (8个位整数)
base64.decode(value) 如果一个 string
Object 无零 .length 假设为缓冲
语句number (32位整数)查找数字代号,如果 string
消息有效消息Message.fromObject(value)
重复 TArray<T>复制
地图<K, V>Object<K,V>复制
  • 明确 undefined 财务报告和审定财务报表 null 如果字段是可选的,则视为未设置.
  • 映射是按键是相应值的字符串表示或8个字符长散列字符串的对象 Long-喜欢.

工具集

考虑到这一点,并且出于性能原因,每个信息类都提供了一套截然不同的方法,每种方法只做一件事. 这避免了不必要的断言/冗余操作,因为性能令人关切,但也迫使用户进行校验(普通JavaScript对象) 可能会 必要时,例如,在处理用户输入时,就明确发出有效的信息.

说明 那个 Message 下文指任何信件类.

  • 信件. 确认(新闻: Object: null|string
    核实 普通 Java 脚本对象 满足有效电文的要求,因此可以不发问题地编码. 它不扔而是将错误消息作为字符串返回,如果有的话.

    var payload = "invalid (not an object)";
    var err = AwesomeMessage.verify(payload);
    if (err)
      throw Error(err);
    
  • Message.encode 消息编码(新闻: Message|Object [,作家: Writer[ ]: Writer
    编码 a 消息实例 无效 普通 Java 脚本对象。这种方法并不隐含地验证消息,由用户确保有效有效消息.

    var buffer = AwesomeMessage.encode(message).finish();
    
  • 消息. encode 有限(新闻: Message|Object [,作家: Writer[ ]: Writer
    喜欢 Message.encode 但也预留了信息长度作为瓦林.

  • 信件. 解码(阅读: Reader|Uint8Array: Message
    将缓冲解码为 a 消息实例如果缺少所需的字段,则丢出一个 util.ProtocolError 带有 instance 属性设置到迄今为止已解码的信件。 如果线条格式无效, 它会扔出一个 Error。 。 。 .

    try {
      var decodedMessage = AwesomeMessage.decode(buffer);
    } catch (e) {
        if (e instanceof protobuf.util.ProtocolError) {
          // e.instance holds the so far decoded message with missing required fields
        } else {
          // wire format is invalid
        }
    }
    
  • 信件. 解码限制(阅读: Reader|Uint8Array: Message
    喜欢 Message.decode 但另外读取了预想中的信息的长度为一瓦林.

  • 信件. 创建(财产: Object: Message
    创建新 消息实例 从符合有效消息要求的一组属性。 在适当情况下,建议采用 Message.create 结束 Message.fromObject 因为它不可能进行多余的转换.

    var message = AwesomeMessage.create({ awesomeField: "AwesomeString" });
    
  • 信件。 来自对象(目标: Object: Message
    转换任何非验证 普通 Java 脚本对象 改为 消息实例 采用上表概述的转换步骤.

    var message = AwesomeMessage.fromObject({ awesomeField: 42 });
    // converts awesomeField to a string
    
  • 信件。 到对象(新闻: Message [,选项: ConversionOptions[ ]: Object
    转换 a 消息实例 对任意行为 普通 Java 脚本对象 用于与其他图书馆或存储的互操作性。 生成的平版 JavaScript 对象 可能会 仍然满足有效消息的要求,取决于指定的实际转换选项,但大部分时间不满足.

    var object = AwesomeMessage.toObject(message, {
      enums: String,  // enums as string names
      longs: String,  // longs as strings (requires long.js)
      bytes: String,  // bytes as base64 encoded strings
      defaults: true, // includes default values
      arrays: true,   // populates empty arrays (repeated fields) even if defaults=false
      objects: true,  // populates empty objects (map fields) even if defaults=false
      oneofs: true    // includes virtual oneof fields set to the present field's name
    });
    

为参考,下图旨在显示不同方法与有效消息概念之间的关系:

Toolset Diagram

换句话说: verify 说明电话 create 或者说 encode 直接在平面对象上将[分别产生有效消息]成功. fromObject另一方面,从更广泛的平面对象转换为创建有效消息。 ()参考(中文(简体) )

实例

使用. proto 文件

可以使用完整的库来装入已存在的.proto文件,该库对定义进行剖析并编译,以便随时使用(基于反应的)消息类:

// awesome.proto
package awesomepackage;
syntax = "proto3";

message AwesomeMessage {
    string awesome_field = 1; // becomes awesomeField
}
protobuf.load("awesome.proto", function(err, root) {
    if (err)
        throw err;

    // Obtain a message type
    var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");

    // Exemplary payload
    var payload = { awesomeField: "AwesomeString" };

    // Verify the payload if necessary (i.e. when possibly incomplete or invalid)
    var errMsg = AwesomeMessage.verify(payload);
    if (errMsg)
        throw Error(errMsg);

    // Create a new message
    var message = AwesomeMessage.create(payload); // or use .fromObject if conversion is necessary

    // Encode a message to an Uint8Array (browser) or Buffer (node)
    var buffer = AwesomeMessage.encode(message).finish();
    // ... do something with buffer

    // Decode an Uint8Array (browser) or Buffer (node) to a message
    var message = AwesomeMessage.decode(buffer);
    // ... do something with message

    // If the application uses length-delimited buffers, there is also encodeDelimited and decodeDelimited.

    // Maybe convert the message back to a plain object
    var object = AwesomeMessage.toObject(message, {
        longs: String,
        enums: String,
        bytes: String,
        // see ConversionOptions
    });
});

此外,如果首选的话,可以通过省略回调来使用承诺语法:

protobuf.load("awesome.proto")
    .then(function(root) {
       ...
    });

使用 JSON 描述符

图书馆使用相当于.proto定义的JSON描述. 例如,以下定义与上文所见.proto定义相同:

// awesome.json
{
  "nested": {
    "awesomepackage": {
      "nested": {
        "AwesomeMessage": {
          "fields": {
            "awesomeField": {
              "type": "string",
              "id": 1
            }
          }
        }
      }
    }
  }
}

JSON描述符与内部反射结构非常相似:

类型( T)扩展类型属性
反射对象选项
命名空间反射对象筑巢
根号命名空间筑巢
类型命名空间字段
数字反射对象数值
外地反射对象规则, 类型, (中文(简体) ), 编号
地图字段外地密钥类型
1个反射对象其中一个 (字段名称阵列)
服务命名空间方法
方法反射对象类型, 请求类型, (中文(简体) ), 响应类型,请求Stream,响应Stream
  • 粗体属性 需要这样做. 斜体类型 是抽象的.
  • T.fromJSON(name, json) 从 JSON 描述符创建相应的反射对象
  • T#toJSON() 从相应的反射对象创建 JSON 描述符( 它的名称被用作母体内部的密钥)

完全使用 JSON 描述符而不是 . proto 文件可以只使用光库(在这种情况下不需要解析符) .

JSON 描述器可以用通常的方式装入:

protobuf.load("awesome.json", function(err, root) {
    if (err) throw err;

    // Continue at "Obtain a message type" above
});

或者可以装入内线 :

var jsonDescriptor = require("./awesome.json"); // exemplary for node

var root = protobuf.Root.fromJSON(jsonDescriptor);

// Continue at "Obtain a message type" above

仅使用反射

完整和光线库都包含全反射支持. 例如,人们可以仅仅通过思考来界定上述例子中所包含的.原始定义:

...
var Root  = protobuf.Root,
    Type  = protobuf.Type,
    Field = protobuf.Field;

var AwesomeMessage = new Type("AwesomeMessage").add(new Field("awesomeField", 1, "string"));

var root = new Root().define("awesomepackage").add(AwesomeMessage);

// Continue at "Create a new message" above
...

关于反射结构的详细资料,可在 API 文档。 。 。 .

使用自定义类

消息类也可以以自定义功能来扩展,并且还可以注册带有被反射消息类型的自定义构建器:

...

// Define a custom constructor
function AwesomeMessage(properties) {
    // custom initialization code
    ...
}

// Register the custom constructor with its reflected type (*)
root.lookupType("awesomepackage.AwesomeMessage").ctor = AwesomeMessage;

// Define custom functionality
AwesomeMessage.customStaticMethod = function() { ... };
AwesomeMessage.prototype.customInstanceMethod = function() { ... };

// Continue at "Create a new message" above

(*) 除了参考其反映的类别外,通过 AwesomeMessage.$type 财务报告和审定财务报表 AwesomeMesage#$type,相应的自定义类自动包含:

  • AwesomeMessage.create
  • AwesomeMessage.encode 财务报告和审定财务报表 AwesomeMessage.encodeDelimited
  • AwesomeMessage.decode 财务报告和审定财务报表 AwesomeMessage.decodeDelimited
  • AwesomeMessage.verify
  • AwesomeMessage.fromObject, (中文(简体) ), AwesomeMessage.toObject 财务报告和审定财务报表 AwesomeMessage#toJSON

之后,此类型的解码信件是 instanceof AwesomeMessage。 。 。 .

或者,如果不需要自定义初始化代码,也可以重新使用并扩展内部构造器:

...

// Reuse the internal constructor
var AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage").ctor;

// Define custom functionality
AwesomeMessage.customStaticMethod = function() { ... };
AwesomeMessage.prototype.customInstanceMethod = function() { ... };

// Continue at "Create a new message" above

使用服务

图书馆也支持消费服务,但并不对实际运输通道作任何假设. 相反,用户必须提供一个合适的 RPC 执行,这是一个同步函数,它以反射的服务方法,二进制请求和节点风格的回调作为其参数:

function rpcImpl(method, requestData, callback) {
    // perform the request using an HTTP request or a WebSocket for example
    var responseData = ...;
    // and call the callback with the binary response afterwards:
    callback(null, responseData);
}

下面是一个使用 grpc npm 软件包进行打字程序执行的工作示例 .

const grpc = require('grpc')

const Client = grpc.makeGenericClientConstructor({})
const client = new Client(
  grpcServerUrl,
  grpc.credentials.createInsecure()
)

const rpcImpl = function(method, requestData, callback) {
  client.makeUnaryRequest(
    method.name,
    arg => arg,
    arg => arg,
    requestData,
    callback
  )
}

示例

// greeter.proto
syntax = "proto3";

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}
...
var Greeter = root.lookup("Greeter");
var greeter = Greeter.create(/* see above */ rpcImpl, /* request delimited? */ false, /* response delimited? */ false);

greeter.sayHello({ name: 'you' }, function(err, response) {
    console.log('Greeting:', response.message);
});

服务还支持承诺:

greeter.sayHello({ name: 'you' })
    .then(function(response) {
        console.log('Greeting:', response.message);
    });

还有一个 用于流媒体 RPC。 。 。 .

注意服务API是针对客户的. 实施服务器端端点几乎总是需要传输通道(即:http,websocket等)的特定代码,唯一的共同点是它解码和编码消息.

使用类型脚本

图书馆有自己的船 类型定义 和现代编辑 视觉工作室代码 将自动检测并用于代码补全.

Npm 软件包取决于 @ types/ 节点 因为 Buffer 财务报告和审定财务报表 @ types/ 长 因为 Long。如果您不是为节点而建和/或不使用长的.js,那么手动排除它们应该是安全的.

利用联合来文API

上面显示的API与TypeScript几乎相同. 然而,由于每件事物都是被打入的,在动态生成的信息类实例中访问字段需要使用括号注释(即:. message["awesomeField"])或明确铸造. 或者,可以使用 为静态对应程序生成的打字文件。 。 。 .

import { load } from "protobufjs"; // respectively "./node_modules/protobufjs"

load("awesome.proto", function(err, root) {
  if (err)
    throw err;

  // example code
  const AwesomeMessage = root.lookupType("awesomepackage.AwesomeMessage");

  let message = AwesomeMessage.create({ awesomeField: "hello" });
  console.log(`message = ${JSON.stringify(message)}`);

  let buffer = AwesomeMessage.encode(message).finish();
  console.log(`buffer = ${Array.prototype.toString.call(buffer)}`);

  let decoded = AwesomeMessage.decode(buffer);
  console.log(`decoded = ${JSON.stringify(decoded)}`);
});

使用生成的静态代码

如果您生成了静态代码到 bundle.js 使用 CLI 及其类型定义 bundle.d.ts,那么你可以仅仅做:

import { AwesomeMessage } from "./bundle.js";

// example code
let message = AwesomeMessage.create({ awesomeField: "hello" });
let buffer  = AwesomeMessage.encode(message).finish();
let decoded = AwesomeMessage.decode(buffer);

使用装饰器

图书馆还包括尽早实施 装饰器。 。 。 .

说明 在TypeScript中,装饰器是一个实验性特征,而根据JS目标,宣布顺序是重要的. 譬如说, @Field.d(2, AwesomeArrayMessage) 要求 AwesomeArrayMessage 目标设定时已提前定义 ES5。 。 。 .

import { Message, Type, Field, OneOf } from "protobufjs/light"; // respectively "./node_modules/protobufjs/light.js"

export class AwesomeSubMessage extends Message<AwesomeSubMessage> {

  @Field.d(1, "string")
  public awesomeString: string;

}

export enum AwesomeEnum {
  ONE = 1,
  TWO = 2
}

@Type.d("SuperAwesomeMessage")
export class AwesomeMessage extends Message<AwesomeMessage> {

  @Field.d(1, "string", "optional", "awesome default string")
  public awesomeField: string;

  @Field.d(2, AwesomeSubMessage)
  public awesomeSubMessage: AwesomeSubMessage;

  @Field.d(3, AwesomeEnum, "optional", AwesomeEnum.ONE)
  public awesomeEnum: AwesomeEnum;

  @OneOf.d("awesomeSubMessage", "awesomeEnum")
  public which: string;

}

// example code
let message = new AwesomeMessage({ awesomeField: "hello" });
let buffer  = AwesomeMessage.encode(message).finish();
let decoded = AwesomeMessage.decode(buffer);

支持的装饰有:

  • Type.d( 类型名称) : string(中文(简体) )   (可选)
    将一个类作为原生信息类型。 若为 typeName 未指定,构造器的运行时函数名用于反射类型.

  • 字段.d<T>(字段编号: number,字段类型 : string | Constructor<T>现场规则 "optional" | "required" | "repeated",默认值 : T(中文(简体) )
    以指定的 id 和 protobuf 类型表示一个属性作为原生体字段.

  • Map Field.d <T extend { [key: string]: 任意 QQ(field Id: number字段键盘 : string田园瓦鲁埃Type. string | Constructor<{}>(中文(简体) )
    以指定的 id、 protobuf 密钥和值类型将属性作为原型图域.

  • OneOf.d <T 扩展字符串>(... 字段名称 : string[](中文(简体) )
    标注一个财产,作为涵盖指定字段的原型.

其他说明:

  • 装饰类型 protobuf.roots["decorated"] 使用平面结构,所以没有重复名称.
  • Enums被复制到一个反射的enum上,在装饰器评价上有一个通用名称,因为被引用的enum对象没有装饰器可以使用的运行时名.
  • 默认值必须指定为给装饰者的参数,而不是使用属性初始化器进行适当的原型行为.
  • 装饰类上的财产名不得在编译时间上被重新命名(即由修饰器重命名),因为装饰者只是作为字符串接收了原字段名.

准备! 没有那么漂亮,但你可以 使用纯 JavaScript 中的装饰器 还有.

其他文件

协议缓冲

(原始内容存档于2012-10-12). protobuf.js

社区

业绩

该套装包括一个基准,将protobuf.js的性能与本地的JSON(尽可能这样做)进行比较;以及 谷歌的JS执行在运行的i7-2600K节点6.9.1上,它产生:

benchmarking encoding performance ...

protobuf.js (reflect) x 541,707 ops/sec ±1.13% (87 runs sampled)
protobuf.js (static) x 548,134 ops/sec ±1.38% (89 runs sampled)
JSON (string) x 318,076 ops/sec ±0.63% (93 runs sampled)
JSON (buffer) x 179,165 ops/sec ±2.26% (91 runs sampled)
google-protobuf x 74,406 ops/sec ±0.85% (86 runs sampled)

   protobuf.js (static) was fastest
  protobuf.js (reflect) was 0.9% ops/sec slower (factor 1.0)
          JSON (string) was 41.5% ops/sec slower (factor 1.7)
          JSON (buffer) was 67.6% ops/sec slower (factor 3.1)
        google-protobuf was 86.4% ops/sec slower (factor 7.3)

benchmarking decoding performance ...

protobuf.js (reflect) x 1,383,981 ops/sec ±0.88% (93 runs sampled)
protobuf.js (static) x 1,378,925 ops/sec ±0.81% (93 runs sampled)
JSON (string) x 302,444 ops/sec ±0.81% (93 runs sampled)
JSON (buffer) x 264,882 ops/sec ±0.81% (93 runs sampled)
google-protobuf x 179,180 ops/sec ±0.64% (94 runs sampled)

  protobuf.js (reflect) was fastest
   protobuf.js (static) was 0.3% ops/sec slower (factor 1.0)
          JSON (string) was 78.1% ops/sec slower (factor 4.6)
          JSON (buffer) was 80.8% ops/sec slower (factor 5.2)
        google-protobuf was 87.0% ops/sec slower (factor 7.7)

benchmarking combined performance ...

protobuf.js (reflect) x 275,900 ops/sec ±0.78% (90 runs sampled)
protobuf.js (static) x 290,096 ops/sec ±0.96% (90 runs sampled)
JSON (string) x 129,381 ops/sec ±0.77% (90 runs sampled)
JSON (buffer) x 91,051 ops/sec ±0.94% (90 runs sampled)
google-protobuf x 42,050 ops/sec ±0.85% (91 runs sampled)

   protobuf.js (static) was fastest
  protobuf.js (reflect) was 4.7% ops/sec slower (factor 1.0)
          JSON (string) was 55.3% ops/sec slower (factor 2.2)
          JSON (buffer) was 68.6% ops/sec slower (factor 3.2)
        google-protobuf was 85.5% ops/sec slower (factor 6.9)

这些成果是通过下列方式取得的:

  • 在运行时生成特定类型编码器、解码器、核查器和转换器
  • 根据环境配置读者/作家界面
  • 在有利和当然有利的情况下使用特定节点功能
  • 通过拆分避免不必要的操作 工具盘。 。 。 .

您也可以运行 基准 .

$> npm run bench

财务报告和审定财务报表 配置器 自己(后者需要最新版本的节点):

$> npm run prof <encode|decode|encode-browser|decode-browser> [iterations=10000000]

请注意,截至此写作时,基准套件在节点7.2.0上的性能明显慢于6.9.1,因为有蛾.

兼容性

  • 除了IE8之外,其他所有现代和非现代浏览器都有工作.
  • 因为这个包的内部不依赖 google/protobuf/descriptor.proto,选项被解析并按字面形式呈现.
  • 如果打入的数组没有环境支持,则会取而代之地使用平面数组.
  • 对ES5前期环境的支持(IE8除外)可以通过 使用多填充器。 。 。 .
  • 支助 内容安全政策-被限制的环境(如Chrome扩展而无不安全-eval)可以通过生成和使用静态代码来实现.
  • 如果需要用64位值(int64, int64等)的正确工作方式,只需安装 长. js 和这个图书馆一起 全部64位数字将返回为 Long 实例,而不是一个可能不安全的 JavaScript 号码(见) (中文(简体) ).
  • 关于描述符.proto互操作性,参见: 分机/说明

大楼

要自己建库或其组件, 请从 GitHub 复制并安装开发依赖性 :

$> git clone https://github.com/protobufjs/protobuf.js.git
$> cd protobuf.js
$> npm install

利用各自的原始地图建立相应的开发和制作版本 dist/数字 :

$> npm run build

建立文档 docs/数字 :

$> npm run docs

将类型脚本定义构建到 index.d.ts数字 :

$> npm run build:types

浏览整合

默认情况下,protobuf.js在任何浏览器中集成构建过程而不需要任何可选模块. 因此:

  • 如果需要Int64支持,则明确要求 long 模块在您的项目中某处, 否则它将被排除在外 。 这假设一个全球性的 require 函数是存在的,protobuf.js可以调用以获取长模块.

    如果没有全球 require 在捆绑后出现的函数,也可以在程序上指定长模块:

    var Long = ...;
    
    protobuf.util.Long = Long;
    protobuf.configure();
    
  • 如果你有任何特别的要求,有 捆绑器 供参考.

许可证 : BSD 3- 标签许可证

版本与发布记录

@cosmology/protobufjs 共发布 3 个版本,首次发布于 2023/06/22;过去 12 个月发布了 0 个版本。

版本发布日期距今
7.3.2latest2024/06/132 年前
6.11.62023/06/223 年前
6.11.52023/06/223 年前

关于 @cosmology/protobufjs 的常见问题

@cosmology/protobufjs 是什么?

JavaScript( & TypeScript) 协议缓冲器 .

如何安装 @cosmology/protobufjs?

在项目目录运行 npm install @cosmology/protobufjs,或使用 pnpm add / yarn add / bun add。

@cosmology/protobufjs 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@cosmology/protobufjs 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@cosmology/protobufjs 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=12.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cosmology/protobufjs 可以商用吗?

@cosmology/protobufjs 使用 BSD-3-Clause 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。另外不得用原作者名义为衍生产品背书。以上为概括,不构成法律意见,请以许可原文为准。

@cosmology/protobufjs 的下载量有多少?

根据 npm 官方下载统计,@cosmology/protobufjs 在 2026/10/11 – 2026/11/09 这 30 天内被下载 43,152 次,日均约 1,438 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cosmology/protobufjs 还在维护吗?

最新版本 7.3.2 发布于 2024/06/13(2 年前);至今共发布 3 个版本,其中过去 12 个月发布了 0 个;首次发布于 2023/06/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。