Skip to content

Commit 2f42099

Browse files
committed
Merge branch 'master' into reduce-bundle
2 parents fb6f386 + 3064694 commit 2f42099

File tree

465 files changed

+66067
-35163
lines changed

Some content is hidden

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

465 files changed

+66067
-35163
lines changed

README.md

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ This is a simple benchmark for several javascript frameworks. The benchmarks cre
55

66
![Screenshot](images/screenshot.png?raw=true "Screenshot")
77

8+
## Security advice
9+
10+
Currently there are 186 implemenations in this repository. It's of course impossible for me to make a security assessment
11+
for all those implementations. `npm ci` and `npm install` can execute arbitraty commands, so they should be executed only for packages you trust. Consequently I build on a dedicated virtual private linux server such that I don't have to install the packages for all those implemenations on my laptop. There's a prebuild build.zip for each chrome release you can download such that you can avoid installing the packages from all implementations.
12+
(I don't know of any (attempted) case for malicious packages in this repository, so please take it just as a general warning.)
13+
14+
The server implemenation in this repository should only be started on your local machine and access should be restricted to your local machine. I recommend against starting the server such that it can be publically accessed from the internet.
15+
816
## About the benchmarks
917

1018
The following operations are benchmarked for each framework:
@@ -54,9 +62,9 @@ Depending on your requirements, the “non-keyed” mode can be a performance ga
5462

5563
Read more here: [https://www.stefankrause.net/wp/?p=342](https://www.stefankrause.net/wp/?p=342)
5664

57-
# 1 NEW: Run pre-built binaries for all frameworks
65+
# 1 Run pre-built binaries for all frameworks
5866

59-
There are currently ~60 framework entries in this repository. Installing (and maintaining) those can be challenging, but here are simplified instructions how to get started.
67+
There are currently 186 implementations in this repository. Installing (and maintaining) those can be challenging, but here are simplified instructions how to get started. See the security advice above to read why that might be a good idea.
6068

6169
## 1.1 Prerequisites
6270

@@ -275,11 +283,12 @@ npm run index
275283

276284
## 2.7 [Optional] Building and running the benchmarks for all frameworks
277285

278-
This is not for the faint at heart. You can build all frameworks simply by issuing:
286+
This is not for the faint at heart. **Please read the security advice before running this command.**
287+
You can build all frameworks by issuing:
279288

280289
```
281290
cd ..
282-
npm run build-prod
291+
npm run rebuild-all
283292
```
284293

285294
After downloading the whole internet it starts building it. Basically there should be no errors during the build, but I can't guarantee that the dependencies won't break.
@@ -511,6 +520,10 @@ You can set an optional different URL if needed or specify that your DOM uses a
511520
512521
## 4.4 Submitting your implementation
513522
523+
Please take a look at https://github.com/krausest/js-framework-benchmark/wiki/Process-for-merging-a-pull-request for informations how pull requests are merged.
524+
525+
526+
514527
Contributions are very welcome. Please use the following rules:
515528
516529
- Name your directory frameworks/[keyed|non-keyed]/[FrameworkName]
@@ -522,7 +535,7 @@ Contributions are very welcome. Please use the following rules:
522535
- Webdriver-ts must be able to run the perf tests for the contribution. This means that all buttons (like "Create 1,000 rows") must have the correct id e.g. like in vanillajs. Using shadow DOM is a real pain for webdriver. The closer you can get to polymer the higher the chances I can make that contribution work.
523536
- Don't change the ids in the index.html, since the automated benchmarking relies on those ids.
524537
- Please push only files in your framework folder (not index.html or results.json)
525-
- **Please make sure your implementation is validated by the test tool.** cd to webdriver-ts and invoke it with `npm run isKeyed [keyed|non-keyed]/[FrameworkName]`. It'll print an error if your framework behaves other as specified. It'll print a big ERROR explaining if it isn't happy with the implementation. Some common errors include:
538+
- **Please make sure your implementation is validated by the test tool.** cd to the root directory and perform a check `npm run rebuild-ci [keyed|non-keyed]/[FrameworkName]`. It'll print an error if your framework doesn't build, the benchmark can't be run or behaves other as specified. It'll print a big ERROR explaining if it isn't happy with the implementation. Some common errors include:
526539
- Your package.json is missing some required fields
527540
- Incorrect classification (Keyed/NonKeyed)
528541
- You have gzipped files in /dist (unfortunately the web server prefers these when they exist)
@@ -551,23 +564,30 @@ Thanks to Baptiste Augrain for making the benchmarks more sophisticated and addi
551564
552565
Frameworks without significant activity on github or npm for more than a year will be removed (_automatic commits like dependabot and minor updates, like docs editions, are ignored_).
553566
567+
## 2023-11-07
568+
The following frameworks were archived after chrome 119. Their last results are included in [chrome 119 results](https://krausest.github.io/js-framework-benchmark/2023/table_chrome_119.0.6045.105.html).
569+
- [x] sifrr
570+
571+
554572
## 2023-10-22
555573
The following frameworks were archived after chrome 118. Their last results are included in [chrome 118 results](https://krausest.github.io/js-framework-benchmark/2023/table_chrome_118.0.5993.70.html).
556574
- [x] 1more
575+
- [x] bdc
576+
- [x] choo
557577
- [x] domdiff
558578
- [x] domvm
559579
- [x] endorphin
560580
- [x] etch
581+
- [x] forgo
582+
- [x] fullweb-helpers
583+
- [x] fullweb-template
561584
- [x] heresy
585+
- [x] hullo
562586
- [x] lighterhtml
563587
- [x] neverland
564588
- [x] resonatejs
565589
- [x] sledgehammer
566590
- [x] uhydro
567-
- [x] fullweb-helpers
568-
- [x] fullweb-template
569-
- [x] forgo
570-
- [x] choo
571591
572592
573593
## 2020-7-9

cli/check-obsolete.js

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ const frameworks = getFrameworks();
2020
*/
2121
function findDuplicateFrameworks(frameworks) {
2222
const names = frameworks.map((framework) => framework.name); // Creates an array with framework names only
23-
const duplicateNames = names.filter(
24-
(name, index) => names.indexOf(name) !== index,
25-
); // Filters out repetitive framework names
23+
const duplicateNames = names.filter((name, index) => names.indexOf(name) !== index); // Filters out repetitive framework names
2624

2725
return duplicateNames;
2826
}
@@ -59,11 +57,7 @@ function maybeObsolete(packageName) {
5957
}
6058

6159
const now = new Date();
62-
const obsoleteDate = new Date(
63-
now.getFullYear() - 1,
64-
now.getMonth(),
65-
now.getDay(),
66-
);
60+
const obsoleteDate = new Date(now.getFullYear() - 1, now.getMonth(), now.getDay());
6761

6862
const modifiedDate = new Date(timeData.modified);
6963
const isObsolete = modifiedDate < obsoleteDate;
@@ -72,7 +66,7 @@ function maybeObsolete(packageName) {
7266
return { isObsolete, lastUpdate: formattedDate, packageName };
7367
} catch (error) {
7468
console.error(
75-
`Failed to execute npm view for ${packageName}. Error Code ${error.status} and message: ${error.message}`,
69+
`Failed to execute npm view for ${packageName}. Error Code ${error.status} and message: ${error.message}`
7670
);
7771
return { isObsolete: false, lastUpdate: null, packageName };
7872
}
@@ -95,15 +89,12 @@ function checkObsoleteFrameworks(options) {
9589
const packageJSONPath = path.join(frameworkPath, "package.json");
9690

9791
if (!fs.existsSync(packageJSONPath)) {
98-
missingPackageWarnings.push(
99-
`WARN: skipping ${type}/${name} since there's no package.json`,
100-
);
92+
missingPackageWarnings.push(`WARN: skipping ${type}/${name} since there's no package.json`);
10193
continue;
10294
}
10395

10496
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, "utf-8"));
105-
const mainPackages =
106-
packageJSON?.["js-framework-benchmark"]?.frameworkVersionFromPackage;
97+
const mainPackages = packageJSON?.["js-framework-benchmark"]?.frameworkVersionFromPackage;
10798

10899
if (!mainPackages) {
109100
manualChecks.push(`${type}/${name} has no frameworkVersionFromPackage`);
@@ -121,35 +112,25 @@ function checkObsoleteFrameworks(options) {
121112
console.log(`Results for ${type}/${name} ${isPackageObsolete}`);
122113
}
123114

124-
const anyPackageObsolete = isPackageObsolete.some(
125-
(packageFramework) => packageFramework.isObsolete,
126-
);
115+
const anyPackageObsolete = isPackageObsolete.some((packageFramework) => packageFramework.isObsolete);
127116

128117
if (anyPackageObsolete) {
129118
const formattedPackages = isPackageObsolete
130119
.map((result) => `${result.packageName}:${result.lastUpdate}`)
131120
.join(", ");
132121

133-
console.log(
134-
`Last npm update for ${type}/${name} - ${mainPackages} is older than a year: ${formattedPackages}`,
135-
);
122+
console.log(`Last npm update for ${type}/${name} - ${mainPackages} is older than a year: ${formattedPackages}`);
136123
continue;
137124
}
138125

139126
if (DEBUG) {
140-
console.log(
141-
`Last npm update for ${type}/${name} ${mainPackages} is newer than a year`,
142-
);
127+
console.log(`Last npm update for ${type}/${name} ${mainPackages} is newer than a year`);
143128
}
144129
}
145130

146-
if (missingPackageWarnings.length > 0)
147-
console.warn("\nWarnings:\n" + missingPackageWarnings.join("\n"));
131+
if (missingPackageWarnings.length > 0) console.warn("\nWarnings:\n" + missingPackageWarnings.join("\n"));
148132
if (manualChecks.length > 0)
149-
console.warn(
150-
"\nThe following frameworks must be checked manually\n" +
151-
manualChecks.join("\n"),
152-
);
133+
console.warn("\nThe following frameworks must be checked manually\n" + manualChecks.join("\n"));
153134
}
154135

155136
export { checkObsoleteFrameworks };

cli/cleanup.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
import * as fs from "node:fs";
22
import path from "node:path";
33

4-
const filesToDelete = [
5-
"package-lock.json",
6-
"yarn-lock",
7-
"dist",
8-
"elm-stuff",
9-
"bower_components",
10-
"node_modules",
11-
];
4+
const filesToDelete = ["package-lock.json", "yarn-lock", "dist", "elm-stuff", "bower_components", "node_modules"];
125

136
/**
147
* Delete specified files in the framework directory

cli/configure-styles.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ async function copyAndGenerateSharedStyles(sourceCss, mainCss) {
1212
const sharedStylesContent = `<dom-module id="shared-styles"><template><style>${mainCssContent}</style></template></dom-module>`;
1313

1414
// Write shared-styles.html
15-
await fs.promises.writeFile(
16-
path.join("polymer-v2.0.0-non-keyed", "src", "shared-styles.html"),
17-
sharedStylesContent,
18-
);
15+
await fs.promises.writeFile(path.join("polymer-v2.0.0-non-keyed", "src", "shared-styles.html"), sharedStylesContent);
1916
}
2017

2118
/**
@@ -37,13 +34,10 @@ async function configureStyles(options) {
3734
if (bootstrap) {
3835
await copyAndGenerateSharedStyles(
3936
path.join("css", "useOriginalBootstrap.css"),
40-
path.join("css", "bootstrap", "dist", "css", "bootstrap.min.css"),
37+
path.join("css", "bootstrap", "dist", "css", "bootstrap.min.css")
4138
);
4239
} else {
43-
await copyAndGenerateSharedStyles(
44-
path.join("css", "useMinimalCss.css"),
45-
path.join("css", "useMinimalCss.css"),
46-
);
40+
await copyAndGenerateSharedStyles(path.join("css", "useMinimalCss.css"), path.join("css", "useMinimalCss.css"));
4741
}
4842
} catch (error) {
4943
console.error("An error occurred:", error.message);

cli/copy.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function shouldInclude(name) {
1717
const isTargetWeb = name.includes("/target/web");
1818

1919
console.log(
20-
`File: ${name}\nIs Binding Scala: ${isBindingScala}\nIs Target: ${isTarget}\nIs Target Web: ${isTargetWeb}`,
20+
`File: ${name}\nIs Binding Scala: ${isBindingScala}\nIs Target: ${isTarget}\nIs Target Web: ${isTargetWeb}`
2121
);
2222

2323
if (isTarget) {
@@ -72,15 +72,10 @@ function copyFolderRecursiveSync(sourcePath, destinationPath) {
7272
*/
7373
function processDirectories() {
7474
const directories = fs.readdirSync(".");
75-
const nonHiddenDirectories = directories.filter(
76-
(directory) => !directory.startsWith("."),
77-
);
75+
const nonHiddenDirectories = directories.filter((directory) => !directory.startsWith("."));
7876

7977
for (const directory of nonHiddenDirectories) {
80-
if (
81-
fs.statSync(directory).isDirectory() &&
82-
!rootExclude.includes(directory)
83-
) {
78+
if (fs.statSync(directory).isDirectory() && !rootExclude.includes(directory)) {
8479
const dirPath = path.join("dist", directory);
8580
console.log(dirPath);
8681
fs.mkdirSync(dirPath);
@@ -97,10 +92,7 @@ function copyProjectToDist() {
9792
fs.rmSync("dist", { force: true, recursive: true });
9893
fs.mkdirSync(path.join("dist", "webdriver-ts"), { recursive: true });
9994

100-
fs.copyFileSync(
101-
path.join("webdriver-ts", "table.html"),
102-
path.join("dist", "webdriver-ts", "table.html"),
103-
);
95+
fs.copyFileSync(path.join("webdriver-ts", "table.html"), path.join("dist", "webdriver-ts", "table.html"));
10496
fs.copyFileSync("index.html", path.join("dist", "index.html"));
10597

10698
processDirectories();
Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,6 @@
11
import { execSync } from "node:child_process";
22
import * as fs from "node:fs";
33
import path from "node:path";
4-
import yargs from "yargs";
5-
6-
const args = yargs(process.argv.slice(2))
7-
.usage("$0 [--ci keyed/framework1 ... non-keyed/frameworkN]")
8-
.boolean("ci")
9-
.default("ci", false)
10-
.describe("ci", "Use npm ci or npm install ?")
11-
.argv;
12-
13-
/**
14-
* Use npm ci or npm install?
15-
* @type {boolean}
16-
*/
17-
const useCi = args.ci;
18-
19-
/**
20-
* @type {string}
21-
*/
22-
const frameworks = args._.filter((arg) => !arg.startsWith("--"));
23-
24-
console.log(
25-
"rebuild-build-single.js started: args",
26-
args,
27-
"useCi",
28-
useCi,
29-
"frameworks",
30-
frameworks
31-
);
32-
33-
const filesToDelete = [
34-
"yarn-lock",
35-
"dist",
36-
"elm-stuff",
37-
"bower_components",
38-
"node_modules",
39-
"output",
40-
].concat(useCi ? [] : ["package-lock.json"]);
414

425
/*
436
rebuild-single.js [--ci] [keyed/framework1 ... non-keyed/frameworkN]
@@ -55,7 +18,7 @@ Pass list of frameworks
5518
/**
5619
* Run a command synchronously in the specified directory and log command
5720
* @param {string} command - The command to run
58-
* @param {string} cwd - The current working directory (optional)
21+
* @param {string|undefined} cwd - The current working directory (optional)
5922
*/
6023
function runCommand(command, cwd = undefined) {
6124
console.log(command);
@@ -82,43 +45,53 @@ function deleteFrameworkFiles(frameworkPath, filesToDelete) {
8245

8346
/**
8447
* @param {string} framework
48+
* @param {boolean} useCi
8549
*/
86-
function rebuildFramework(framework) {
50+
function rebuildFramework(framework, useCi) {
8751
const components = framework.split("/");
8852

8953
if (components.length !== 2) {
90-
console.log(
91-
`ERROR: invalid name ${framework}. It must contain exactly one /.`
92-
);
54+
console.log(`ERROR: invalid name ${framework}. It must contain exactly one /.`);
9355
process.exit(1);
9456
}
9557

9658
const [keyed, name] = components;
9759
const frameworkPath = path.join("frameworks", keyed, name);
9860

61+
const filesToDelete = [
62+
"yarn-lock",
63+
"dist",
64+
"elm-stuff",
65+
"bower_components",
66+
"node_modules",
67+
"output",
68+
].concat(useCi ? [] : ["package-lock.json"]);
69+
9970
deleteFrameworkFiles(frameworkPath, filesToDelete);
10071

10172
const installCmd = `npm ${useCi ? "ci" : "install"}`;
10273
runCommand(installCmd, frameworkPath);
10374

10475
const buildCmd = "npm run build-prod";
10576
runCommand(buildCmd, frameworkPath);
106-
10777
}
10878

109-
function rebuildFrameworks() {
79+
/**
80+
* @param {string[]} frameworks
81+
* @param {boolean} useCi
82+
*/
83+
export function rebuildFrameworks(frameworks, useCi) {
84+
console.log("rebuild-build-single.js started: useCi", useCi, "frameworks", frameworks);
85+
11086
if (!frameworks.length) {
111-
console.log(
112-
"ERROR: Missing arguments. Command: rebuild keyed/framework1 non-keyed/framework2 ..."
113-
);
87+
console.log("ERROR: Missing arguments. Command: rebuild keyed/framework1 non-keyed/framework2 ...");
11488
process.exit(1);
11589
}
11690

11791
for (const framework of frameworks) {
118-
rebuildFramework(framework);
92+
rebuildFramework(framework, useCi);
11993
}
12094

12195
console.log("rebuild-build-single.js finished: Build finsished sucessfully!");
12296
}
12397

124-
rebuildFrameworks();

0 commit comments

Comments
 (0)