Transforms styleName
to className
using compile time CSS module resolution.
In contrast to react-css-modules
, babel-plugin-react-css-modules
has a loot smaller performance overhead (0-10% vs +50%; see Performance) and a lot smaller size footprint (less than 2kb vs 17kb reaact-css-modules + lodash dependency).
- Background
- Performance
- How does it work?
- Conventions
- Configuration
- Example transpilations
- Limitations
- Have a question or want to suggest an improvement?
react-css-modules
introduced a convention of using styleName
attribute to reference CSS module. react-css-modules
is a higher-order React component. It is using the styleName
value to construct the className
at the run-time. This abstraction frees a developer from needing to reference the imported styles object when using CSS modules (What's the problem?). However, this approach has a measurable performance penalty at the cost of better developer experience (DX).
babel-plugin-react-css-modules
solves the DX problem without impacting the performance.
The important metric here is "Difference from base" (DFB). "base" is defined as using React with hardcoded className
values. The lesser the DFB value, the bigger the performance impact.
Note: This benchmark suite does not include a scenario when
babel-plugin-react-css-modules
can statically construct the value ofclassName
. If a literal value of theclassName
is constructed at the compile time, the performance is equal to the base benchmark.
Name | Operations per second (relative margin of error) | Sample size | Difference from the base benchmark |
---|---|---|---|
Using className (base) |
9551 (±1.47%) | 587 | -0% |
react-css-modules |
5914 (±2.01%) | 363 | -61% |
babel-plugin-react-css-modules (runtime, anonymous) |
9145 (±1.94%) | 540 | -4% |
babel-plugin-react-css-modules (runtime, named) |
8786 (±1.59%) | 527 | -8% |
Platform info:
- Darwin 16.1.0 x64
- Node.JS 7.1.0
- V8 5.4.500.36
- NODE_ENV=production
- Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz × 8
View the ./benchmark.
Run the benchmark:
git clone git@github.com:gajus/babel-plugin-react-css-modules.git
cd ./babel-plugin-react-css-modules
npm install
npm run build
cd ./benchmark
npm install
NODE_ENV=production ./test
- Builds index of all stylesheet imports per file.
- Uses postcss to parse the matching CSS files.
- Iterates through all JSX element declarations.
- Uses the
styleName
value to resolve the generated CSS class name of the CSS module.
- If
styleName
value is a string literal, generates a string literal value. - If
styleName
value is non-string (variable, condition, etc.), uses a helper function to constructclassName
value at the runtime.
- Removes the
styleName
attribute from the element. - Appends the resulting
className
to the existingclassName
value (or createsclassName
attribute if one does not exist).
Name | Description | Default |
---|---|---|
generateScopedName |
Refer to Generating scoped names | N/A (delegates default resolution to postcss-modules) |
Missing a configuration? Raise an issue.
Named reference is used to refer to a specific stylesheet import.
Format: [name of the import].[CSS module name]
.
Example:
import foo from './foo1.css';
import bar from './bar1.css';
// Imports "a" CSS module from ./foo1.css.
<div styleName="foo.a"></div>;
// Imports "a" CSS module from ./bar1.css.
<div styleName="bar.a"></div>;
When styleName
is a literal string value, babel-plugin-react-css-modules
resolves the value of className
at the compile time.
Input:
import './bar.css';
<div styleName="a"></div>;
Output:
import './bar.css';
<div className="bar___a"></div>;
When file imports multiple stylesheets, you must use a named reference.
Input:
import foo from './foo1.css';
import bar from './bar1.css';
<div styleName="foo.a"></div>;
<div styleName="bar.a"></div>;
Output:
import foo from './foo1.css';
import bar from './bar1.css';
<div className="foo___a"></div>;
<div className="bar___a"></div>;
When the value of styleName
cannot be determined at the compile time, babel-plugin-react-css-modules
inlines all possible styles into the file. It then uses getClassName
helper function to resolve the styleName
value at the runtime.
Input:
import './bar.css';
<div styleName={Math.random() > .5 ? 'a' : 'b'}></div>;
Output:
import _getClassName from 'babel-plugin-react-css-modules/dist/browser/getClassName';
import foo from './bar.css';
const _styleModuleImportMap = {
foo: {
a: 'bar__a',
b: 'bar__b'
}
};
<div styleName={_getClassName(Math.random() > .5 ? 'a' : 'b', _styleModuleImportMap)}></div>;
- Have a technical questions? Ask on Stack Overflow.
- Have a feature suggestion or want to report an issue? Raise an issues.
- Want to say hello to other
babel-plugin-react-css-modules
users? Chat on Gitter.