Skip to content

Commit 37070ca

Browse files
authored
Reduce bundle size (#363)
## TL;DR; - 1.8kB raw filesize reduction with some not-too-extreme code golfing ## Before String/identifier analysis: `Total size: 18.0 kB, string size: 2.9 kB (15.9%)` ## After String/identifier analysis: `Total size: 16.2 kB, string size: 2.8 kB (17.4%)`
1 parent 1cf7361 commit 37070ca

16 files changed

+454
-307
lines changed

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,12 @@
3939
"analytics",
4040
"performance",
4141
"styleguide",
42-
"metrics"
42+
"metrics",
43+
"designsystem",
44+
"fonts",
45+
"colors",
46+
"quality",
47+
"code"
4348
],
4449
"dependencies": {
4550
"@bramus/specificity": "^2.3.0",

src/aggregate-collection.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ function Mode(arr) {
1111
let maxOccurrences = -1
1212
let maxOccurenceCount = 0
1313
let sum = 0
14+
let len = arr.length
1415

15-
for (let i = 0; i < arr.length; i++) {
16+
for (let i = 0; i < len; i++) {
1617
let element = arr[i]
1718
let updatedCount = (frequencies.get(element) || 0) + 1
1819
frequencies.set(element, updatedCount)
@@ -70,7 +71,9 @@ class AggregateCollection {
7071
}
7172

7273
aggregate() {
73-
if (this._items.length === 0) {
74+
let len = this._items.length
75+
76+
if (len === 0) {
7477
return {
7578
min: 0,
7679
max: 0,
@@ -86,19 +89,20 @@ class AggregateCollection {
8689
/** @type Number[] */
8790
let sorted = this._items.slice().sort((a, b) => a - b)
8891
let min = sorted[0]
89-
let max = sorted[sorted.length - 1]
92+
let max = sorted[len - 1]
9093

9194
let mode = Mode(sorted)
9295
let median = Median(sorted)
96+
let sum = this._sum
9397

9498
return {
9599
min,
96100
max,
97-
mean: this._sum / sorted.length,
101+
mean: sum / len,
98102
mode,
99103
median,
100104
range: max - min,
101-
sum: this._sum,
105+
sum: sum,
102106
}
103107
}
104108

src/atrules/atrules.js

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { strEquals, startsWith, endsWith } from '../string-utils.js'
22
import walk from 'css-tree/walker'
3+
import {
4+
Identifier,
5+
MediaQuery,
6+
MediaFeature,
7+
Declaration,
8+
} from '../css-tree-node-types.js'
39

410
/**
511
* Check whether node.property === property and node.value === value,
@@ -10,9 +16,10 @@ import walk from 'css-tree/walker'
1016
* @returns true if declaratioNode is the given property: value, false otherwise
1117
*/
1218
function isPropertyValue(node, property, value) {
19+
let firstChild = node.value.children.first
1320
return strEquals(property, node.property)
14-
&& node.value.children.first.type === 'Identifier'
15-
&& strEquals(value, node.value.children.first.name)
21+
&& firstChild.type === Identifier
22+
&& strEquals(value, firstChild.name)
1623
}
1724

1825
/**
@@ -24,7 +31,7 @@ export function isSupportsBrowserhack(prelude) {
2431
let returnValue = false
2532

2633
walk(prelude, function (node) {
27-
if (node.type === 'Declaration') {
34+
if (node.type === Declaration) {
2835
if (
2936
isPropertyValue(node, '-webkit-appearance', 'none')
3037
|| isPropertyValue(node, '-moz-appearance', 'meterbar')
@@ -47,38 +54,43 @@ export function isMediaBrowserhack(prelude) {
4754
let returnValue = false
4855

4956
walk(prelude, function (node) {
50-
if (node.type === 'MediaQuery'
51-
&& node.children.size === 1
52-
&& node.children.first.type === 'Identifier'
57+
let children = node.children
58+
let name = node.name
59+
let value = node.value
60+
61+
if (node.type === MediaQuery
62+
&& children.size === 1
63+
&& children.first.type === Identifier
5364
) {
54-
node = node.children.first
65+
let n = children.first.name
5566
// Note: CSSTree adds a trailing space to \\9
56-
if (startsWith('\\0', node.name) || endsWith('\\9 ', node.name)) {
67+
if (startsWith('\\0', n) || endsWith('\\9 ', n)) {
5768
returnValue = true
5869
return this.break
5970
}
6071
}
61-
if (node.type === 'MediaFeature') {
62-
if (node.value !== null && node.value.unit === '\\0') {
72+
if (node.type === MediaFeature) {
73+
if (value !== null && value.unit === '\\0') {
6374
returnValue = true
6475
return this.break
6576
}
66-
if (strEquals('-moz-images-in-menus', node.name)
67-
|| strEquals('min--moz-device-pixel-ratio', node.name)
68-
|| strEquals('-ms-high-contrast', node.name)
77+
if (strEquals('-moz-images-in-menus', name)
78+
|| strEquals('min--moz-device-pixel-ratio', name)
79+
|| strEquals('-ms-high-contrast', name)
6980
) {
7081
returnValue = true
7182
return this.break
7283
}
73-
if (strEquals('min-resolution', node.name)
74-
&& strEquals('.001', node.value.value)
75-
&& strEquals('dpcm', node.value.unit)
84+
if (strEquals('min-resolution', name)
85+
&& strEquals('.001', value.value)
86+
&& strEquals('dpcm', value.unit)
7687
) {
7788
returnValue = true
7889
return this.break
7990
}
80-
if (strEquals('-webkit-min-device-pixel-ratio', node.name)) {
81-
if ((strEquals('0', node.value.value) || strEquals('10000', node.value.value))) {
91+
if (strEquals('-webkit-min-device-pixel-ratio', name)) {
92+
let val = value.value
93+
if ((strEquals('0', val) || strEquals('10000', val))) {
8294
returnValue = true
8395
return this.break
8496
}

src/collection.js

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
export class Collection {
2-
constructor({ useLocations = false }) {
2+
/** @param {boolean} useLocations */
3+
constructor(useLocations = false) {
34
/** @type {Map<string, number[]>} */
45
this._items = new Map()
56
this._total = 0
6-
/** @type {number[]} */
7-
this.node_lines = []
8-
/** @type {number[]} */
9-
this.node_columns = []
10-
/** @type {number[]} */
11-
this.node_lengths = []
12-
/** @type {number[]} */
13-
this.node_offsets = []
7+
8+
if (useLocations) {
9+
/** @type {number[]} */
10+
this._node_lines = []
11+
/** @type {number[]} */
12+
this._node_columns = []
13+
/** @type {number[]} */
14+
this._node_lengths = []
15+
/** @type {number[]} */
16+
this._node_offsets = []
17+
}
1418

1519
/** @type {boolean} */
1620
this._useLocations = useLocations
@@ -20,13 +24,18 @@ export class Collection {
2024
* @param {string} item
2125
* @param {import('css-tree').CssLocation} node_location
2226
*/
23-
push(item, node_location) {
27+
p(item, node_location) {
2428
let index = this._total
2529

26-
this.node_lines[index] = node_location.start.line
27-
this.node_columns[index] = node_location.start.column
28-
this.node_offsets[index] = node_location.start.offset
29-
this.node_lengths[index] = node_location.end.offset - node_location.start.offset
30+
if (this._useLocations) {
31+
let start = node_location.start
32+
let start_offset = start.offset
33+
34+
this._node_lines[index] = start.line
35+
this._node_columns[index] = start.column
36+
this._node_offsets[index] = start_offset
37+
this._node_lengths[index] = node_location.end.offset - start_offset
38+
}
3039

3140
if (this._items.has(item)) {
3241
/** @type number[] */
@@ -53,35 +62,41 @@ export class Collection {
5362
*
5463
* @returns {{ total: number; totalUnique: number; uniquenessRatio: number; unique: Record<string, number>; __unstable__uniqueWithLocations: Record<string, CssLocation[]>}}
5564
*/
56-
count() {
65+
c() {
66+
let useLocations = this._useLocations
5767
let uniqueWithLocations = new Map()
5868
let unique = {}
59-
this._items.forEach((list, key) => {
60-
let nodes = list.map(index => ({
61-
line: this.node_lines[index],
62-
column: this.node_columns[index],
63-
offset: this.node_offsets[index],
64-
length: this.node_lengths[index],
65-
}))
66-
uniqueWithLocations.set(key, nodes)
69+
let items = this._items
70+
let size = items.size
71+
72+
items.forEach((list, key) => {
73+
if (useLocations) {
74+
let nodes = list.map(index => ({
75+
line: this._node_lines[index],
76+
column: this._node_columns[index],
77+
offset: this._node_offsets[index],
78+
length: this._node_lengths[index],
79+
}))
80+
uniqueWithLocations.set(key, nodes)
81+
}
6782
unique[key] = list.length
6883
})
6984

7085
if (this._useLocations) {
7186
return {
7287
total: this._total,
73-
totalUnique: this._items.size,
88+
totalUnique: size,
7489
unique,
75-
uniquenessRatio: this._total === 0 ? 0 : this._items.size / this._total,
90+
uniquenessRatio: this._total === 0 ? 0 : size / this._total,
7691
__unstable__uniqueWithLocations: Object.fromEntries(uniqueWithLocations),
7792
}
7893
}
7994

8095
return {
8196
total: this._total,
82-
totalUnique: this._items.size,
97+
totalUnique: size,
8398
unique,
84-
uniquenessRatio: this._total === 0 ? 0 : this._items.size / this._total,
99+
uniquenessRatio: this._total === 0 ? 0 : size / this._total,
85100
}
86101
}
87102
}

src/context-collection.js

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Collection } from './collection.js'
22

33
class ContextCollection {
4-
constructor({ useLocations = false }) {
5-
this._list = new Collection({ useLocations })
4+
/** @param {boolean} useLocations */
5+
constructor(useLocations) {
6+
this._list = new Collection(useLocations)
67
/** @type {Map<string, Collection>} */
78
this._contexts = new Map()
89
/** @type {boolean} */
9-
this.useLocations = useLocations
10+
this._useLocations = useLocations
1011
}
1112

1213
/**
@@ -16,13 +17,13 @@ class ContextCollection {
1617
* @param {import('css-tree').CssLocation} node_location
1718
*/
1819
push(item, context, node_location) {
19-
this._list.push(item, node_location)
20+
this._list.p(item, node_location)
2021

2122
if (!this._contexts.has(context)) {
22-
this._contexts.set(context, new Collection({ useLocations: this.useLocations }))
23+
this._contexts.set(context, new Collection(this._useLocations))
2324
}
2425

25-
this._contexts.get(context).push(item, node_location)
26+
this._contexts.get(context).p(item, node_location)
2627
}
2728

2829
count() {
@@ -37,10 +38,10 @@ class ContextCollection {
3738
let itemsPerContext = new Map()
3839

3940
for (let [context, value] of this._contexts.entries()) {
40-
itemsPerContext.set(context, value.count())
41+
itemsPerContext.set(context, value.c())
4142
}
4243

43-
return Object.assign(this._list.count(), {
44+
return Object.assign(this._list.c(), {
4445
itemsPerContext: Object.fromEntries(itemsPerContext)
4546
})
4647
}

src/countable-collection.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ class CountableCollection {
3030
}
3131

3232
count() {
33+
let items = this._items
34+
let size = items.size
35+
let total = this._total
36+
3337
return {
34-
total: this._total,
35-
totalUnique: this._items.size,
36-
unique: Object.fromEntries(this._items),
37-
uniquenessRatio: this._total === 0 ? 0 : this._items.size / this._total,
38+
total: total,
39+
totalUnique: size,
40+
unique: Object.fromEntries(items),
41+
uniquenessRatio: total === 0 ? 0 : size / total,
3842
}
3943
}
4044
}

src/css-tree-node-types.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Atrule
2+
export const Atrule = 'Atrule'
3+
export const MediaQuery = 'MediaQuery'
4+
export const MediaFeature = 'MediaFeature'
5+
// Rule
6+
export const Rule = 'Rule'
7+
8+
// Selector
9+
export const Selector = 'Selector'
10+
export const TypeSelector = 'TypeSelector'
11+
export const PseudoClassSelector = 'PseudoClassSelector'
12+
export const AttributeSelector = 'AttributeSelector'
13+
export const IdSelector = 'IdSelector'
14+
export const ClassSelector = 'ClassSelector'
15+
export const PseudoElementSelector = 'PseudoElementSelector'
16+
17+
// Declaration
18+
export const Declaration = 'Declaration'
19+
20+
// Values
21+
export const Value = 'Value'
22+
export const Identifier = 'Identifier'
23+
export const Nth = 'Nth'
24+
export const Combinator = 'Combinator'
25+
export const Nr = 'Number'
26+
export const Dimension = 'Dimension'
27+
export const Operator = 'Operator'
28+
export const Hash = 'Hash'
29+
export const Url = 'Url'
30+
export const Func = 'Function'

0 commit comments

Comments
 (0)