css-mangle-webpack-plugin
Version:
This webpack plugin package is a CSS mangler that globally optimizes and shortens identifier names.
141 lines (121 loc) • 6.23 kB
text/typescript
import { Compiler } from "webpack";
import { CSSMinificationManglerOptions, CSSMinificationManglerTranspiler, CSSQueryManglerTranspiler, CSSVariableManglerOptions, CSSVariableManglerTranspiler, DrivenManglerTranspiler } from "../core/mangler_transpiler";
import { CSSMangleReserved } from "../types";
import { ManglerUtil } from "../utils/mangler";
import "colors";
export interface CSSMangleWebpackPluginOptions {
/**
* Whether unique identifiers in JavaScript and JSX should not be
* targets for transpilation.
*/
ignoreScript?: boolean;
/**
* This option value defines which bundle process stage of Webpack
* to proceed with optimization task.
*/
processStage?: "OPTIMIZE" | "OPTIMIZE_INLINE";
printLogs?: "ALL" | "WARNING" | "NONE";
debugLogs?: "ALL" | "TIMEOUT" | "NONE";
reserved?: CSSMangleReserved;
minify?: boolean | Partial<CSSMinificationManglerOptions>;
mangle?: boolean | {
variableName?: boolean | CSSVariableManglerOptions;
className?: boolean;
idName?: boolean;
options?: {
/**
* Whether an undeclared identifier in this webpack plugin would
* still be considered for minification.
*/
undeclared: boolean;
}
}
}
export class CSSMangleWebpackPlugin {
transpilers: DrivenManglerTranspiler<any>[] = [];
constructor(public options: CSSMangleWebpackPluginOptions) {
if (options?.minify ?? false) {
const minifyOptions = options.minify as CSSMinificationManglerOptions;
this.transpilers.push(new CSSMinificationManglerTranspiler({
rgbToHex: minifyOptions?.rgbToHex ?? true,
comments: minifyOptions?.comments ?? true,
escapeSequence: minifyOptions?.escapeSequence ?? true
}));
}
// When is not active to compress about the identifiers of CSS.
if (!(options?.mangle ?? true)) return
/** @ts-ignore */
const variableName: boolean = options?.mangle?.variableName ?? true;
/** @ts-ignore */
const className: boolean = options?.mangle?.className ?? false;
/** @ts-ignore */
const idName: boolean = options?.mangle?.idName ?? false;
/** @ts-ignore */
const canUndeclared: boolean = options?.mangle?.options?.undeclared ?? false;
// When a developer want to compress a variable names of CSS.
if (variableName === true
|| variableName["property"] != null
|| variableName["literals"] != null) {
this.transpilers.push(new CSSVariableManglerTranspiler({
reversed: [],
canUndeclared: canUndeclared,
property: variableName["property"] ?? true,
literals: variableName["literals"] ?? true
}));
}
// When a developer want to compress a class-names of CSS.
if ((className ?? false) || (idName ?? false)) {
this.transpilers.push(new CSSQueryManglerTranspiler());
}
}
apply(compiler: Compiler) {
const useMangleScript = !(this.options?.ignoreScript ?? false);
const processStage = this.options?.processStage ?? "OPTIMIZE_INLINE";
const debugLogs = this.options?.debugLogs ?? "TIMEOUT";
const reversed = this.options?.reserved ?? [];
compiler.hooks.compilation.tap("CSSMangleWebpackPlugin", (compilation) => {
compilation.hooks.processAssets.tap(
{
name: "CSSMangleWebpackPlugin",
stage: processStage == "OPTIMIZE_INLINE"
? compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE
: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE
},
(assets) => {
for (const assetName in assets) {
// When a given assets name and reversed assets names matched.
if (reversed.find(name => name == assetName)) {
return;
}
if (assetName.endsWith(".html")
|| assetName.endsWith(".js") && useMangleScript
|| assetName.endsWith(".jsx") && useMangleScript
|| assetName.endsWith(".css")) {
const startTime = performance.now();
for (const transpiler of this.transpilers) {
const source = assets[assetName].source().toString();
const result = transpiler.transform({
syntaxText: source,
syntaxType: ManglerUtil.assetTypeOf(assetName)
});
compilation.updateAsset(assetName, new compiler.webpack.sources.RawSource(result));
}
if (debugLogs == "ALL" || debugLogs == "TIMEOUT") {
const timeout = Math.round(performance.now() - startTime); // ms
const message = "is minimized by (css-mangle-webpack-plugin)";
// Notifies a developer the current asset-name and timeout to microseconds format.
console.log("asset " + assetName.green.bold + ` ${message} ` + `[${timeout}ms]`.yellow.bold);
}
}
}
if (this.options?.printLogs == "ALL" ?? false) {
this.transpilers.forEach(e => e.context.parent.forEach(m => m.printLogs()));
}
if (this.options?.printLogs == "WARNING" ?? false) {
this.transpilers.forEach(e => e.context.parent.forEach(m => m.printLogsUnused()));
}
}
);
});
}
}