npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jserial

v0.2.6

Published

[![GitHub](https://img.shields.io/github/license/hojin-jeong/jserial)](https://github.com/hojin-jeong/jserial/blob/master/license.md) [![npm](https://img.shields.io/npm/v/jserial)](https://badge.fury.io/js/jserial)

Readme

jserial

GitHub npm

Compressed and Fast JSON Serializer

Using Libraries

msgpackr — MessagePack serialization
lz4_flex (Rust → WASM) — LZ4 compression
WASM memory layout inspired by @evan/wasm

Quick Start

Installation

npm install jserial --save
# or
yarn add jserial

Browser Support

This library is compatible with modern browsers and module bundlers (Webpack, Rspack, Vite, etc.). It handles platform-specific dependencies internally, so you don't need extensive polyfill configurations.

Simply import and use it in your project:

import JsonSerializer from 'jserial';

const serializer = new JsonSerializer();
// ...

Basic Usage

const JSONSerializer = require("jserial");
const serializer = new JSONSerializer();

const json = {
  hello: "world",
};
const serialized = serializer.serialize(json);
const deserialized = serializer.deserialize(serialized);
if (deserialized instanceof Error) {
  // Deserialize Error
}

Zero-Copy API

For performance-critical paths, use the zero-copy variants that avoid buffer allocation:

const JsonSerializer = require("jserial")
const serializer = new JsonSerializer()

const data = { hello: "world", numbers: [1, 2, 3] }

// serializeView: returns Uint8Array view into WASM memory (no copy)
const view = serializer.serializeView(data)
// ⚠️ view is invalidated on next serialize call — copy if you need to keep it:
// const copy = Buffer.from(view)

// deserializeView: accepts Uint8Array directly (skips Buffer wrapping)
const result = serializer.deserializeView(view)
console.log(result) // { hello: "world", numbers: [1, 2, 3] }

When to use: High-throughput scenarios where you immediately consume the serialized data (e.g., writing to a socket, comparing buffers). The returned view shares WASM memory and is overwritten on the next serialize/serializeView call.

Msgpack Custom Extension

const JSONSerializer = require("jserial");
class CustomClass {};
JSONSerializer.addExtension({
    class: CustomClass,
    type: 1, // 1 ~ 100
    read(instance) {
        return instance.customData;
    },
    write(data) {
        const customClass = new CustomClass();
        customClass.customData = data;
        return customClass;
    }
});

Using Msgpackr Dictionary

const JSONSerializer = require("jserial");
const serializer = new JSONSerializer("namespace");
// or
const serializer = new JSONSerializer({ namespace: "namespace" });

const json = {
  hello: "world",
};
const serialized = serializer.serialize(json);
const deserialized = serializer.deserialize(serialized);

Stream Framing

For TCP sockets, WebSockets, or other stream-based communication, use FrameStream to handle message framing automatically.

Node.js (Native Streams)

const JsonSerializer = require("jserial");
const net = require("net");

const serializer = new JsonSerializer();
const socket = net.connect({ port: 8080 });

// Create FrameStream from duplex stream
const frame = JsonSerializer.createFrameStream(serializer, socket);

// Read a message
const message = await frame.read();

// Write a message
await frame.write({ hello: "world" });

// Write multiple messages efficiently (batch)
await frame.writeV([
  { id: 1, data: "first" },
  { id: 2, data: "second" },
  { id: 3, data: "third" },
]);

Browser (WhatWG Streams)

import JsonSerializer from "jserial";

const serializer = new JsonSerializer();

// For WebTransport, fetch streams, etc.
const frame = JsonSerializer.createFrameStream(serializer, readable, writable);

// Same API as Node.js
const message = await frame.read();
await frame.write({ hello: "world" });
await frame.writeV([obj1, obj2, obj3]);

// Clean up
frame.close();

API Reference

| Method | Description | | :--- | :--- | | JsonSerializer.createFrameStream(serializer, stream) | Create FrameStream for Node.js duplex stream | | JsonSerializer.createFrameStream(serializer, readable, writable) | Create FrameStream for Browser streams | | frame.read() | Read next deserialized message (Promise) | | frame.readV(count) | Read multiple messages in batch - more efficient when buffered (Promise) Node.js only | | frame.write(data) | Write single message (Promise) | | frame.writeV(dataArray) | Write multiple messages in batch - more efficient (Promise) | | frame.unwrap() | Get underlying stream (Node.js only) | | frame.close() | Release stream resources (Browser only) | | serializeView(data) | Zero-copy serialize — returns Uint8Array view into WASM memory | | deserializeView(buffer) | Deserialize — accepts Uint8Array directly, returns result without output buffer allocation |

Benchmark

Node Version: v24.11.1
Benchmark JSON Size: ~471,357 bytes

| Library | Size | Ratio | Serialize | Deserialize | | :------------------- | --------: | ------: | ---------: | ----------: | | JSON.stringify | 471,357 B | 100.00% | 2.18 ms | 1.74 ms | | Msgpackr | 424,399 B | 90.04% | 1.06 ms | 1.58 ms | | JSON + Gzip | 21,220 B | 4.50% | 4.38 ms | 2.14 ms | | JSON + Brotli | 13,564 B | 2.88% | 971.79 ms | 2.22 ms | | JSON + Zstd (Native) | 17,917 B | 3.80% | 2.10 ms | 1.95 ms | | JSON + Inflate | 21,208 B | 4.50% | 3.98 ms | 1.92 ms | | jserial | 24,428 B | 5.18% | 1.03 ms | 0.76 ms | | jserial (view) | 24,428 B | 5.18% | 0.95 ms | 0.04 ms |

Summary

  • Compression Ratio: Brotli (2.88%) > Zstd (3.80%) > Gzip/Inflate (4.50%) > jserial (5.18%)
    • jserial provides excellent compression close to Gzip level while being dramatically faster.
  • Deserialization Speed: jserial view (0.04 ms) > jserial (0.76 ms) > Msgpackr (1.58 ms) > JSON.parse (1.74 ms)
    • jserial (view) is 43x faster than JSON.parse (0.04 ms vs 1.74 ms) — skips output buffer allocation by returning a WASM memory view directly.
  • Serialization Speed: jserial view (0.95 ms) > jserial (1.03 ms) > Msgpackr (1.06 ms) > JSON.stringify (2.18 ms)
    • jserial (view) beats Msgpackr and JSON.stringify while achieving excellent compression (~5.18%).

BlockFrameStream

For high-throughput scenarios where wire bandwidth matters, BlockFrameStream batches multiple messages into a single LZ4-compressed block using msgpackr sequential structures. This achieves dramatically smaller wire sizes at the cost of a small buffering delay.

Wire format: [4B decompressed_len][4B compressed_len][LZ4(sequential msgpack...)]

const JsonSerializer = require("jserial");
const net = require("net");

const socket = net.connect({ port: 8080 });

const frame = JsonSerializer.createBlockFrameStream(socket, {
  blockSize: 64 * 1024,  // flush when buffer reaches 64KB (default)
  flushInterval: 10,      // auto-flush after 10ms idle (default). 0 = disabled.
  packrOptions: {},        // additional msgpackr options (optional)
});

// Write — buffered until blockSize or flushInterval
await frame.write({ id: 1, action: "update" });

// Batch write (most efficient)
await frame.writeV([{ id: 2 }, { id: 3 }]);

// Force flush
await frame.flush();

// Batch read — up to 11x faster than read()×N
const messages = await frame.readV(100);

frame.destroy();

Configuration

| Option | Type | Default | Description | | :--- | :--- | :--- | :--- | | blockSize | number | 65536 | Flush threshold in bytes. Smaller = lower latency, less compression. | | flushInterval | number | 10 | Auto-flush idle timeout (ms). 0 disables timer flushing. | | packrOptions | object | {} | Options forwarded to msgpackr Packr/Unpackr. |

BlockFrameStream vs FrameStream (1000 msgs)

| Metric | FrameStream | BlockFrameStream | | :--- | :--- | :--- | | Write (1000 msgs) | 14.59 ms | 12.37 ms (1.18x faster) | | readV(N) | 0.24 ms | 0.17 ms (1.44x faster) | | read() individual | 1.00 ms | 2.07 ms (use readV) | | Wire size per message | 225.6 B | 27.9 B (87.6% smaller) |

Tip: Use readV(count) with BlockFrameStream for best performance. Individual read() waits for the entire block to decompress.

BlockFrameStream API

| Method | Description | | :--- | :--- | | JsonSerializer.createBlockFrameStream(stream, options) | Create a BlockFrameStream | | frame.write(data) | Write one message — buffered (Promise) | | frame.writeV(dataArray) | Write multiple messages in batch (Promise) | | frame.read() | Read next message (Promise) | | frame.readV(count) | Read count messages in one batch — 12x faster than read()×N (Promise<Array>) | | frame.flush() | Force compress and send buffered messages (Promise) | | frame.destroy() | Release WASM buffers and stream resources | | frame.unwrap() | Return underlying Node.js stream |