dynamic-css-plugin
v2.2.1
Published
Vite / Webpack - plugin to transform dynamic css class names on-the-fly
Maintainers
Readme
Dynamic CSS Plugin
Patch. Inject. Transform.
"btn-primary btn-primary-disabled" ==> .app_Xscyf.app_LfRuA
Supported frameworks:
Advantages:
- 👌 Prevent conflicts with third party CSS
- ❤️🔥 Smaller bundle size
- 💥 Obfuscate class names
How it works:
- Patch into the framework's DOM rendering setAttribute method to intercept class names as they are applied to elements
- Inject a custom setAttribute method into the bundle that runs the transformation logic
- Transform class names at run-time and cooresponding CSS at build-time
Getting Started
Install
npm install dynamic-css-plugin -DVite
vite.config.js
Import into Vite config
import dynamicCssPlugin from "dynamic-css-plugin/vite";Add to Vite plugins
plugins: [
dynamicCssPlugin({
transform: "app_[md4:hash:base64:5]"
})
];Webpack
webpack.config.js
Import into Webpack config
import DynamicCssPlugin from "dynamic-css-plugin/webpack";Add to Webpack plugins
plugins: [
new DynamicCssPlugin({
transform: "app_[md4:hash:base64:5]"
})
];Options
enabled: true- If false, the plugin will not runscope: ""- Applies a scope to the injected method. Useful if multiple instances are on the same page such as with micro-frontendsdebug: false- Enables debug logging
Transform
transform: "[md4:hash:base64:5]"- The transform template or config objecttransform: {}- The transform config objecttransform.template: "[md4:hash:base64:5]"- The format of transformed class names- "prefix_[{algorithm}:hash:{encoding}:{length}]"
transform.attributes: /^(class)$/- Regex for HTML attributes to transformtransform.ignoreTags: /(path)/i- Regex for HTML tags to ignoretransform.ignoreValues: /^(css|sc|icon)-/i- Regex for HTML attribute values to ignoretransform.ignoreFiles: /\.notransform\.(css|scss)$/i- Regex for files to ignore
Inject
inject: {}- The injection configinject.entryPoint: undefinedThe entry point for the injected method in the bundle, if undefined the first entry is usedinject.src: "./src/inject/index.js"The code to apply options and generate the file to injectinject.file: "./src/inject/index_generated.js"The code to inject
Patch
patch: PatchReactDom- The patch functionimport PatchReactDom from "dynamic-css-plugin/patch/react-dom";Patch method signature:
function PatchReactDom(scope = "") { return { test: /react-dom/, search: /(\w+)\.setAttribute\(/g, replace: `globalThis['${scope}setAttributeDynamic'].call($1,` }; }
Notes
ignoreValues default excludes class names with the following prefixes that are commonly generated by other libraries and should not be transformed
- css- which is the emotion default
- sc- which is the styled-components default
- icon- which is the the standard for icon classes
Limitations
Since we are only patching calls to "setAttribute" inside react-dom that means if a class is applied a different way such as with vanilla JS or using classList the transform will not apply. This is largely ok since these patterns don’t necessarily follow the "react way of doing things". However if you do need to support these patterns you can use the injected method directly.
For example:
import DynamicCss from "dynamic-css-plugin";
document.body.classList.add(DynamicCss("theme-light"));To avoid issues, the plugin supports options to ignore specific tags and values. Additionally the plugin does not transform ids, this is done purposely so that tests and analytics can still reliably target elements.
