PostCSS plugin to rebase, inline, or copy assets from url() declarations with support for multiple transformation modes and advanced filtering options.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
PostCSS URL provides four distinct processing modes for transforming CSS url() declarations: rebase, inline, copy, and custom. Each mode optimizes assets differently based on deployment needs and performance requirements.
Adjusts relative URLs based on the difference between source and target file locations. This is the default mode when no options are specified.
/**
* Rebase mode configuration
* @param {RebaseOptions} options - Rebase-specific options
*/
interface RebaseOptions {
url: 'rebase';
/** Optional assets path for URL adjustment */
assetsPath?: string;
}Usage Example:
const postcss = require('postcss');
const postcssUrl = require('postcss-url');
// Rebase URLs based on file locations
const result = await postcss()
.use(postcssUrl({
url: 'rebase'
}))
.process(css, {
from: 'src/styles/components/button.css',
to: 'dist/styles/main.css'
});
// Before: background: url('../images/icon.png');
// After: background: url('../src/styles/images/icon.png');With Assets Path:
// Rebase with custom assets directory
const result = await postcss()
.use(postcssUrl({
url: 'rebase',
assetsPath: 'static/assets'
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });Converts asset files to data URIs (base64 or URI-encoded) and embeds them directly in the CSS. Ideal for small assets to reduce HTTP requests.
/**
* Inline mode configuration
* @param {InlineOptions} options - Inline-specific options
*/
interface InlineOptions {
url: 'inline';
/** Base path(s) to search for assets */
basePath?: string | string[];
/** Encoding type for data URI */
encodeType?: 'base64' | 'encodeURI' | 'encodeURIComponent';
/** Maximum file size in KB to inline */
maxSize?: number;
/** Fallback mode when file exceeds maxSize */
fallback?: 'copy' | 'rebase' | ((asset: Asset, dir: Dir, options: any) => string);
/** Include URI fragment in data URI */
includeUriFragment?: boolean;
/** Suppress SVG fragment warnings */
ignoreFragmentWarning?: boolean;
/** Optimize SVG encoding for better compression */
optimizeSvgEncode?: boolean;
}Basic Inline Example:
// Inline all assets as data URIs
const result = await postcss()
.use(postcssUrl({
url: 'inline'
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// Before: background: url('./icon.png');
// After: background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...');Advanced Inline Example:
// Inline with size limits and fallback
const result = await postcss()
.use(postcssUrl({
url: 'inline',
maxSize: 10, // 10KB limit
fallback: 'copy', // Copy large files
encodeType: 'base64', // Use base64 encoding
basePath: ['src/assets', 'node_modules/icons']
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });SVG Optimization Example:
// Optimized SVG inlining
const result = await postcss()
.use(postcssUrl({
url: 'inline',
encodeType: 'encodeURIComponent',
optimizeSvgEncode: true, // Optimize SVG encoding
ignoreFragmentWarning: true // Suppress fragment warnings
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// SVG files are URI-encoded with optimizations
// Before: background: url('./icon.svg');
// After: background: url('data:image/svg+xml,%3Csvg xmlns%3D...');MIME Type Detection:
The inline mode automatically detects file types using the mime package and applies appropriate encoding:
// Automatic MIME type detection and encoding selection
const result = await postcss()
.use(postcssUrl({
url: 'inline'
// SVG files automatically use 'encodeURIComponent'
// Other files automatically use 'base64'
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// PNG: data:image/png;base64,iVBORw0KGgoAAAANSUh...
// SVG: data:image/svg+xml,%3Csvg xmlns%3D%22http...
// JPEG: data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...Copies asset files to a specified directory and updates URLs to point to the copied files. Supports hash-based renaming for cache busting.
/**
* Copy mode configuration
* @param {CopyOptions} options - Copy-specific options
*/
interface CopyOptions {
url: 'copy';
/** Directory to copy assets (relative to 'to' option or absolute) */
assetsPath: string;
/** Base path(s) to search for assets */
basePath?: string | string[];
/** Use content hash for filenames */
useHash?: boolean;
/** Hash generation options */
hashOptions?: HashOptions;
}
interface HashOptions {
/** Hash algorithm or custom function */
method?: 'xxhash32' | 'xxhash64' | string | ((content: Buffer) => string);
/** Number of characters to keep from hash */
shrink?: number;
/** Prepend original filename to hash */
append?: boolean;
}
// Default hash options
const defaultHashOptions = {
method: 'xxhash32',
shrink: 8,
append: false
};Basic Copy Example:
// Copy assets to specified directory
const result = await postcss()
.use(postcssUrl({
url: 'copy',
assetsPath: 'static/images'
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// Before: background: url('./icon.png');
// After: background: url('static/images/icon.png');
// File copied: dist/static/images/icon.pngHash-based Copy Example:
// Copy with hash-based filenames
const result = await postcss()
.use(postcssUrl({
url: 'copy',
assetsPath: 'assets',
useHash: true,
hashOptions: {
method: 'xxhash32',
shrink: 8,
append: true // Prepend original filename
}
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// Before: background: url('./icon.png');
// After: background: url('assets/icon_a1b2c3d4.png');
// File copied: dist/assets/icon_a1b2c3d4.pngCrypto Hash Support:
The plugin supports Node.js crypto module hash algorithms as well as xxhash:
// Using crypto hash algorithms
const result = await postcss()
.use(postcssUrl({
url: 'copy',
assetsPath: 'assets',
useHash: true,
hashOptions: {
method: 'sha256', // Any Node.js crypto hash: md5, sha1, sha256, etc.
shrink: 16, // Keep first 16 characters
append: false
}
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// Before: background: url('./icon.png');
// After: background: url('assets/9f86d081884c7d65.png');Allows custom transformation functions for advanced URL processing scenarios like CDN integration or dynamic path generation.
/**
* Custom mode configuration
* @param {CustomOptions} options - Custom function options
*/
interface CustomOptions {
url: (asset: Asset, dir: Dir, options: CustomOptions, decl: any, warn: Function, result: any, addDependency: Function) => string | Promise<string>;
/** Allow processing with subsequent options */
multi?: boolean;
/** Custom option properties */
[key: string]: any;
}
interface CustomFunctionParameters {
/** Asset information object */
asset: Asset;
/** Directory information object */
dir: Dir;
/** Current option configuration */
options: CustomOptions;
/** PostCSS declaration object */
decl: any;
/** Warning function for reporting issues */
warn: (message: string) => void;
/** PostCSS result object */
result: any;
/** Function to add file dependencies */
addDependency: (filePath: string) => void;
}CDN Transform Example:
// Transform URLs to CDN paths
const result = await postcss()
.use(postcssUrl({
url: (asset, dir, options) => {
if (asset.url.startsWith('/images/')) {
return `https://cdn.example.com${asset.url}`;
}
return asset.url; // Return unchanged
}
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
// Before: background: url('/images/hero.jpg');
// After: background: url('https://cdn.example.com/images/hero.jpg');Multi-processing Example:
// Custom function with multi-option processing
const result = await postcss()
.use(postcssUrl([
{
url: (asset, dir, options, decl, warn) => {
// Log all processed assets
console.log(`Processing: ${asset.url}`);
return asset.url; // Pass through unchanged
},
multi: true // Allow subsequent processing
},
{
url: 'copy',
assetsPath: 'assets'
}
]))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });Async Custom Function Example:
// Async custom transformation
const result = await postcss()
.use(postcssUrl({
url: async (asset, dir, options) => {
// Async processing (e.g., API calls, file system operations)
const optimizedUrl = await optimizeAssetUrl(asset.url);
return optimizedUrl;
}
}))
.process(css, { from: 'src/main.css', to: 'dist/main.css' });
async function optimizeAssetUrl(url) {
// Custom async logic
return url;
}The plugin automatically selects the appropriate processing mode based on configuration and provides fallback handling for error conditions.
interface ModeSelection {
/** Default mode when no options specified */
default: 'rebase';
/** Available built-in modes */
modes: ['rebase', 'inline', 'copy'];
/** Custom function detection */
custom: 'typeof options.url === "function"';
/** Error handling for invalid modes */
validation: 'throws Error for unknown modes';
}Install with Tessl CLI
npx tessl i tessl/npm-postcss-url