Skip to content

Commit fe27356

Browse files
JIT: Optimize universal selector usage by inlining only the relevant selectors (tailwindlabs#4850)
* WIP * run prettier * drop new lines in custom matcher Drop all newlines, let prettier handle everything for us. * add cache for the selector parser * add `@apply` tests for the universal optimizer * drop comments * initial replacements * WIP * WIP * MAKE IT WORK * Rename to resolveDefaultsAtRules * Update tests + defaults identifiers * Don't add @defaults in AOT mode Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
1 parent 369c7b5 commit fe27356

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1172
-488
lines changed

jest/customMatchers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ expect.extend({
102102
// This is probably naive but it's fast and works well enough.
103103
toMatchFormattedCss(received, argument) {
104104
function format(input) {
105-
return prettier.format(input, {
105+
return prettier.format(input.replace(/\n/g, ''), {
106106
parser: 'css',
107107
printWidth: 100,
108108
})
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import postcss from 'postcss'
2+
import selectorParser from 'postcss-selector-parser'
3+
4+
let elementSelectorParser = selectorParser((selectors) => {
5+
return selectors.map((s) => {
6+
return s
7+
.split((n) => n.type === 'combinator')
8+
.pop()
9+
.filter((n) => n.type !== 'pseudo' || n.value.startsWith('::'))
10+
.join('')
11+
.trim()
12+
})
13+
})
14+
15+
let cache = new Map()
16+
17+
function extractElementSelector(selector) {
18+
if (!cache.has(selector)) {
19+
cache.set(selector, elementSelectorParser.transformSync(selector))
20+
}
21+
22+
return cache.get(selector)
23+
}
24+
25+
export default function resolveDefaultsAtRules() {
26+
return (root) => {
27+
let variableNodeMap = new Map()
28+
let universals = new Set()
29+
30+
root.walkAtRules('defaults', (rule) => {
31+
if (rule.nodes.length > 0) {
32+
universals.add(rule)
33+
return
34+
}
35+
36+
let variable = rule.params
37+
if (!variableNodeMap.has(variable)) {
38+
variableNodeMap.set(variable, new Set())
39+
}
40+
41+
variableNodeMap.get(variable).add(rule.parent)
42+
43+
rule.remove()
44+
})
45+
46+
for (let universal of universals) {
47+
let selectors = new Set()
48+
49+
let rules = variableNodeMap.get(universal.params) ?? []
50+
51+
for (let rule of rules) {
52+
for (let selector of extractElementSelector(rule.selector)) {
53+
selectors.add(selector)
54+
}
55+
}
56+
57+
if (selectors.size === 0) {
58+
universal.remove()
59+
continue
60+
}
61+
62+
let universalRule = postcss.rule()
63+
universalRule.selectors = [...selectors]
64+
universalRule.append(universal.nodes)
65+
universal.before(universalRule)
66+
universal.remove()
67+
}
68+
}
69+
}

src/jit/processTailwindFeatures.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import expandTailwindAtRules from './lib/expandTailwindAtRules'
33
import expandApplyAtRules from './lib/expandApplyAtRules'
44
import evaluateTailwindFunctions from '../lib/evaluateTailwindFunctions'
55
import substituteScreenAtRules from '../lib/substituteScreenAtRules'
6+
import resolveDefaultsAtRules from './lib/resolveDefaultsAtRules'
67
import collapseAdjacentRules from './lib/collapseAdjacentRules'
78
import { createContext } from './lib/setupContextUtils'
89
import log from '../util/log'
@@ -45,6 +46,7 @@ export default function processTailwindFeatures(setupContext) {
4546
expandApplyAtRules(context)(root, result)
4647
evaluateTailwindFunctions(context)(root, result)
4748
substituteScreenAtRules(context)(root, result)
49+
resolveDefaultsAtRules(context)(root, result)
4850
collapseAdjacentRules(context)(root, result)
4951
}
5052
}

src/plugins/backdropBlur.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export default function () {
55
'backdrop-blur': (value) => {
66
return {
77
'--tw-backdrop-blur': `blur(${value})`,
8-
...(config('mode') === 'jit' ? { 'backdrop-filter': 'var(--tw-backdrop-filter)' } : {}),
8+
...(config('mode') === 'jit'
9+
? {
10+
'@defaults backdrop-filter': {},
11+
'backdrop-filter': 'var(--tw-backdrop-filter)',
12+
}
13+
: {}),
914
}
1015
},
1116
},

src/plugins/backdropBrightness.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export default function () {
55
'backdrop-brightness': (value) => {
66
return {
77
'--tw-backdrop-brightness': `brightness(${value})`,
8-
...(config('mode') === 'jit' ? { 'backdrop-filter': 'var(--tw-backdrop-filter)' } : {}),
8+
...(config('mode') === 'jit'
9+
? {
10+
'@defaults backdrop-filter': {},
11+
'backdrop-filter': 'var(--tw-backdrop-filter)',
12+
}
13+
: {}),
914
}
1015
},
1116
},

src/plugins/backdropContrast.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export default function () {
55
'backdrop-contrast': (value) => {
66
return {
77
'--tw-backdrop-contrast': `contrast(${value})`,
8-
...(config('mode') === 'jit' ? { 'backdrop-filter': 'var(--tw-backdrop-filter)' } : {}),
8+
...(config('mode') === 'jit'
9+
? {
10+
'@defaults backdrop-filter': {},
11+
'backdrop-filter': 'var(--tw-backdrop-filter)',
12+
}
13+
: {}),
914
}
1015
},
1116
},

src/plugins/backdropFilter.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export default function () {
22
return function ({ config, addBase, addUtilities, variants }) {
33
if (config('mode') === 'jit') {
44
addBase({
5-
'*, ::before, ::after': {
5+
'@defaults backdrop-filter': {
66
'--tw-backdrop-blur': 'var(--tw-empty,/*!*/ /*!*/)',
77
'--tw-backdrop-brightness': 'var(--tw-empty,/*!*/ /*!*/)',
88
'--tw-backdrop-contrast': 'var(--tw-empty,/*!*/ /*!*/)',
@@ -27,7 +27,10 @@ export default function () {
2727
})
2828
addUtilities(
2929
{
30-
'.backdrop-filter': { 'backdrop-filter': 'var(--tw-backdrop-filter)' },
30+
'.backdrop-filter': {
31+
'@defaults backdrop-filter': {},
32+
'backdrop-filter': 'var(--tw-backdrop-filter)',
33+
},
3134
'.backdrop-filter-none': { 'backdrop-filter': 'none' },
3235
},
3336
variants('backdropFilter')

src/plugins/backdropGrayscale.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export default function () {
55
'backdrop-grayscale': (value) => {
66
return {
77
'--tw-backdrop-grayscale': `grayscale(${value})`,
8-
...(config('mode') === 'jit' ? { 'backdrop-filter': 'var(--tw-backdrop-filter)' } : {}),
8+
...(config('mode') === 'jit'
9+
? {
10+
'@defaults backdrop-filter': {},
11+
'backdrop-filter': 'var(--tw-backdrop-filter)',
12+
}
13+
: {}),
914
}
1015
},
1116
},

src/plugins/backdropHueRotate.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export default function () {
55
'backdrop-hue-rotate': (value) => {
66
return {
77
'--tw-backdrop-hue-rotate': `hue-rotate(${value})`,
8-
...(config('mode') === 'jit' ? { 'backdrop-filter': 'var(--tw-backdrop-filter)' } : {}),
8+
...(config('mode') === 'jit'
9+
? {
10+
'@defaults backdrop-filter': {},
11+
'backdrop-filter': 'var(--tw-backdrop-filter)',
12+
}
13+
: {}),
914
}
1015
},
1116
},

src/plugins/backdropInvert.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ export default function () {
55
'backdrop-invert': (value) => {
66
return {
77
'--tw-backdrop-invert': `invert(${value})`,
8-
...(config('mode') === 'jit' ? { 'backdrop-filter': 'var(--tw-backdrop-filter)' } : {}),
8+
...(config('mode') === 'jit'
9+
? {
10+
'@defaults backdrop-filter': {},
11+
'backdrop-filter': 'var(--tw-backdrop-filter)',
12+
}
13+
: {}),
914
}
1015
},
1116
},

0 commit comments

Comments
 (0)