CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-gulp-changed

Gulp plugin that optimizes build processes by only passing through files that have been modified since the last build

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

gulp-changed

gulp-changed is a Gulp plugin that optimizes build processes by only passing through files that have been modified since the last build. It offers multiple comparison strategies including modification time checking and content-based comparison, with built-in comparators for common use cases and support for custom comparison functions.

Package Information

  • Package Name: gulp-changed
  • Package Type: npm
  • Language: JavaScript (ES Module)
  • Installation: npm install --save-dev gulp-changed

Core Imports

import gulpChanged, { compareLastModifiedTime, compareContents } from 'gulp-changed';

Basic Usage

import gulp from 'gulp';
import gulpChanged from 'gulp-changed';
import ngAnnotate from 'gulp-ng-annotate'; // Example processor

const SOURCE = 'src/*.js';
const DESTINATION = 'dist';

export default function build() {
  return gulp.src(SOURCE)
    .pipe(gulpChanged(DESTINATION))
    // ngAnnotate will only get the files that
    // changed since the last time it was run
    .pipe(ngAnnotate())
    .pipe(gulp.dest(DESTINATION));
}

Capabilities

Main Plugin Function

Creates a Gulp transform stream that filters out unchanged files based on comparison with destination files.

/**
 * Create a gulp plugin that only passes through changed files
 * @param destination - Destination directory path or function returning destination path
 * @param options - Configuration options for comparison behavior
 * @returns Transform stream for use in gulp pipeline
 */
function gulpChanged(destination: string | ((file: Vinyl) => string), options?: ChangedOptions): Transform;

interface ChangedOptions {
  /** Working directory the folder is relative to (default: process.cwd()) */
  cwd?: string;
  /** Function that determines whether the source file is different from the destination file */
  hasChanged?: (sourceFile: Vinyl, targetPath: string) => Promise<Vinyl | undefined>;
  /** Extension of the destination files (useful if different from source) */
  extension?: string;
  /** Function to transform the path to the destination file */
  transformPath?: (newPath: string) => string;
}

Usage Examples:

// Basic usage with destination directory
gulp.src('src/**/*.js')
  .pipe(gulpChanged('dist'))
  .pipe(babel())
  .pipe(gulp.dest('dist'));

// With different file extension
gulp.src('src/**/*.jade')
  .pipe(gulpChanged('app', {extension: '.html'}))
  .pipe(jade())
  .pipe(gulp.dest('app'));

// With custom path transformation
gulp.src('src/content/*.md')
  .pipe(gulpChanged('dist', {
    transformPath: (newPath) => path.join(
      path.dirname(newPath), 
      path.basename(newPath, '.md'), 
      'index.html'
    )
  }))
  .pipe(marked())
  .pipe(gulp.dest('dist'));

// With function-based destination
gulp.src('src/**/*.js')
  .pipe(gulpChanged((file) => `dist/${file.relative.split('/')[0]}`))
  .pipe(babel())
  .pipe(gulp.dest('dist'));

Last Modified Time Comparator

Built-in comparator that compares files based on modification time. This is the default comparison method.

/**
 * Compare files based on modification time
 * @param sourceFile - Source vinyl file object with stat information
 * @param targetPath - Absolute path to target file for comparison
 * @returns Promise resolving to sourceFile if changed, undefined if not
 */
async function compareLastModifiedTime(sourceFile: Vinyl, targetPath: string): Promise<Vinyl | undefined>;

Usage Example:

// Explicitly use modification time comparison (this is the default)
gulp.src('src/**/*.js')
  .pipe(gulpChanged('dist', {hasChanged: compareLastModifiedTime}))
  .pipe(babel())
  .pipe(gulp.dest('dist'));

Content-Based Comparator

Built-in comparator that compares files based on actual content differences rather than modification time.

/**
 * Compare files based on content differences
 * @param sourceFile - Source vinyl file object with contents buffer
 * @param targetPath - Absolute path to target file for comparison
 * @returns Promise resolving to sourceFile if changed, undefined if not
 */
async function compareContents(sourceFile: Vinyl, targetPath: string): Promise<Vinyl | undefined>;

Usage Example:

// Use content-based comparison for more accurate change detection
gulp.src('src/**/*.js')
  .pipe(gulpChanged('dist', {hasChanged: compareContents}))
  .pipe(babel())
  .pipe(gulp.dest('dist'));

Types

// Vinyl file object (from vinyl package)
interface Vinyl {
  /** Current working directory */
  cwd: string;
  /** Base directory for relative paths */
  base: string;
  /** Full file path */
  path: string;
  /** Relative file path from base */
  relative: string;
  /** File contents as Buffer or Stream */
  contents: Buffer | Stream | null;
  /** File system stat object */
  stat?: {
    /** Modification time in milliseconds */
    mtimeMs: number;
    [key: string]: any;
  };
}

// Transform stream (from Node.js streams)
interface Transform extends Stream.Transform {
  /** Write a file to the stream */
  write(file: Vinyl): boolean;
  /** End the stream */
  end(): void;
  /** Event emitted when stream ends */
  on(event: 'end', callback: () => void): this;
  /** Event emitted for each file passing through */
  on(event: 'data', callback: (file: Vinyl) => void): this;
}

Error Handling

The plugin handles several error conditions:

  • Missing destination: Throws Error('gulp-changed: \dest` required')` if no destination is provided
  • Invalid transformPath: Throws Error('gulp-changed: \options.transformPath` needs to be a function')` if transformPath is not a function
  • Invalid transformPath return: Throws TypeError('\options.transformPath` needs to return a string')` if transformPath doesn't return a string
  • File system errors: Gracefully handles ENOENT errors (file doesn't exist in destination) by passing the file through
  • Other file system errors: Re-throws other file system errors for proper error handling

Advanced Usage Patterns

Custom Comparator Function

You can provide a custom comparator function for specialized comparison logic:

function customComparator(sourceFile, targetPath) {
  // Custom logic here - must return Promise<Vinyl | undefined>
  // Return sourceFile if it should be processed, undefined if not
  return Promise.resolve(sourceFile);
}

gulp.src('src/**/*.js')
  .pipe(gulpChanged('dist', {hasChanged: customComparator}))
  .pipe(babel())
  .pipe(gulp.dest('dist'));

Working Directory Configuration

Configure the working directory for relative path resolution:

gulp.src('src/**/*.js')
  .pipe(gulpChanged('dist', {
    cwd: '/custom/working/directory'
  }))
  .pipe(babel())
  .pipe(gulp.dest('dist'));

docs

index.md

tile.json