vinyl-contents
vinyl-contents is a specialized utility designed to asynchronously read and normalize the content of a Vinyl file object, a fundamental data structure within the Gulp.js build system. It adeptly handles Vinyl files where the `contents` property can be a Buffer, a Node.js Stream, or `null`. For Buffer contents, it returns them directly. For Stream contents, it buffers the entire stream into a `BufferList` and returns it as a single Buffer, while empty contents (e.g., `file.isNull()`) result in `undefined`. The current stable version is `2.0.0`. As part of the Gulp.js organization, its release cadence prioritizes stability and ecosystem compatibility over rapid feature iteration. A key differentiator is its focused handling of `Vinyl` file types, simplifying content access for downstream processes that expect string or buffer input, though it includes a crucial warning against processing very large streaming files due to its in-memory buffering approach.
Common errors
-
TypeError: The first argument must be a Vinyl file.
cause The `vinylContents` function was called with an argument that is not a valid `Vinyl` file instance (e.g., `null`, `undefined`, or a plain object).fixEnsure that the first argument passed to `vinylContents` is always an instance of `Vinyl` from the `vinyl` package. -
ERR_REQUIRE_ESM or 'require() of ES Module ...' when attempting to use 'require('vinyl-contents')' in an ES Module context.cause You are attempting to use CommonJS `require()` syntax within a JavaScript file that is being treated as an ES Module (e.g., `"type": "module"` in `package.json` or `.mjs` extension).fixUse the ES Module import syntax: `import vinylContents from 'vinyl-contents';` -
Maximum call stack size exceeded / JavaScript heap out of memory
cause Processing extremely large streaming Vinyl files with `vinyl-contents` causes the entire file to be buffered into memory, exceeding available heap space.fixRefactor your pipeline to avoid buffering very large files into memory. If `vinyl-contents` must be used, increase Node.js's memory limit (e.g., `node --max-old-space-size=4096 script.js`) or process files in smaller chunks (if the downstream consumer supports it) or switch to a stream-based approach for large files.
Warnings
- breaking Version 2.0.0 drops support for Node.js versions older than 10.13.0. Running on unsupported versions will likely lead to errors.
- breaking The internal streaming implementation was changed from `readable-stream` to `bl` (BufferList) in v2.0.0. While this is an internal change, it could potentially affect users who relied on specific behaviors or stream types from the previous implementation, or lead to unexpected interactions with highly customized stream pipelines.
- gotcha When `vinyl-contents` processes a Vinyl file with streaming contents, it buffers the entire stream into memory before returning it as a Buffer. This can lead to significant memory consumption and performance issues if processing very large files, potentially causing your application to crash or become unresponsive.
Install
-
npm install vinyl-contents -
yarn add vinyl-contents -
pnpm add vinyl-contents
Imports
- vinylContents
import { vinylContents } from 'vinyl-contents';import vinylContents from 'vinyl-contents';
- vinylContents
const vinylContents = require('vinyl-contents'); - type VinylContentsCallback
import vinylContents, { type VinylContentsCallback } from 'vinyl-contents';
Quickstart
const { Transform } = require('streamx');
const pug = require('pug');
const vinylContents = require('vinyl-contents');
const Vinyl = require('vinyl');
const stream = require('stream');
// A naive Gulp-like plugin to demonstrate vinyl-contents usage
function gulpPug(options) {
return new Transform({
transform: function (file, cb) {
// Pass through null files or non-Vinyl objects
if (!Vinyl.isVinyl(file) || file.isNull()) {
return cb(null, file);
}
vinylContents(file, function (err, contents) {
if (err) {
return cb(err);
}
if (contents === undefined) {
// File was empty after processing
return cb(null, file);
}
try {
// Compile the contents (which is now a Buffer) to a string
const compiledHtml = pug.compile(contents.toString(), options)();
file.contents = Buffer.from(compiledHtml);
cb(null, file);
} catch (compileErr) {
cb(compileErr);
}
});
},
});
}
// Example usage:
const pugPlugin = gulpPug();
// Create a dummy vinyl file with streaming content
const sourceStream = new stream.Readable({
read() {
this.push('h1 Hello from Stream, #{name}');
this.push(null);
}
});
const fileWithStream = new Vinyl({
path: 'template-stream.pug',
contents: sourceStream, // This will be buffered by vinyl-contents
data: { name: 'World' }
});
// Create a dummy vinyl file with buffer content
const fileWithBuffer = new Vinyl({
path: 'template-buffer.pug',
contents: Buffer.from('p Hello from Buffer, #{name}'),
data: { name: 'Universe' }
});
// Create a dummy vinyl file with null content
const fileWithNull = new Vinyl({
path: 'template-null.pug',
contents: null
});
console.log('--- Processing files ---');
pugPlugin.on('data', (file) => {
console.log(`\nProcessed file: ${file.path}`);
console.log(`Contents type: ${file.contents ? 'Buffer' : 'null/undefined'}`);
console.log(`Output: ${file.contents ? file.contents.toString() : 'N/A'}`);
});
pugPlugin.on('error', (err) => {
console.error('Plugin error:', err);
});
pugPlugin.write(fileWithStream);
pugPlugin.write(fileWithBuffer);
pugPlugin.write(fileWithNull);
pugPlugin.end();