-
Notifications
You must be signed in to change notification settings - Fork 176
Expand file tree
/
Copy pathpruneNonCriticalSelectors.js
More file actions
97 lines (82 loc) · 3.31 KB
/
Copy pathpruneNonCriticalSelectors.js
File metadata and controls
97 lines (82 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// executed inside sandboxed browser environment,
// no access to scrope outside of function
export default function pruneNonCriticalSelectors ({
selectors,
maxElementsToCheckPerSelector
}) {
console.log('debug: pruneNonCriticalSelectors init')
var h = window.innerHeight
// cache whether elements are above fold,
// primarily because getBoundingClientRect() can be slow to query,
// and some stylesheets have lots of generic selectors (like '.button', '.fa' etc)
var isElementAboveFoldCache = new Map()
function isElementAboveFold (element) {
if (isElementAboveFoldCache.has(element)) {
return isElementAboveFoldCache.get(element)
}
// temporarily force clear none in order to catch elements that clear previous
// content themselves and who w/o their styles could show up unstyled in above
// the fold content (if they rely on f.e. 'clear:both;' to clear some main content)
// but do that only if elements have their style attribute defined
// (ref: https://github.com/pocketjoso/penthouse/issues/342)
const isElementStyleDefined = typeof element.style !== 'undefined'
if (isElementStyleDefined) {
var originalClearStyle = element.style.clear || ''
element.style.clear = 'none'
}
var aboveFold = element.getBoundingClientRect().top < h
// cache so we dont have to re-query DOM for this value
isElementAboveFoldCache.set(element, aboveFold)
if (isElementStyleDefined) {
// set clear style back to what it was
element.style.clear = originalClearStyle
}
// Should not be needed anymore with Chrome Headless:
// do some monitoring before complete removing the code (below)
// if (!aboveFold) {
// // phantomJS/QT browser has some bugs regarding fixed position;
// // sometimes positioning elements outside of screen incorrectly.
// // just keep all fixed position elements - normally very few in a stylesheet anyway
// var styles = window.getComputedStyle(element, null)
// if (styles.position === 'fixed') {
// console.log('debug: force keeping fixed position styles')
// return true
// }
// }
return aboveFold
}
function isSelectorCritical (selector) {
// we have a selector to test, first grab any matching elements
let elements
try {
elements = document.querySelectorAll(selector)
} catch (e) {
// not a valid selector, remove it.
return false
}
let nrElementsToCheck = elements.length
if (
maxElementsToCheckPerSelector &&
nrElementsToCheck > maxElementsToCheckPerSelector
) {
console.log(
`debug: isSelectorCritical, selector: ${selector} appearing ${nrElementsToCheck} time on page, ONLY checking first ${maxElementsToCheckPerSelector}...`
)
nrElementsToCheck = maxElementsToCheckPerSelector
}
// only keep selectors that match at least one elements on the page above the fold
for (let idx = 0; idx < nrElementsToCheck; idx++) {
if (isElementAboveFold(elements[idx])) {
return true
}
}
return false
}
function filterSelectors (selectors) {
console.log('debug: filterSelectors START')
selectors = selectors.filter(isSelectorCritical)
console.log('debug: filterSelectors DONE')
return selectors
}
return filterSelectors(selectors)
}