Basically some component examples and 7guis tasks implemented in Angular, Next (React), Nuxt (Vue), SvelteKit (Svelte) and Marko (using the new Tags API).
View live versions for Angular, Next, Nuxt and SvelteKit.
View source code for Angular, Next, Nuxt and SvelteKit.
Below I compare component syntax for these technologies.
- All except Marko are using TypeScript (which gives Marko an advantage in this comparison when it comes to character count, maybe TypeScript should be stripped for all or have a separate comparison)
- Character counts done with VSCode with code formatted using Prettier (with default SvelteKit
.prettierrc
) and with as few empty lines as Prettier allows. - Trying to get the tersest valid syntax that doesn't give framework warnings / ts errors (with framework default tsconfig; might need to unify tsconfigs later).
Click the name of the technology in the tables to view source of each component.
Task: Show the text "Hello World". This is the most minimal component you can make, which lets us closely inspect how the technology deals with components.
Angular | Next | Nuxt | SvelteKit | Marko | |
---|---|---|---|---|---|
character count | 150 | 57 | 33 | 12 | 15 |
component declared as | class with @Component decorator |
function returning JSX | SFC (.vue ) |
SFC (.svelte ) |
SFC (.marko ) |
component imported in | class with @NgModule decorator |
parent component | auto-import | parent component | auto-import |
self closing tag allowed | ❌ | ✅ | ✅ | ✅ | ✅ |
renders w/o wrapper element | ❌ | ✅ | ✅ | ✅ | ✅ |
template / markup | linked / defined inside decorator | JSX, requires fragment | defined in <template> |
defined at top level | defined at top level, two modes available |
01 - Counter
Binding count state in a <span>
and handling click event from a <button>
.
Angular | Next | Nuxt | SvelteKit | Marko | |
---|---|---|---|---|---|
character count | 266 | 258 | 201 | 160 | 97 |
declaring state as | class property | variable + destructuring function call | variable + function call | variable | let tag (variable) |
setting state | mutation of class property | calling function | assigning variable property | assigning variable | assigning variable |
binding state to view | double curly braces | curly braces | double curly braces | curly braces | dollar curly braces |
adding event listener | (click)="increment()" |
> |
@click="increment" or @click="increment()" |
on:click={increment} |
> |
notes | auto-import of Reactivity APIs |
Bidirectional data flow.
Angular | Next | Nuxt | SvelteKit | Marko | |
---|---|---|---|---|---|
character count | 547 | 725 | 478 | 387 | 394 |
two way binding | [(ngModel)]="c" |
none (manually set value on in event listener) | v-model="c" |
bind:value={c} |
none (can't use with event listener) |
notes | can't have undefined initial value; ts requires unary plus |
two way binding would be value:=c ;formatting is off |
03 - Flight Booker
Angular | Next + module.css | Nuxt | SvelteKit | |
---|---|---|---|---|
character count | 1965 | 1454 | 1122 | 985 |
constraints / reactivity | subscribing on FormControl valueChanges + unsubscribing |
variables get re-declared every update | variable + function call | labeled variable |
scoped css | linked / defined inside decorator | imports from .module.css |
defined in <styles scoped> |
defined <styles> |
conditional class | [class.error]="startInvalid" |
className={startInvalid ? styles.error : undefined} |
:class="{ error: startInvalid }" |
class:error={startInvalid} |
class attribute initially | ng-untouched ng-pristine (formControl status) |
6E59 (correctly missing) | (empty) | s-AlKFmgiKvTi_ (css scoping hash) |
[Angular][add-angular] | Next | [Nuxt][add-nuxt] | SvelteKit | Marko (busted) | |
---|---|---|---|---|---|
character count | 442 | 149 | 172 | ||
notes | two way binding doesn't type cast |
Maybe coming in the future:
- custom table component
- Timer
- CRUD
- Circle Drawer
- Cells
- Flux Challenge
- ThreaditJS
Benchmarks with existing examples in all technologies (though partly outdated):