Skip to content

Commit

Permalink
feat: performance optimization.
Browse files Browse the repository at this point in the history
  • Loading branch information
chizukicn committed Jun 1, 2023
1 parent 57e16d3 commit 15affae
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 16 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
coverage
dist
dist-*
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ types
*.log*
*.conf*
*.env*
dist-*
64 changes: 64 additions & 0 deletions bench/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Suite } from "benchmark";
import classnames from "classnames";
import classcat from "classcat";
import clsx from "clsx";
import consola from "consola";
import { cls as old } from "tslx";
import { cls } from "../dist/index.cjs";

function bench(name, ...args) {
consola.log(`\n# ${name}`);
new Suite()
.add("classcat* ", () => classcat.apply(classcat, [args]))
.add("classnames ", () => classnames.apply(classnames, args))
.add("clsx ", () => clsx.apply(clsx, args))
.add("tslx old ", () => old.apply(old, args))
.add("tslx ", () => cls.apply(cls, args))
.on("cycle", e => consola.log(` ${e.target}`))
.run();
}

bench(
"Strings",
"foo", "", "bar", "baz", "bax", "bux"
);

bench(
"Objects",
{ foo: true, bar: true, bax: true, bux: false },
{ baz: true, bax: false, bux: true }
);

bench(
"Arrays",
["foo", "bar"],
["baz", "bax", "bux"]
);

bench(
"Nested Arrays",
["foo", ["bar"]],
["baz", ["bax", ["bux"]]]
);

bench(
"Nested Arrays w/ Objects",
["foo", { bar: true, bax: true, bux: false }],
["bax", { bax: false, bux: true }]
);

bench(
"Mixed",
"foo", "bar",
{ bax: true, bux: false },
["baz", { bax: false, bux: true }]
);

bench(
"Mixed (Bad Data)",
"foo", "bar",
undefined, null, NaN,
() => {},
{ bax: true, bux: false, 123: true },
["baz", { bax: false, bux: true, abc: null }, {}]
);
16 changes: 16 additions & 0 deletions bench/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"private": true,
"scripts": {
"start":"tsx ./index.ts"
},
"devDependencies": {
"benchmark": "^2.1.4",
"classcat": "^3.2.5",
"classnames": "^2.2.6",
"clsx": "1.1.0",
"tslx":"0.0.5"
},
"dependencies": {
"consola": "^3.1.0"
}
}
68 changes: 68 additions & 0 deletions bench/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"prepare": "npx simple-git-hooks",
"preinstall": "npx only-allow pnpm",
"release": "pnpm test && changelogen --release && npm publish --registry=https://registry.npmjs.org && git push --follow-tags",
"test": "pnpm lint && vitest run --coverage"
"test": "pnpm lint && vitest run --coverage",
"bench": "pnpm -C bench start"
},
"dependencies": {
"csstype": "^3.1.2"
Expand All @@ -56,4 +57,4 @@
"npx eslint --cache --fix"
]
}
}
}
34 changes: 22 additions & 12 deletions src/cls.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import { isArray, isObject, isString, unique } from "./shared";
import { isArray, isNumber, isObject, isString } from "./shared";

/**
*
*/
export function classnames(...literals: ClassName[]) {
return unique(literals
.reduce<string[]>((prev, cur) => {
if (isArray(cur)) {
prev.push(...classnames(...cur));
} else if (isString(cur)) {
prev.push(...cur.trim().split(/\s+/));
} else if (isObject(cur)) {
prev.push(...Object.keys(cur).filter((key) => !!cur[key]));
export function classnames(...literals: ClassName[]): string {
return literals
.reduce<string>((prev, cur) => {
if (cur) {
if (isString(cur) || isNumber(cur)) {
prev = prev && `${prev} `;
prev = prev.concat(String(cur));
} else if (isArray(cur)) {
prev = prev && `${prev} `;
prev = prev.concat(classnames(...cur));
} else if (isObject(cur)) {
for (const key in cur) {
if (cur[key]) {
prev = prev && `${prev} `;
prev = prev.concat(key);
}
}
}
}
return prev;
}, [])).filter((item) => !!item);
}, "");
}

/**
Expand All @@ -23,8 +32,9 @@ export function classnames(...literals: ClassName[]) {
export const cls = classnames;

export type ClassName =
| Record<string, boolean | undefined | null>
| Record<string, any>
| string
| number
| undefined
| null
| ClassName[];
2 changes: 1 addition & 1 deletion src/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function isNumber(obj: any): obj is number {
return typeof obj === "number";
}

export function isArray<T>(obj: any): obj is T[] {
export function isArray(obj: any): obj is any[] {
return Array.isArray(obj);
}

Expand Down
2 changes: 1 addition & 1 deletion test/cls.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ test("test classnames", () => {
}, "baz", ["p-4 foo m-3", {
absolute: true,
relative: false
}]).join(" ")).toBe("foo baz p-4 m-3 absolute");
}], null, undefined, NaN)).toBe("foo baz p-4 foo m-3 absolute");
});

0 comments on commit 15affae

Please sign in to comment.