什么是ProtoBuf
Protobuf(Protocol Buffers) 是一种由 Google 开发的、语言中立、平台中立、可扩展 的机制,用于 高效地序列化结构化数据。它的核心目的是提供一种比 XML 或 JSON 更小、更快、更简单 的方式来在系统之间(尤其是分布式系统、微服务之间)或用于数据存储时交换数据。
性能对比
同样的数据,压缩10000次,得到以下数据
| 压缩方式 | 耗时(压缩10000次耗时) | 包大小 |
|---|---|---|
| Protobuf | 9ms | 25B |
| JSON+gZip | 483ms | 75B |
可以看出protobuf相比gzip,耗时更短,压缩率更好,是比较推荐的压缩方式。
ProtoBuf的用法
1. 定义proto文件
首先定义一个proto文件,下面放一个简单的例子
syntax = "proto3";
message Message {
int32 intValue = 1;
float floatValue = 2;
string stringValue = 3;
message Info {
string name = 1;
}
repeated Info arr = 4;
}
上面的proto文件中简单的定义了几个类型,比如int32是整数、float是浮点数(嗯。。。对应前端都是number~~~但是这个是个所有端都能用的类型,所以还是需要区分一下)、string是字符串。里面还定义了一个Info,是为了后面的arr字段是个数组,可以是简单的类型,也可以是自定义的任何类型。
2. 静态编译proto
proto类型也支持动态编译,不过会有一定的耗时,所以我们使用静态编译的方法
安装依赖
npm install protobufjs --save
npm install protobufjs-cli --save-dev
编译命令
"scripts": {
"proto": "pbjs -t static-module -w cmomonjs -o src/proto/message.js proto/message.proto",
},
命令中 -o src/proto/message.js 是静态编译后输出的js文件路径,proto/message.proto是proto源文件的路径
使用方式
encode
// 需要压缩的数据
const data = {
intValue: 1,
stringValue: "1",
arr: [{
name: "1"}, {
name: "2"}, {
name: "3"}, {
name: "4"}],
}
// 执行压缩方法
const buffer = Message.encode(data).finish();
decode
// buffer是上面encode方法返回的Uint8Array
Message.decode(buffer);
兼容性
在定义proto文件的时候我们写了syntax = “proto3” 所以定义的每个字段都是可选的,相当于typescript中每个字段都加了?。如果需要扩展,只需要在定义中增加字段即可,注意=后面的index需要递增。
并且protobuf是所有端都可以使用的一种压缩方式,包括Android、iOS、Windows、Mac、服务端等
代码
<html>
<head>
<title>测试protobuf</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<script src="../dist/index.js"></script>
<script src="pako.js"></script>
<script>
const data = {
intValue: 1,
stringValue: "1",
arr: [{
name: "1"}, {
name: "2"}, {
name: "3"}, {
name: "4"}],
}
let ts = Date.now();
for (let i = 0; i < 10000; ++i) {
Message.encode(data).finish();
}
console.log("proto time:", Date.now() - ts, " bytes:", Message.encode(data).finish().byteLength);
ts = Date.now();
for (let i = 0; i < 10000; ++i) {
pako.gzip(JSON.stringify(data));
}
console.log("gzip time:", Date.now() - ts, " bytes:", pako.gzip(JSON.stringify(data)).byteLength);
</script>
</body>
</html>
其他
如果你也是专注前端多媒体或者对前端多媒体感兴趣,可以搜索微信公众号”前端多媒体”


















暂无评论内容