Skip to content

Commit 4083853

Browse files
committed
Update README.md to make it a bit easier to add a new framework/implementation
1 parent 5d4158f commit 4083853

File tree

2 files changed

+134
-3
lines changed

2 files changed

+134
-3
lines changed

README.md

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,137 @@ After that you can check all results in [http://localhost:8080/webdriver-ts/tabl
294294

295295
## 4. Contributing a new implementation
296296

297+
## TL;DR
298+
1. Install all of the root-level dependencies
299+
1. `cd js-framework-benchmark/`
300+
1. `npm ci` or `npm i`
301+
2. Make a new directory for your desired framework, for example Fast framework: `mkdir /frameworks/keyed/fast`
302+
3. Set up your new directory in whatever way is appropriate for that framework, for example:
303+
1. Set up prettier, eslint, dependencies (i.e. `@microsoft/fast-element`) etc
304+
2. Create `index.html` in the root of your folder where your app will be served `touch /frameworks/keyed/fast/index.html`
305+
3. Note: your html file must use the global CSS styles `<link href="/css/currentStyle.css" rel="stylesheet" />`
306+
4. Serve the page - Test that your html page is loaded properly in the browser
307+
1. For example put <h1>Hello World - Fast Framework</h1> somewhere
308+
2. Run the server from the root directory: `npm start`
309+
3. Visit your page in the browser (URL follows the folder structure): `http://localhost:8080/frameworks/keyed/fast/index.html`
310+
4. Note: Its important to always start the server from the root, because that way you'll get access to global CSS that all apps must share
311+
5. Add the "action triggers" - buttons that all apps must have (see `frameworks/keyed/vanillajs/index.html`)
312+
1. Note: Action triggers are simply buttons that are used to run the benchmarks (adding rows, deleting rows, swapping them, etc). Those buttons can be static HTML, or you can render them with your framework of choice
313+
2. Make sure your HTML elements have the same classes and structure as VanillaJS, otherwise benchmarks won't be able to find your elements on the page, and you will not get the global CSS (Bootstrap)
314+
3. Add the html example below and open the page. You should see nicely formatted elements on the page, like in the GIF image below.
315+
4. Example for action triggers
316+
```html
317+
<body>
318+
<div id="main">
319+
<div class="container">
320+
<div class="jumbotron">
321+
<div class="row">
322+
<div class="col-md-6">
323+
<h1>VanillaJS-"keyed"</h1>
324+
</div>
325+
<div class="col-md-6">
326+
<div class="row">
327+
<div class="col-sm-6 smallpad">
328+
<button
329+
type="button"
330+
class="btn btn-primary btn-block"
331+
id="run"
332+
>
333+
Create 1,000 rows
334+
</button>
335+
</div>
336+
<div class="col-sm-6 smallpad">
337+
<button
338+
type="button"
339+
class="btn btn-primary btn-block"
340+
id="runlots"
341+
>
342+
Create 10,000 rows
343+
</button>
344+
</div>
345+
<div class="col-sm-6 smallpad">
346+
<button
347+
type="button"
348+
class="btn btn-primary btn-block"
349+
id="add"
350+
>
351+
Append 1,000 rows
352+
</button>
353+
</div>
354+
<div class="col-sm-6 smallpad">
355+
<button
356+
type="button"
357+
class="btn btn-primary btn-block"
358+
id="update"
359+
>
360+
Update every 10th row
361+
</button>
362+
</div>
363+
<div class="col-sm-6 smallpad">
364+
<button
365+
type="button"
366+
class="btn btn-primary btn-block"
367+
id="clear"
368+
>
369+
Clear
370+
</button>
371+
</div>
372+
<div class="col-sm-6 smallpad">
373+
<button
374+
type="button"
375+
class="btn btn-primary btn-block"
376+
id="swaprows"
377+
>
378+
Swap Rows
379+
</button>
380+
</div>
381+
</div>
382+
</div>
383+
</div>
384+
</div>
385+
<table class="table table-hover table-striped test-data">
386+
<!-- your dynamic content should render here -->
387+
</table>
388+
</div>
389+
</div>
390+
</body>
391+
```
392+
6. Generate dummy data for rendering
393+
1. See `frameworks/keyed/fast/src/utils/build-dummy-data.ts` as an example
394+
2. Note: `id` is an important attribute and it must be initialized as `1`, and continuously incremented. The only time `id` resets back to `1` is when the page reloads - otherwise it should just keep incrementing each time a new row is created. Doing anything else will cause errors when benchmarks try to find elements with specific IDs. Trust me, I learned the hard way.
395+
7. . Your app needs to support several actions that correspond to "Action triggers" listed above. Here's an example from Fast framework:
396+
1. Code example:
397+
```typescript
398+
export class BenchmarkApp extends FASTElement {
399+
createOneThousandRows() {}
400+
createTenThousandRows() {}
401+
appendOneThousandRows() {}
402+
updateEveryTenthRowLabel() {}
403+
deleteAllRows() {}
404+
swapTwoRows() {}
405+
deleteSingleRow(rowId: number) {}
406+
}
407+
```
408+
2. Note: your app doesn't need methods with the same name - you should write idiomatic code and follow the best practices of your framework of choice. The example above is just to give you an idea of which operations must be supported, but how you choose to implement those methods can be very different from one framework to the next.
409+
8. Manually testing your app - do this before you run the benchmarks
410+
1. Open your page and click on the buttons, make sure your app adds 1000 rows, then removes them, or swaps them, or adds/removes 10,000 rows.
411+
2. To do this, you'll probably need to watch your local files and compile them into some sort of a bundle, like `frameworks\keyed\fast\dist\bundle.js` which will be loaded through a script tag in your HTML file
412+
3. For example, in Fast folder we have webpack watching our files: ` "build-dev": "rimraf dist && webpack --config webpack.config.js --watch --mode=development",`
413+
4. That means we have two terminal tabs running
414+
1. One for the server from the root folder `npm start`
415+
2. And another in our local folder where webpack is watching the files
416+
9. Run the single benchmark for your framework
417+
1. Once you manually verified that everything works as expected, run a single benchmark and make sure all of the tests are running
418+
2. If you forgot something, one of the benchmarks will probably fail - for example it won't be able to find an element on the page or similar
419+
3. Keep the server in the root folder running `npm start`, and in another terminal tab, also from the root folder run `npm run bench -- --framework keyed/fast` (or whatever is your framework `keyed/react`, `keyed/angular`, etc.).
420+
4. The benchmark runner will open and close Chrome multiple times. The whole thing will take a couple of minutes.
421+
10. Optional: run the benchmark for VanillaJS as comparison
422+
1. ` npm run bench -- --framework keyed/vanillajs`
423+
11. Build the report
424+
1. `npm run results`
425+
12. Open the report in your browser (NOTE: the server must still be running if you want to see this page)
426+
1. `http://localhost:8080/webdriver-ts-results/table.html`
427+
297428
## 4.1 Building the app
298429

299430
For contributions it is basically sufficient to create a new directory for your framework that supports `npm install` and `npm run build-prod` and can be then opened in the browser. All other steps are optional. Let's simulate that by copying vanillajs.

frameworks/keyed/fast/src/App.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export class BenchmarkApp extends FASTElement {
5050
backupData?: RowItem[];
5151

5252
createOneThousandRows() {
53-
this.clear();
53+
this.deleteAllRows();
5454
this.rows = buildData();
5555
}
5656

@@ -72,7 +72,7 @@ export class BenchmarkApp extends FASTElement {
7272
this.triggerRerender();
7373
}
7474

75-
clear() {
75+
deleteAllRows() {
7676
this.rows = [];
7777
}
7878

@@ -106,7 +106,7 @@ export class BenchmarkApp extends FASTElement {
106106
if (name === 'run') return this.createOneThousandRows();
107107
if (name === 'update') return this.updateEveryTenthRowLabel();
108108
if (name === 'runlots') return this.createTenThousandRows();
109-
if (name === 'clear') return this.clear();
109+
if (name === 'clear') return this.deleteAllRows();
110110
if (name === 'swaprows') return this.swapTwoRows();
111111
if (name === 'deleteSingleRow') return this.deleteSingleRow(data);
112112

0 commit comments

Comments
 (0)