Security News
GitHub Removes Malicious Pull Requests Targeting Open Source Repositories
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Give some fresh air to your production HTML, JS and CSS! Breezify is a library that replaces class names in your build files with shorter ones.
Works with most frameworks. Next.js is now supported!
If you like the project and want to support it, you can donate to the author:
npm i -g breezify
breezify init
in your project folder to create a config file{ "build": "your-build-command && breezify do" }
breezify do -h
for the list of optionsCommonJS:
const breezify = require('breezify');
breezify(options);
ESM:
import breezify from 'breezify';
breezify(options);
Initialize the plugin in your next.config.js
:
const { BreezifyWebpack5Plugin } = require("breezify");
module.exports = {
webpack: (config) => {
config.plugins.push(new BreezifyWebpack5Plugin());
return config;
},
}
You can pass options to the plugin:
new BreezifyWebpack5Plugin({
css: {
prefix: "tw-",
},
});
Long class names are great for development, but they can make your production files unnecessarily large. Replacing class names with shorter ones can reduce the file sizes and improve performance.
Breezify turns this:
<div class="w-full max-w-content px-6 md:px-9 grid mx-auto z-[1] relative gap-x-6 md:gap-x-10 gap-y-6 md:gap-y-10 grid-cols-1 md:grid-cols-2 justify-items-start items-start">
<a
href="#"
class="gap-2 items-center mb-10 transition-all text-theme-text-interactive dark:text-dark-text-interactive group-hover:text-theme-text-interactive-hover hover:text-theme-text-interactive-hover dark:hover:text-dark-text-interactive-hover dark:group-hover:text-dark-text-interactive-hover"
>
Carts
</a>
</div>
into this:
<div class="a b c d e f g h i j k l m n o p">
<a href="#" class="q r s t u v y z A B">
Carts
</a>
</div>
439 characters of class names reduced to 50 characters! (89% less)
Breezify uses AST tree parsing and manipulations for JS and CSS to carefully transform the code, so in JS it turns this:
const mySpecialClass = "primary-color";
const decorated = "decorated";
const header = document.querySelector(
`.header[role='decorated']:not(.decorated) .aside, ${decorated}, aside > .aside, ${mySpecialClass}`,
);
into this:
const mySpecialClass = "a";
const decorated = "b";
const header = document.querySelector(
`.c[role='decorated']:not(.b) .d, ${decorated}, aside > .d, ${mySpecialClass}`,
);
In CSS, it turns this:
.focus\:border-\[blue-500\]:focus {
border-color: #4299e1;
}
.group:hover .group-hover\:text-\[blue-400\] {
color: #63b3ed;
}
into this:
.a:focus {
border-color: #4299e1;
}
.b:hover .c {
color: #63b3ed;
}
It also works with inline scripts and styles, and it's customizable to fit your needs.
Every byte counts – money, load times, performance, and user experience.
In case of code in most cases there is no much difference between your class name and any other string. So when Breezify replaces your class name with a new one there is a possibility of replacing the wrong value which can cause a bug.
The best way to run Breezify without any issues is to prefix your class names with a unique prefix, like tw-
for Tailwind CSS. You can also use includeClassPatterns
and ignoreClassPatterns
options to include or ignore class names by patterns.
{
css: {
includeClassPatterns: ["^tw-"],
ignoreClassPatterns: ["^ProseMirror"],
}
}
To make it easier to find and fix bugs, you can add a prefix to the class names in the config file. When you see a bug, you can find this place in the code and replace a conflicting class name with a safe one in your source files. After that you can remove the prefix.
{
css: {
prefix: "breezify-",
}
}
If you have a problem with JS, you can use skip rules to ignore certain nodes when replacing the class names. See ESTree, Acorn, and example skip rules.
Example:
/**
* Skip local storage methods
* @param node {AnyNode} - AST node
* @param ancestors {AnyNode[]} - Ancestors of the AST node
*/
function skipLocalStorageMethods(
node: AnyNode,
ancestors: AnyNode[],
): boolean {
return (
ancestors[ancestors.length - 2]?.callee?.object?.name === "localStorage"
);
}
const options: BreezifyOptions = {
js: {
skipRules: [skipLocalStorageMethods],
}
}
This will ignore class names in the localStorage
methods, for example, in this case:
localStorage.setItem("favoriteClassName", "myClassName");
Options for configuring Breezify.
config
(string): The path to the Breezify config file.ignoreConfig
(boolean): Whether to ignore the config file.files
(FilesOptions): Configuration options for file handling.css
(CSSOptions): Configuration options for CSS processing.js
(JSOptions): Configuration options for JavaScript processing.html
(HTMLOptions): Configuration options for HTML processing.Options related to file handling.
buildDir
(string): The directory where the files are located. Default: "dist"
.outputDir
(string | undefined): The directory where the files should be outputted.pattern
(string): The pattern to match files relative to the build folder. Default: "**/*.{css,js,html}"
. See glob for pattern syntax.ignore
(string[]): The RegExp patterns to ignore. Use as strings, without modifiers. Example: ["^node_modules/"]
.Options for CSS processing.
includeClassPatterns
(string[] | undefined): The RegExp patterns to include. Example: ["^tw-"]
for class names with "tw-" prefix.ignoreClassPatterns
(string[] | undefined): The RegExp patterns to ignore. Use as strings, without modifiers. Example: ["^ProseMirror"]
for class names with "ProseMirror" prefix.shuffle
(boolean | undefined): Whether to shuffle class names. Default: true
.prefix
(string | undefined): The prefix to add to the class names.minify
(boolean | undefined): Whether to minify the output CSS. Default: true
.extractClassesFromHtml
(boolean | undefined): Whether to extract class names from tags found in HTML files. Default: true.restructure
(boolean | undefined): Whether to restructure the output CSS with CSSO for more efficient minification. Can break your styles! Default: false
.forceMediaMerge
(boolean | undefined): Whether to force merging media queries with CSSO for more efficient minification. Can break your styles! Default: false
.Options for JavaScript processing.
ignoreStringPatterns
(string[] | undefined): The RegExp patterns to ignore when replacing class names in strings in JS files. Use as strings, without modifiers. Example: ["^%s"]
.skipRules
(SkipRule[] | undefined): Skip rules to ignore certain nodes. See ESTree, Acorn, and example skip rules.mode
("acorn" | "simple" | undefined): The mode to use for parsing JS files. Default: "acorn"
.minify
(boolean | undefined): Whether to minify the output JS. Default: true
.minifyInlineJS
(boolean | undefined): Whether to minify inline JS (inside HTML files). Default: true
.Options for HTML processing.
attributes
(string[]): The attributes you use for class names in HTML files. You may want to include some data attributes in addition to default. Default: ["class"]
.beautify
(boolean | PrettyOptions | undefined): Whether to beautify the output HTML.minify
(boolean | Options | undefined): Whether to minify the output HTML. If true
, minifyHtmlDefaultOptions
will be used. See html-minifier.const options: BreezifyOptions = {
files: {
buildDir: "dist",
pattern: "**/*.{css,js,html}",
ignore: [],
},
css: {
minify: true,
extractClassesFromHtml: true,
},
js: {
mode: "acorn",
minify: true,
},
html: {
attributes: ["class"],
minify: true,
},
}
This project is licensed under the MIT License - see the LICENSE file for details.
I appreciate any help with the project!
Please read CONTRIBUTING.md and CODE_OF_CONDUCT.md for details.
FAQs
A tool for minifying CSS class names
The npm package breezify receives a total of 1 weekly downloads. As such, breezify popularity was classified as not popular.
We found that breezify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.