Skip to content

Commit

Permalink
Compress atomic class names (#1408)
Browse files Browse the repository at this point in the history
* Update 'ax' to accept short class name

* Update 'ax' flow type and up the size limit

* Add benchmark test to test ax(compressed class names)

* Change the format of compress class names

* Restore Flow type

* Compress class names

* Update snapshot

* chore(deps): update dependency @types/node to ^18.11.19 (#1407)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Turn off compressing class names if stylesheet extraction is off

* parcel integration

* Add changeset

* Replace rather than insert class name in the sheet and make ClassNames to support conditional CSS

* add 'generateCompressionMap'

* Update changelog

* Fix spelling mistake

* Allow uppercase in class-name-generator

* chore(deps): update dependency css-what to >=5.1.0 (#1409)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update webpack packages (#1411)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Fix transparent and currentcolor not being treated as a color (#1412)

* chore(deps): update dependency css-what to >=6.1.0 (#1414)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Version Packages (#1413)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

* chore(deps): update dependency nth-check to >=2.1.1 (#1415)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency prettier to ^2.8.4 (#1416)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency @types/node to ^18.13.0 (#1417)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* Bump node version to v18 (#1392)

* Bump node version to v18

* Bump import jsx

* Bump nvmrc node version from 18.12 to 18.14

* Add changeset for PR #1392

---------

Co-authored-by: Grant Wong <gwong2@atlassian.com>

* chore(deps): update parcel packages (#1390)

* chore(deps): update parcel packages

* Add dummy generic type so optimizer works with parcel v2.8.0+

Parcel v2.8.0 adds a BundleConfigType generic type to Optimizer
(parcel-bundler/parcel#8370) as part of
their `loadBundleConfig` method. We use a dummy type because we
don't need this functionality currently.

* Update snapshot tests for Parcel 2.8.3

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Grant Wong <gwong2@atlassian.com>

* chore(deps): update eslint packages (#1420)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* chore(deps): update dependency jest to v29 (#1384)

* chore(deps): update dependency jest to v29

* Update snapshots and node env for some tests

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jake Lane <jlane2@atlassian.com>

* Add Grant Wong as codeowner (#1421)

Co-authored-by: Grant Wong <2908767+dddlr@users.noreply.github.com>

* Replace rather than insert class name in the sheet and make ClassNames to support conditional CSS

* Add prefix option and avoid 'ad'

* Add comment to ax benchmark

* Make classNameCompressionMap a separate file in parcel example app

* Remove default reservedClassNames

* Export generateCompressionMap

* Update comment

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Jake Lane <jlane2@atlassian.com>
Co-authored-by: atlas-dst-bot <81662413+atlas-dst-bot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Grant Wong <gwong2@atlassian.com>
Co-authored-by: Grant Wong <2908767+dddlr@users.noreply.github.com>
  • Loading branch information
7 people committed Feb 20, 2023
1 parent 32b54a1 commit f9c957e
Show file tree
Hide file tree
Showing 30 changed files with 933 additions and 147 deletions.
10 changes: 10 additions & 0 deletions .changeset/grumpy-cows-look.md
@@ -0,0 +1,10 @@
---
'@compiled/parcel-transformer': minor
'@compiled/webpack-loader': minor
'@compiled/babel-plugin': minor
'@compiled/react': minor
'@compiled/css': minor
---

Add an option to compress class names based on "classNameCompressionMap", which is provided by library consumers.
Add a script to generate compressed class names.
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -2,6 +2,7 @@ module.exports = {
root: true,
ignorePatterns: [
'dist',
'build',
'flow-typed',
'*.d.ts',
'babel-cjs.js',
Expand Down
24 changes: 0 additions & 24 deletions examples/parcel/.compiledcssrc

This file was deleted.

18 changes: 18 additions & 0 deletions examples/parcel/class-name-compression-map.json
@@ -0,0 +1,18 @@
{
"1wyb12am": "a",
"syaz5scu": "b",
"syazruxl": "c",
"k48pbfng": "d",
"30l35scu": "e",
"f8pj13q2": "f",
"1e0c1o8l": "g",
"ca0qftgi": "h",
"u5f3ftgi": "i",
"n3tdftgi": "j",
"19bvftgi": "k",
"19itak0l": "l",
"2rko1l7b": "m",
"syaz1aj3": "n",
"1p1dangw": "o",
"bfhkbf54": "p"
}
18 changes: 18 additions & 0 deletions examples/parcel/compiledcss.js
@@ -0,0 +1,18 @@
const classNameCompressionMap = require('./class-name-compression-map.json');

module.exports = {
importReact: false,
extensions: ['.js', '.jsx', '.ts', '.tsx', '.customjsx'],
parserBabelPlugins: ['typescript', 'jsx'],
transformerBabelPlugins: [
[
'@babel/plugin-proposal-decorators',
{
legacy: true,
},
],
],
extract: true,
optimizeCss: false,
classNameCompressionMap: classNameCompressionMap,
};
27 changes: 27 additions & 0 deletions examples/webpack/class-name-compression-map.json
@@ -0,0 +1,27 @@
{
"1wyb12am": "a",
"syaz32ev": "b",
"k48pbfng": "c",
"30l35scu": "d",
"f8pj13q2": "e",
"19itptrx": "f",
"1kt92a4o": "g",
"171dak0l": "h",
"1swkri7e": "i",
"1tjq14ap": "j",
"yzbc5scu": "k",
"19pk1ul9": "l",
"syaz13q2": "m",
"1wyb1ul9": "n",
"19itlf8h": "o",
"ca0q1vi7": "p",
"u5f31vi7": "q",
"n3td1vi7": "r",
"19bv1vi7": "s",
"k48p1fw0": "t",
"syaz1cnh": "u",
"19it1srw": "v",
"bfhk1j28": "w",
"syazruxl": "x",
"bfhkbf54": "y"
}
3 changes: 3 additions & 0 deletions examples/webpack/webpack.config.js
Expand Up @@ -7,6 +7,8 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');

const classNameCompressionMap = require('./class-name-compression-map.json');

const extractCSS = process.env.EXTRACT_TO_CSS === 'true';

module.exports = {
Expand Down Expand Up @@ -40,6 +42,7 @@ module.exports = {
parserBabelPlugins: ['typescript', 'jsx'],
transformerBabelPlugins: [['@babel/plugin-proposal-decorators', { legacy: true }]],
optimizeCss: false,
classNameCompressionMap,
},
},
],
Expand Down
156 changes: 156 additions & 0 deletions packages/babel-plugin/src/__tests__/index.test.ts
Expand Up @@ -201,4 +201,160 @@ describe('babel plugin', () => {

expect(actual).toInclude('c_MyDiv');
});

it('should compress class name for styled component', () => {
const actual = transform(
`
import { styled } from '@compiled/react';
const MyDiv = styled.div\`
font-size: 12px;
\`;
`,
{
classNameCompressionMap: {
'1wyb1fwx': 'a',
},
}
);

expect(actual).toIncludeMultiple(['.a{font-size:12px}', 'ax(["_1wyb_a", __cmplp.className])']);
});

it('should compress class name for css props', () => {
const actual = transform(
`
import '@compiled/react';
<div css={{ fontSize: 12 }} />
`,
{
classNameCompressionMap: {
'1wyb1fwx': 'a',
},
}
);

expect(actual).toIncludeMultiple(['.a{font-size:12px}', 'ax(["_1wyb_a"])']);
});

it('should compress class name for ClassNames', () => {
const actual = transform(
`
import { ClassNames } from '@compiled/react';
<ClassNames>
{({ css }) => (
<div className={css({ fontSize: 12 })} />
)}
</ClassNames>
`,
{
classNameCompressionMap: {
'1wyb1fwx': 'a',
},
}
);

expect(actual).toIncludeMultiple(['.a{font-size:12px}', 'className={ax(["_1wyb_a"])']);
});

it('should compress class names with atrules', () => {
const actual = transform(
`
import '@compiled/react';
<div css={{ "@media (max-width: 1250px) ": { fontSize: 12 } }} />
`,
{
classNameCompressionMap: {
pz521fwx: 'a',
},
}
);

expect(actual).toIncludeMultiple([
'@media (max-width:1250px){.a{font-size:12px}}',
'ax(["_pz52_a"])',
]);
});

it('should compress pseudo classes', () => {
const actual = transform(
`
import '@compiled/react';
<div css={{ "&:hover": { fontSize: 12 }, "&:active": { color: 'red' } }} />
`,
{
classNameCompressionMap: {
'9h8h5scu': 'a',
e9151fwx: 'b',
},
}
);

expect(actual).toIncludeMultiple([
'.a:active{color:red}',
'.b:hover{font-size:12px}',
'ax(["_e915_b _9h8h_a"])',
]);
});

it('should compress nested selector', () => {
const actual = transform(
`
import '@compiled/react';
<div css={{ '>div': { 'div div:hover': { fontSize: 12 } } }} />
`,
{
classNameCompressionMap: {
'1jkf1fwx': 'a',
},
}
);

expect(actual).toIncludeMultiple(['.a >div div div:hover{font-size:12px}', 'ax(["_1jkf_a"]']);
});

it('should compress conditional class names', () => {
const actual = transform(
`
import '@compiled/react';
<div css={[{ fontSize: ({ bar }) => bar ? 14 : 16 }, () => foo ? { fontSize: 12 } : {}, baz && { fontSize: 20 }]} />
`,
{
classNameCompressionMap: {
'1wyb19ub': 'a',
'1wyb1fwx': 'b',
},
}
);

expect(actual).toIncludeMultiple([
'.a{font-size:16}',
'.b{font-size:12px}',
'bar ? "_1wyb1o8a" : "_1wyb_a"',
'foo && "_1wyb_b"',
]);
});

it('should compress class names according to the map', () => {
const actual = transform(
`
import '@compiled/react';
<div css={{ fontSize: 12, color: 'red', marginTop: 10 }} />
`,
{
classNameCompressionMap: {
syaz5scu: 'a',
},
}
);

expect(actual).toIncludeMultiple([
'._19pk19bv{margin-top:10px}',
'.a{color:red}',
'._1wyb1fwx{font-size:12px}',
'ax(["_1wyb1fwx _syaz_a _19pk19bv"]',
]);
});
});
2 changes: 1 addition & 1 deletion packages/babel-plugin/src/__tests__/jsx-automatic.test.ts
Expand Up @@ -49,7 +49,7 @@ describe('jsx automatic', () => {
children: [_],
}),
_jsx("div", {
className: "_syaz13q2",
className: ax(["_syaz13q2"]),
}),
],
});
Expand Down

0 comments on commit f9c957e

Please sign in to comment.