-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve collapsing of duplicate declarations (#6856)
* improve collapsing of duplicate properties In theory, we don't have to do anything because the browser is smart enough to figure everything out. However, leaving in duplicate properties is not that ideal for file size. Our previous method was pretty simple: if you see a declaration you already saw in this rule, delete the previous one and keep the current one. This works pretty well, but this gets rid of **all** the declarations with the same property. This is not great for overrides for older browsers. In a perfect world, we can handle this based on your target browser but this is a lot of unnecessary complexity and will slow things down performance wise. Alternative, we improved the solution by being a bit smarter: 1. Delete duplicate declarations that have the same property and value (this will get rid of **exact** duplications). 2. Delete declarations with the same property and the same **unit**. This means that we will reduce this: ```css .example { height: 50%; height: 100px; height: 20vh; height: 30%; height: 50px; height: 30vh; transform: var(--value); transform: var(--value); } ``` To: ```diff-css .example { - height: 50%; /* Another height exists later with a `%` unit */ - height: 100px; /* Another height exists later with a `px` unit */ - height: 20vh; /* Another height exists later with a `vh` unit */ height: 30%; height: 50px; height: 30vh; - transform: var(--value); /* Value is too complex, but is **exactly** the same as the one below */ transform: var(--value); } ``` This will reduce the values that we are 100% sure that can be safely removed. This will still result in some overrides but the browser can handle those for you. Fixes: #6844 * update changelog
- Loading branch information
1 parent
3149738
commit b9af5a9
Showing
4 changed files
with
243 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
import { run, css, html } from './util/run' | ||
|
||
it('should collapse duplicate declarations with the same units (px)', () => { | ||
let config = { | ||
content: [{ raw: html`<div class="example"></div>` }], | ||
corePlugins: { preflight: false }, | ||
plugins: [], | ||
} | ||
|
||
let input = css` | ||
@tailwind utilities; | ||
@layer utilities { | ||
.example { | ||
height: 100px; | ||
height: 200px; | ||
} | ||
} | ||
` | ||
|
||
return run(input, config).then((result) => { | ||
expect(result.css).toMatchFormattedCss(css` | ||
.example { | ||
height: 200px; | ||
} | ||
`) | ||
}) | ||
}) | ||
|
||
it('should collapse duplicate declarations with the same units (no unit)', () => { | ||
let config = { | ||
content: [{ raw: html`<div class="example"></div>` }], | ||
corePlugins: { preflight: false }, | ||
plugins: [], | ||
} | ||
|
||
let input = css` | ||
@tailwind utilities; | ||
@layer utilities { | ||
.example { | ||
line-height: 3; | ||
line-height: 2; | ||
} | ||
} | ||
` | ||
|
||
return run(input, config).then((result) => { | ||
expect(result.css).toMatchFormattedCss(css` | ||
.example { | ||
line-height: 2; | ||
} | ||
`) | ||
}) | ||
}) | ||
|
||
it('should not collapse duplicate declarations with the different units', () => { | ||
let config = { | ||
content: [{ raw: html`<div class="example"></div>` }], | ||
corePlugins: { preflight: false }, | ||
plugins: [], | ||
} | ||
|
||
let input = css` | ||
@tailwind utilities; | ||
@layer utilities { | ||
.example { | ||
height: 100px; | ||
height: 50%; | ||
} | ||
} | ||
` | ||
|
||
return run(input, config).then((result) => { | ||
expect(result.css).toMatchFormattedCss(css` | ||
.example { | ||
height: 100px; | ||
height: 50%; | ||
} | ||
`) | ||
}) | ||
}) | ||
|
||
it('should collapse the duplicate declarations with the same unit, but leave the ones with different units', () => { | ||
let config = { | ||
content: [{ raw: html`<div class="example"></div>` }], | ||
corePlugins: { preflight: false }, | ||
plugins: [], | ||
} | ||
|
||
let input = css` | ||
@tailwind utilities; | ||
@layer utilities { | ||
.example { | ||
height: 100px; | ||
height: 50%; | ||
height: 20vh; | ||
height: 200px; | ||
height: 100%; | ||
height: 30vh; | ||
} | ||
} | ||
` | ||
|
||
return run(input, config).then((result) => { | ||
expect(result.css).toMatchFormattedCss(css` | ||
.example { | ||
height: 200px; | ||
height: 100%; | ||
height: 30vh; | ||
} | ||
`) | ||
}) | ||
}) | ||
|
||
it('should collapse the duplicate declarations with the exact same value', () => { | ||
let config = { | ||
content: [{ raw: html`<div class="example"></div>` }], | ||
corePlugins: { preflight: false }, | ||
plugins: [], | ||
} | ||
|
||
let input = css` | ||
@tailwind utilities; | ||
@layer utilities { | ||
.example { | ||
height: var(--value); | ||
color: blue; | ||
height: var(--value); | ||
} | ||
} | ||
` | ||
|
||
return run(input, config).then((result) => { | ||
expect(result.css).toMatchFormattedCss(css` | ||
.example { | ||
color: blue; | ||
height: var(--value); | ||
} | ||
`) | ||
}) | ||
}) | ||
|
||
it('should work on a real world example', () => { | ||
let config = { | ||
content: [{ raw: html`<div class="h-available"></div>` }], | ||
corePlugins: { preflight: false }, | ||
plugins: [], | ||
} | ||
|
||
let input = css` | ||
@tailwind utilities; | ||
@layer utilities { | ||
.h-available { | ||
height: 100%; | ||
height: 100vh; | ||
height: -webkit-fill-available; | ||
} | ||
} | ||
` | ||
|
||
return run(input, config).then((result) => { | ||
expect(result.css).toMatchFormattedCss(css` | ||
.h-available { | ||
height: 100%; | ||
height: 100vh; | ||
height: -webkit-fill-available; | ||
} | ||
`) | ||
}) | ||
}) |