mrkeyoor.com_
Sat 08 Aug 21:00 UTC
npmWeb Frontendupdated 08 Aug 2026

vite-compatible-readable-stream

vite-compatible-readable-stream is a browser-oriented fork of readable-stream 3.6. It exposes the familiar Node Readable, Writable, Duplex, Transform, PassThrough, pipeline, and finished APIs, but rearranges circular imports that caused Rollup and Vite production builds to fail. The README names vite-plugin-shim-react-pdf as its expected consumer, so this is best understood as a compatibility patch for older Node-style dependencies, not a new stream design for application code.

Verdict

Install this only to solve the specific Rollup or Vite circular-dependency problem described by its README, especially in the react-pdf shim path. For new code, native Web Streams in browsers or node:stream in Node are clearer and more current choices.

API stability4/5The exported surface is the long-established readable-stream 3 API: Readable, Writable, Duplex, Transform, PassThrough, pipeline, and finished are all wired from readable.js, and version 3.6.1 has not changed since April 2022. That makes existing behavior predictable, but it also freezes the package before newer Node stream additions and promise-based helpers.
Docs2/5The package README accurately states that this is a readable-stream fork with circular dependencies refactored for Rollup and Vite, and it names the react-pdf shim use case. It does not document the exported classes, browser substitutions, CommonJS shape, or version differences, so users must consult Node's stream documentation and readable-stream source while remembering that newer Node features may not exist here.
Maintenance2/5The repository is not archived and has no open issues or pull requests in GitHub's combined counter, but both the 3.6.1 npm release and last repository push were in April 2022. The tiny patch-focused scope may need little churn, yet there is no current release activity showing that regressions against new Vite, Rollup, or browser versions are being tested.
Ecosystem3/5The package recorded 4,713,708 downloads for the measured week, largely because it sits in dependency graphs that need readable-stream compatibility. Its actual direct ecosystem is narrow: the README points to vite-plugin-shim-react-pdf, the repository has 6 stars, and it offers Node stream compatibility rather than plugins or integrations of its own.

Use it if

  • A Vite production build fails on readable-stream circular dependencies and the package causing it cannot be upgraded
  • You use vite-plugin-shim-react-pdf, whose compatibility path explicitly expects this fork
  • Browser code must satisfy a dependency that imports Node stream classes and changing that dependency is outside your control
  • You need readable-stream 3 semantics specifically, including Readable.from, async iteration, pipeline, and finished
Skip it if

Setup reality

Installation is a plain npm install, with no native build, credentials, or configuration file. The surprise is that this package is rarely a direct replacement you import deliberately. It exists so a Vite dependency graph that expects readable-stream can be redirected to a circular-dependency-free fork, often through vite-plugin-shim-react-pdf or an alias in Vite's resolve configuration. The package is CommonJS, has no bundled TypeScript declarations, and depends on inherits, string_decoder, and util-deprecate. Its browser map disables util and worker_threads and swaps several internal modules, so compatibility is intentionally narrower than running Node itself. The public surface follows readable-stream 3, including callback-based pipeline and finished rather than the newer promise helpers from node:stream/promises. It also buffers according to Node stream highWaterMark rules, which can surprise browser developers expecting WHATWG streams. Do not mix Node streams and native Web Streams as if they were the same objects; conversion helpers from modern Node are not part of this fork. If the original Vite failure disappears after upgrading the problem dependency, remove this shim instead of making it permanent infrastructure.

Patterns

Import the CommonJS stream classesimport-stream-classes

const { Readable, Writable, Transform, PassThrough } = require('vite-compatible-readable-stream');

Version 3.6.1 is CommonJS. In ESM projects, test your bundler's CommonJS interop rather than assuming named imports work identically everywhere.

Create a custom readable streamcreate-readable

const { Readable } = require('vite-compatible-readable-stream');

const source = new Readable({
  read() {
    this.push('first\n');
    this.push('second\n');
    this.push(null);
  },
});

push(null) signals end of stream. _read can be called more than once, so real producers need state that prevents duplicate chunks.

Build a readable from an iterableread-from-iterable

const { Readable } = require('vite-compatible-readable-stream');

const source = Readable.from(['alpha', 'beta', 'gamma']);

Readable.from is present in this fork, but browser behavior comes from its substituted from-browser module and should be tested with your target build.

Consume chunks in flowing modeconsume-data-events

source.setEncoding('utf8');
source.on('data', (chunk) => console.log(chunk));
source.on('end', () => console.log('done'));
source.on('error', (err) => console.error(err));

Adding a data listener switches the readable into flowing mode. Attach error handling before work starts.

Consume a readable with for awaitconsume-async-iterator

for await (const chunk of source) {
  console.log(chunk.toString());
}

Async iteration requires Symbol.asyncIterator support in the target runtime and destroys the stream when iteration exits early.

Create a writable sinkcreate-writable

const { Writable } = require('vite-compatible-readable-stream');

const sink = new Writable({
  write(chunk, encoding, callback) {
    console.log(chunk.toString());
    callback();
  },
});

Call callback exactly once for every chunk. Delaying it is how a writable applies backpressure.

Transform chunkscreate-transform

const { Transform } = require('vite-compatible-readable-stream');

const upper = new Transform({
  transform(chunk, encoding, callback) {
    callback(null, chunk.toString().toUpperCase());
  },
});

Pass an error as the first callback argument to fail the stream; thrown async errors are not converted automatically.

Process JavaScript values in object modeuse-object-mode

const { Transform } = require('vite-compatible-readable-stream');

const pickId = new Transform({
  objectMode: true,
  transform(user, encoding, callback) {
    callback(null, user.id);
  },
});

Object mode counts buffered objects rather than bytes, and its default highWaterMark differs from byte streams.

Pipe a source through a transformpipe-streams

source
  .pipe(upper)
  .pipe(sink);

pipe manages backpressure, but a destination error does not reliably tear down every stream. Use pipeline for multi-stage production work.

Connect streams with cleanuppipeline-with-callback

const { pipeline } = require('vite-compatible-readable-stream');

pipeline(source, upper, sink, (err) => {
  if (err) console.error('pipeline failed', err);
  else console.log('pipeline complete');
});

This package exports the callback form. It does not include node:stream/promises, so omitting the callback is not a promise API.

Observe stream completionwait-for-finish

const { finished } = require('vite-compatible-readable-stream');

finished(sink, (err) => {
  if (err) console.error(err);
  else console.log('sink closed cleanly');
});

finished reports premature close and errors as well as normal completion; keep the cleanup function it returns if the observer may be cancelled.

Stop a stream with an errordestroy-on-error

const err = new Error('input rejected');
source.destroy(err);

source.on('error', (cause) => {
  console.error(cause.message);
});

An error passed to destroy is emitted asynchronously. Without an error listener, it can become an uncaught exception.

Alternatives

PackageRegistryPick it when
readable-streamnpmYou need the maintained userland mirror of Node streams and your bundler handles its module graph correctly
stream-browserifynpmA browser bundle needs the conventional Browserify shim for Node's stream module
web-streams-polyfillnpmYou want WHATWG Web Streams semantics on browsers or runtimes that lack them
vite-plugin-node-polyfillsnpmA Vite app needs several Node core shims, not just a readable-stream workaround