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 Optimizer plugin optimizes bundled code through minification, tree shaking, and other performance improvements. Optimizers transform bundle contents to reduce file size and improve runtime performance.
Base class for creating code optimization plugins.
/**
* Base class for code optimization plugins
* @template C - Configuration type
* @template B - Bundle configuration type
*/
export declare class Optimizer<C, B> {
constructor(opts: OptimizerOpts<C, B>);
}
/**
* Optimizer plugin configuration interface
*/
interface OptimizerOpts<ConfigType, BundleConfigType> {
/** Load global configuration */
loadConfig?: (args: {
config: Config;
options: PluginOptions;
logger: PluginLogger;
tracer: PluginTracer;
}) => Promise<ConfigType>;
/** Load bundle-specific configuration */
loadBundleConfig?: (args: {
bundle: NamedBundle;
bundleGraph: BundleGraph<NamedBundle>;
config: Config;
options: PluginOptions;
logger: PluginLogger;
tracer: PluginTracer;
}) => Promise<BundleConfigType>;
/** Optimize bundle contents (required) */
optimize(args: {
bundle: NamedBundle;
contents: Blob;
map?: SourceMap;
options: PluginOptions;
logger: PluginLogger;
tracer: PluginTracer;
config: ConfigType;
bundleConfig: BundleConfigType;
getSourceMapReference: (map?: SourceMap) => Promise<string | null>;
}): Promise<BundleResult | BundleResult[]>;
}Usage Example:
import { Optimizer } from "@parcel/plugin";
import { minify } from "terser"; // Example minifier
export default new Optimizer({
// Load optimization configuration
loadConfig({config}) {
return {
minify: config.minify !== false,
mangle: config.mangle !== false,
compress: config.compress !== false,
sourceMap: config.sourceMap !== false
};
},
// Optimize bundle contents (required)
async optimize({
bundle,
contents,
map,
config,
getSourceMapReference,
options
}) {
// Only optimize in production mode
if (options.mode !== 'production') {
return { contents, map };
}
// Optimize JavaScript bundles
if (bundle.type === 'js' && config.minify) {
const code = contents.toString();
const result = await minify(code, {
mangle: config.mangle,
compress: config.compress,
sourceMap: config.sourceMap && map ? {
content: map,
filename: bundle.filePath,
url: bundle.filePath + '.map'
} : false
});
if (result.error) {
throw new Error(`Minification failed: ${result.error}`);
}
let optimizedContents = result.code;
// Add source map reference
if (result.map && config.sourceMap) {
const mapRef = await getSourceMapReference(result.map);
if (mapRef) {
optimizedContents += `\n//# sourceMappingURL=${mapRef}`;
}
}
return {
contents: optimizedContents,
map: result.map
};
}
// Optimize CSS bundles
if (bundle.type === 'css' && config.minify) {
return this.optimizeCSS(contents, map, config);
}
// Return unoptimized for other types
return { contents, map };
},
async optimizeCSS(contents, map, config) {
// CSS optimization implementation
const minified = contents.toString()
.replace(/\s+/g, ' ') // Collapse whitespace
.replace(/;\s*}/g, '}') // Remove trailing semicolons
.replace(/\s*{\s*/g, '{') // Clean braces
.replace(/\s*}\s*/g, '}')
.replace(/\s*;\s*/g, ';') // Clean semicolons
.replace(/\s*,\s*/g, ',') // Clean commas
.trim();
return {
contents: minified,
map: map // Preserve existing source map
};
}
});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