@apollo/protobufjs

中文文档
1.2.8发布于 2026/05/01BSD-3-ClauseTypeScriptCommonJS近 30 天下载 1800.7万

JavaScript( & TypeScript) 协议缓冲器 .

中文使用文档
文档目录25 节
  1. 目录
  2. 安装
  3. 节点.js
  4. 浏览器
  5. 分发量
  6. 使用量
  7. 有效消息
  8. 工具集
  9. 实例
  10. 使用. proto 文件
  11. 使用 JSON 描述符
  12. 仅使用反射
  13. 使用自定义类
  14. 使用服务
  15. 使用类型脚本
  16. 命令行
  17. 用于 Java 脚本的 pbjs
  18. 类型脚本的 pbts
  19. 反射对静态代码
  20. 命令行 API
  21. 其他文件
  22. 业绩
  23. 兼容性
  24. 大楼
  25. 浏览整合

阿波罗叉

我们准备了 源重播 因为我们需要修改包 用于阿波罗服务器.

这个包只供阿波罗·塞弗使用. 您不应该直接在其它上下文中使用它 。 它只应用于阿波罗服务器上的具体原生生物定义,当然不应用于用户控制的原生生物定义(阿波罗没有试图将所有仅会影响使用由用户控制的原生生物定义的上游弱点补上. )

1.0.0版本从 master 包含6.8.8版 加上一些未释放的犯法行为. 萨

protobuf.js

donate ❤

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

(原始内容存档于2012-10-12). protobuf.js 是 JavaScript 纯执行 类型脚本 支持 节点.js 和浏览器。 它很容易使用, 猛烈地快速 和工作出盒 . proto (中文(简体) ) 档案!

目录

安装

节点.js

$> npm install @apollo/protobufjs [--save --save-prefix=~]
var protobuf = require("@apollo/protobufjs");

说明 由于历史原因,这个图书馆的版本方案是无法兼容的。 对于保证的后向兼容性,总是依赖于 ~6.A.B 改为 ^6.A.B (因此 --save-prefix (见上文).

浏览器

发展:

<script src="//cdn.rawgit.com/dcodeIO/protobuf.js/6.X.X/dist/protobuf.js"></script>

生产:

<script src="//cdn.rawgit.com/dcodeIO/protobuf.js/6.X.X/dist/protobuf.min.js"></script>

记住 将版本标记替换为精确 释放 您的项目取决于.

库支持CommonJS和AMD加载器,并在全球范围内输出为 protobuf。 。 。 .

分发量

如果捆绑大小是一个因素,则会有额外的剥离版本 完整库 排除某些功能的可用(~19kb gziped):

  • 在与 JSON 描述器合作时(即由 密码)和/或只进行反思,见 轻型库 (~16kb gzipped),不包括解析器. 常见JS切入点为:

    var protobuf = require("@apollo/protobufjs/light");
    
  • 仅使用静态生成的代码工作时,请参见 最小图书馆 (~ 6.5kb gzipped),也排除了反射. 常见JS切入点为:

    var protobuf = require("@apollo/protobufjs/minimal");
    

使用量

由于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)
  • 明确 undefined 财务报告和审定财务报表 null 如果字段是可选的,则视为未设置.
  • 重复字段为 Array.<T>。 。 。 .
  • 地图字段是 Object.<string,T> 键为相应值的字符串表示式或8个字符长 二进制散列字符串 Long-喜欢.
  • 类型标记为 最佳 提供最佳性能,因为不需要转换步骤(即数字到低位和高位或基数64字符串来缓冲).

工具集

考虑到这一点,并且出于性能原因,每个信息类都提供了一套截然不同的方法,每种方法只做一件事. 这避免了不必要的断言/冗余操作,因为性能令人关切,但也迫使用户进行校验(普通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": {
    "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/ 长 因为 Long。如果您不是为节点而建和/或不使用长的.js,那么手动排除它们应该是安全的.

利用联合来文API

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

import { load } from "@apollo/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 "@apollo/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 中的装饰器 还有.

命令行

说明 移动 CLI 到 其自己的软件包 这是一项正在进行的工作。 目前仍属于主包.

命令行界面(CLI)可用于文件格式之间的翻译并生成静态代码以及TypeScript定义.

用于 Java 脚本的 pbjs

Translates between file formats and generates static code.

  -t, --target     Specifies the target format. Also accepts a path to require a custom target.

                   json          JSON representation
                   json-module   JSON representation as a module
                   proto2        Protocol Buffers, Version 2
                   proto3        Protocol Buffers, Version 3
                   static        Static code without reflection (non-functional on its own)
                   static-module Static code without reflection as a module

  -p, --path       Adds a directory to the include path.

  -o, --out        Saves to a file instead of writing to stdout.

  --sparse         Exports only those types referenced from a main file (experimental).

  Module targets only:

  -w, --wrap       Specifies the wrapper to use. Also accepts a path to require a custom wrapper.

                   default   Default wrapper supporting both CommonJS and AMD
                   commonjs  CommonJS wrapper
                   amd       AMD wrapper
                   es6       ES6 wrapper (implies --es6)
                   closure   A closure adding to protobuf.roots where protobuf is a global

  -r, --root       Specifies an alternative protobuf.roots name.

  -l, --lint       Linter configuration. Defaults to protobuf.js-compatible rules:

                   eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins

  --es6            Enables ES6 syntax (const/let instead of var)

  Proto sources only:

  --keep-case      Keeps field casing instead of converting to camel case.

  Static targets only:

  --no-create      Does not generate create functions used for reflection compatibility.
  --no-encode      Does not generate encode functions.
  --no-decode      Does not generate decode functions.
  --no-verify      Does not generate verify functions.
  --no-convert     Does not generate convert functions like from/toObject
  --no-delimited   Does not generate delimited encode/decode functions.
  --no-beautify    Does not beautify generated code.
  --no-comments    Does not output any JSDoc comments.

  --force-long     Enforces the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.
  --force-number   Enforces the use of 'number' for s-/u-/int64 and s-/fixed64 fields.
  --force-message  Enforces the use of message instances instead of plain objects.

usage: pbjs [options] file1.proto file2.json ...  (or pipe)  other | pbjs [options] -

对于生产环境,建议将您所有.proto文件捆绑到一个单一的.json文件中,这将最小化网络请求的数量并避免任何解析器上浮(int:仅使用 光线 库 :

$> pbjs -t json file1.proto file2.proto > bundle.json

现在,要么把这个文件纳入您的最后捆绑:

var root = protobuf.Root.fromJSON(require("./bundle.json"));

或按通常方式装入:

protobuf.load("bundle.json", function(err, root) {
    ...
});

生成的静态代码, 另一方面,工作与只有 最小 图书馆。 举个例子

$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto

将生成内部定义的静态代码 file1.proto 财务报告和审定财务报表 file2.proto 改为通用JS模块 compiled.js。 。 。 .

准备! 记录您的 . proto 文件 /** ... */- 块或(拖动) /// ... 线条翻译为生成的静态代码.

类型脚本的 pbts

Generates TypeScript definitions from annotated JavaScript files.

  -o, --out       Saves to a file instead of writing to stdout.

  -g, --global    Name of the global object in browser environments, if any.

  --no-comments   Does not output any JSDoc comments.

  Internal flags:

  -n, --name      Wraps everything in a module of the specified name.

  -m, --main      Whether building the main library without any imports.

usage: pbts [options] file1.js file2.js ...  (or)  other | pbts [options] -

从上面的例子来看,下面不仅生成一个普通JS模块的静态代码 compiled.js 及其相应的类型脚本定义 compiled.d.ts数字 :

$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
$> pbts -o compiled.d.ts compiled.js

此外,静态模块的TypeScript定义与基于反射的对等模块(即由JSON模块导出)相兼容,只要满足以下条件: 1

  1. 而不是使用 new SomeMessage(...),总是使用 SomeMessage.create(...) 因为反射对象不提供构建器.
  2. 类型、服务和enums必须从大写字母入手,才能作为所反映类型的属性(即能够使用) MyMessage.MyEnum 改为 root.lookup("MyMessage.MyEnum")) (中文(简体) ).

例如,以下生成一个 JSON 模块 bundle.js (单位:千美元) bundle.d.ts,但没有静态代码 :

$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -

反射对静态代码

在使用.proto文件时,直接要求完整库分别纯反射/JSON光光库,几乎所有代码,但相对短的描述符被共享.

另一方面,静态代码只需要最小的库,但生成没有任何反射特性的额外源代码. 这还意味着,当生成的代码数量超过完整的光库大小后,静态生成的代码就会比以描述符为基础的代码大出一个断点.

性能方面没有显著差异,因为静态生成的代码与运行时生成的代码基本相同,而且如上一节所见,两者基本上可以互换.

来源图书馆优点权衡
. proto (中文(简体) )满易于编辑
与其他图书馆的互通性
没有编译步骤
一些解析和可能的网络间接费用
贾森光线易于编辑
没有分析间接费用
单装( 无网络管理)
特有原型
有汇编步骤
静态最小工作地点 eval 访问受到限制
完整记录
小原生物的小脚印
可能很难编辑
无反省
有汇编步骤

命令行 API

通过提供命令行参数和回调,这两种公用事业都可以在方案上使用 main 函数:

var pbjs = require("@apollo/protobufjs/cli/pbjs"); // or require("@apollo/protobufjs/cli").pbjs / .pbts

pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
    if (err)
        throw err;
    // do something with output
});

其他文件

协议缓冲

(原始内容存档于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/dcodeIO/protobuf.js.git
$> cd protobuf.js
$> npm install

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

$> npm run build

建立文档 docs/数字 :

$> npm run docs

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

$> npm run types

浏览整合

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

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

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

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

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

版本与发布记录

@apollo/protobufjs 共发布 17 个版本,首次发布于 2019/11/20;过去 12 个月发布了 1 个版本。

版本发布日期距今
1.2.8latest2026/05/016 个月前
1.2.72022/11/103 年前
1.2.62022/10/014 年前
1.2.52022/09/304 年前
1.2.42022/06/174 年前
1.2.32022/06/174 年前

关于 @apollo/protobufjs 的常见问题

@apollo/protobufjs 是什么?

JavaScript( & TypeScript) 协议缓冲器 .

如何安装 @apollo/protobufjs?

在项目目录运行 npm install @apollo/protobufjs,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 apollo-pbjs、apollo-pbts,可以用 npx apollo-pbjs 直接运行。

@apollo/protobufjs 支持 TypeScript 吗?

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

@apollo/protobufjs 支持 ESM 还是 CommonJS?

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

@apollo/protobufjs 可以商用吗?

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

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

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

@apollo/protobufjs 还在维护吗?

最新版本 1.2.8 发布于 2026/05/01(6 个月前);至今共发布 17 个版本,其中过去 12 个月发布了 1 个;首次发布于 2019/11/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。