Plugin API for Parcel bundler - provides base classes for creating Parcel plugins including transformers, resolvers, bundlers, namers, runtimes, packagers, optimizers, compressors, reporters, and validators
67
The Compressor plugin compresses bundle outputs using various compression algorithms to reduce file sizes for network transfer. Compressors operate on the final bundle contents.
Base class for creating bundle compression plugins.
/**
* Base class for bundle compression plugins
*/
export declare class Compressor {
constructor(opts: CompressorOpts);
}
/**
* Compressor plugin configuration interface
*/
interface CompressorOpts {
/** Compress bundle contents (required) */
compress(args: {
stream: Readable;
options: PluginOptions;
logger: PluginLogger;
tracer: PluginTracer;
}): Promise<{
stream: Readable;
type?: string;
} | null>;
}Usage Example:
import { Compressor } from "@parcel/plugin";
import { createGzip, createBrotliCompress } from "zlib";
import { pipeline } from "stream/promises";
export default new Compressor({
// Compress bundle contents (required)
async compress({stream, options, logger}) {
// Only compress in production
if (options.mode !== 'production') {
return null;
}
// Use Brotli compression for better compression ratio
if (this.supportsBrotli()) {
const compressedStream = createBrotliCompress({
level: 6, // Balance between compression and speed
flush: require('zlib').constants.BROTLI_OPERATION_FLUSH
});
// Create compressed stream
const compressed = stream.pipe(compressedStream);
return {
stream: compressed,
type: 'br' // Brotli encoding
};
}
// Fallback to Gzip
const gzipStream = createGzip({
level: 6,
flush: require('zlib').constants.Z_SYNC_FLUSH
});
const compressed = stream.pipe(gzipStream);
return {
stream: compressed,
type: 'gzip'
};
},
supportsBrotli() {
// Check if Brotli is available
try {
require('zlib').createBrotliCompress;
return true;
} catch {
return false;
}
}
});/**
* Readable stream interface
*/
interface Readable {
/** Read data from stream */
read(size?: number): Buffer | string | null;
/** Pipe to another stream */
pipe<T extends Writable>(destination: T): T;
/** Add event listeners */
on(event: string, listener: Function): this;
/** Remove event listeners */
off(event: string, listener: Function): this;
}
/**
* Writable stream interface
*/
interface Writable {
/** Write data to stream */
write(chunk: any): boolean;
/** End the stream */
end(): void;
}/**
* Supported compression types
*/
type CompressionType =
| 'gzip' // Gzip compression
| 'br' // Brotli compression
| 'deflate' // Deflate compression
| 'lz4' // LZ4 compression
| 'zstd'; // Zstandard compressionimport { Compressor } from "@parcel/plugin";
import { Transform } from "stream";
export default new Compressor({
async compress({stream, options}) {
// Custom compression with size checking
let totalSize = 0;
const sizeTracker = new Transform({
transform(chunk, encoding, callback) {
totalSize += chunk.length;
callback(null, chunk);
}
});
// Track original size
const trackedStream = stream.pipe(sizeTracker);
// Choose compression based on content type and size
const compressionLevel = this.getCompressionLevel(totalSize);
const algorithm = this.chooseAlgorithm(options);
const compressor = this.createCompressor(algorithm, compressionLevel);
const compressed = trackedStream.pipe(compressor);
return {
stream: compressed,
type: algorithm
};
},
getCompressionLevel(size) {
// Higher compression for larger files
if (size > 100000) return 9; // Maximum compression
if (size > 10000) return 6; // Balanced
return 3; // Fast compression for small files
},
chooseAlgorithm(options) {
// Choose best algorithm based on environment
if (options.target?.engines?.browsers) {
return 'gzip'; // Better browser support
}
return 'br'; // Better compression for modern environments
},
createCompressor(algorithm, level) {
switch (algorithm) {
case 'br':
return createBrotliCompress({ level });
case 'gzip':
return createGzip({ level });
default:
return createGzip({ level });
}
}
});Install with Tessl CLI
npx tessl i tessl/npm-parcel--plugindocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10