Man in bos in de verenigde staten

React vs. Vue.js in 2020 maakt het nog uit?

Een paar jaar geleden had ik een sterke voorkeur voor Vue.js, vergeleken met andere frameworks zoals React, Ember of Angular. Vue was vergeleken met React overzichtelijker, makkelijker te leren, had een beter open source licentiemodel, betere documentatie, en was groot genoeg gegroeid om een levensvatbare community met stabiele packages te onderhouden. De afgelopen maanden werkte ik aan twee projecten, een op basis van Vue.js, de ander gebouwd met React. Een uitgelezen kans om eens de balans op te maken: Hoe staat het ervoor met deze frameworks, waar word ik blij van als ontwikkelaar, waar kan ik onze klanten het best mee bedienen… en maakt het sowieso nog uit?

De setup van een nieuw project is voor beide systemen erg vergelijkbaar als je de bijbehorende scaffolding tool gebruikt. Of je nu npx create-react-app of vue create draait, er is weinig verschil. Je krijgt een basis directory structuur, uitgerust met package manager, build- en develop-tasks, Webpack, Babel, ESlint, Autoprefixer en nog meer. De Vue CLI generator biedt wat meer opties die je kan configureren. Beide systemen kennen een concept van plugins/templates om de generator aan te passen naar je eigen smaak, als je het belangrijk vindt om dat eigen smaakje te automatiseren. Je kan hoe dan ook snel van start met bouwen.

React

React heeft verschillende manieren om componenten te definiëren. De meer moderne (en m.i. beter leesbare manier) is om function components te schrijven ipv. class components. Dat houdt in dat je een component maakt door simpelweg een JavaScript functie te schrijven. Function components hadden voorheen nog beperkingen, maar met de introductie van “hooks” in React 16.8 is dat geen issue meer.

React gebruikt JSX, een variant op JavaScript die het geschikt maakt om HTML markup met dynamische JS code te combineren. Ook CSS wordt vaak met JS gegenereerd, waardoor het wellicht niet direct vertrouwd aanvoelt voor frontend developers die gewend zijn om CSS of Sass code te schrijven.

Als je React-component gebruikt maakt van sub-components die verder niet herbruikbaar hoeven te zijn, kan je die gewoon bundelen in hetzelfde bestand. Denk bijvoorbeeld aan een situatie waar een ToDoList component een lijst opbouwt van ToDoItem components. Als je het ToDoItem niet ergens anders wil hergebruiken, kan je gerust in hetzelfde bestand bundelen.

Al met al biedt React flexibiliteit maar soms ook verwarring over wat nu de “juiste” manier is. Dat effect wordt nog versterkt doordat het maar al te makkelijk is om verouderde technieken terug te vinden in blogposts, StackOverflow antwoorden en NPM packages. Het is zinvol om daar als tech lead een keuze in te maken om zo wat consistentie af te dwingen.

Vue

Hoewel er voor een speciale gevallen ook andere methodes zijn, zal je in Vue vooral componenten schrijven in de vorm van “Single File Components” (SFC). Dat is een enkel bestand waarin 3 afzonderlijke delen los van elkaar te herkennen zijn: een <template> voor de HTML markup (met wat toevoegingen voor bv. dynamische data en loops), <script> voor al je JavaScript (bijvoorbeeld dynamische data en interactie), en optioneel <style> voor CSS (of Sass / Scss). Dit nodigt het automatisch uit tot een nette scheiding van structuur, gedrag en vorm. Bovendien draagt het eraan bij dat veel developers, waaronder ikzelf, een minder steile learning curve zeggen te ervaren bij Vue. Er is namelijk minder twijfel over welke code waar hoort en de code die je schrijft lijkt mogelijk meer op wat je al kent.

In tegenstelling tot React heeft Vue geen elegante oplossing voor sub-components in hetzelfde bestand. Dus ook als je ToDoItem component onlosmakelijk verbonden is aan je ToDoList, maak je er een apart bestand voor. Of dat een nadeel is, mag de lezer zelf beslissen; Het voelt soms een beetje omslachtig, maar omwille van consistentie valt er zeker ook wat voor te zeggen voor een strikte toepassing van de “1 component = 1 file” logica.

Voorbeelden

Ter vergelijk twee eenvoudige, gelijkwaardige componenten in React en Vue. Hierbij gaan we er vanuit dat een array met ToDo objecten wordt meegegeven aan dit component. Je ziet duidelijk hoe het React component een enkele JS functie is, terwijl het Vue component uit twee delen bestaat.

Voorbeeld ToDo component voor React

 

Voorbeeld ToDo component voor Vue.js

 

Virtual DOM

Om een webpagina te tonen, zal een browser “onder de motorkap” een schematisch model opbouwen van de structuur van de pagina. Dit wordt de Document Object Model (DOM) genoemd. JavaScript frameworks doen hun werk door wanneer nodig de DOM te veranderen. Het manipuleren van de DOM kost wel rekenkracht van de computer, dus moet zo efficient mogelijk gebeuren.

Vue en React gebruiken het “Virtual DOM” principe om de pagina op te bouwen, te bepalen welke delen veranderd zijn, en alleen die delen in de DOM bij te werken. Een vergelijking van beide frameworks op vuejs.org beschrijft het verschil tussen de twee implementaties: "In React, when a component’s state changes, it triggers the re-render of the entire component sub-tree, starting at that component as root. […] In Vue, a component’s dependencies are automatically tracked during its render, so the system knows precisely which components actually need to re-render when state changes."

Met andere woorden, als de data in component X verandert, zal React normaliter alle onderliggende components ook opnieuw renderen. Vue probeert daar slimmer mee om te gaan. In React kan je wel het onnodig re-renderen van components voorkomen, bv. met React.memo. Vue kan dat automatisch omdat je in een component expliciet de data, components en props definieert waar je component van afhankelijk is. (Voor wie een achtergond heeft in Drupal: dat is een beetje zoals je in Drupal cacheability metadata toevoegt aan je render array). Vergelijkende tests laten zien dat de performance van Vue, mede hierdoor, iets beter is dan die van React. De ontwikkelaars van Vue claimen bovendien dat Vue versie 3 (verwacht: eind Q2 2020) nog sneller is op dit vlak.

Styling

Beide frameworks zijn sterk gericht op componenten die zowel qua functie als vormgeving op zichzelf kunnen staan. Dat is een concept dat zeer behulpzaam is voor frontend developers en het stimuleert om goed na te denken over de architectuur van de site. Tegelijk zijn er altijd dingen die je niet per component, maar site-wide wil definiëren. Denk bv. aan tekstgrootte of kleuren. Binnen Drupal projecten gebruiken we daarvoor vaak Sass. Vue biedt uitstekende ondersteuning voor Sass binnen het <style> gedeelte van een SFC, dus al die ervaring en code kan worden meegenomen naar een Vue project. Binnen React projecten is de ondersteuning voor Sass veel minder, en omdat het hele systeem toch al veel sterker op JavaScript gebaseerd is, ligt het voor de hand om daar gebruik te maken van de populaire Styled Components package. Veel van de concepten die we van Sass kennen, zoals geneste selectors, variabelen, functies en mixins, kunnen ook met Styled Components in JavaScript toegepast worden.

Styling met Styled Components in React is even wennen, maar het is zeker goed te doen. Grappig genoeg bleek het voor mij soms ook een nadeel dat de Sass ondersteuning in Vue zo goed is, want de verleiding is groot om veel te veel standaardcode te kopiëren uit eerdere projecten, terwijl je veel minder technical debt opbouwt als je met een frisse blik en een lege bladzijde ergens aan begint.

Ecosysteem

Zowel Vue als React hebben een gezond ecosysteem van plugins. De paralellen met de welbekende Wordpress-vs-Drupal vergelijkingen zijn sterk. Het systeem dat groter is in gebruikersaantal, React, heeft ook een veel groter aantal packages dat daarvoor geschreven is. De community achter Vue is echter ook groot genoeg om kant en klare code te kunnen bieden voor veelgebruikte functionaliteit. Het grote aantal React plugins betekent ook dat het soms moeilijk kiezen is, en de snelle ontwikkeling van het React framework zorgt ervoor dat je wat vaker verouderde code tegenkomt.

React kent een tweetal plugins, Redux en React Router, die zo veel gebruikt worden dat ze de de facto standaard zijn geworden voor respectievelijk state management en routing. Toch zijn het losstaande packages, met hun eigen maintainers, release cycle, websites en documentatie. Bij Vue worden vergelijkbare packages, Vuex en Vue Router, onderhouden door het Vue core team zelf. Dat laatste pleit wat mij betreft voor Vue, zeker als je ziet hoe enorm verschillend de documentatie van de diverse packages kan zijn.

React en Vue zijn kunnen direct ingezet worden als flexibele basis voor een web applicatie, maar zijn ook een goede basis gebleken voor meer gefocuste frameworks. Zoals de React community Gatsby en Next heeft opgeleverd, zijn er Nuxt en Gridsome voor Vue.js. Deze systemen kunnen helpen om nog sneller vaak gebruikte functies neer te zetten. Doordat ze elkaar goed in de gaten houden, bieden ze in grote lijnen dezelfde mogelijkheden.

Toekomst

Zoals gezegd wordt binnen afzienbare tijd Vue 3 verwacht. Daar zitten een paar flinke toevoegingen in waar veel mensen in de Vue community erg enthousiast over zijn — hoewel er initieel ook weerstand was. De belangrijkste daarvan is wellicht de Composition API, die het makkelijker moet maken om logica te groeperen, afscheiden en hergebruiken tussen verschillende components. Ook wordt Vue 3 geschreven in typescript, wat de codekwaliteit ten goede kan komen. Tegelijkertijd is het moeilijk te zeggen hoe lang het zal duren voordat Vue 3 echt voldoende ondersteund wordt binnen het ecosysteem. Ik kijk zelf uit naar Vue 3, maar voor de nabije toekomst lijkt React een veiliger keuze.

De updates van React hebben een hoger tempo en ook minor versions kunnen significante uitbreidingen bevatten. Dat zorgt ervoor dat je goed moet opletten hoe oud een artikel / blogpost / Q&A is als je iets opzoekt op internet. Het heeft er echter ook voor gezorgd dat ik inmiddels een stuk positiever ben over React dan voorheen, want function components en hooks werken prettig.

Conclusie

Drie jaar geleden had ik een sterke voorkeur voor Vue ipv. React, maar er is veel veranderd. De switch van React naar een MIT licentie vond ik persoonlijk belangrijk, zeker ook voor de integratie met open source projecten als Drupal. Maar ook de developer experience is wat mij betreft vooruit gegaan en de learning curve lijkt minder steil — al is het onmogelijk voor mij om dat echt te beoordelen, omdat iets maar één keer echt nieuw kan zijn. Tegelijk heeft Vue zich minder snel ontwikkeld dan ik misschien gehoopt had. Door de performance en de Single File Components heb ik nog een lichte voorkeur voor de technische kant van Vue en de toekomstplannen zijn veelbelovend. Misschien kan Vue het voordeel weer verder uitbouwen, maar de toekomst zal moeten uitwijzen hoe zich dat gaat verhouden tot de overmacht die React momenteel heeft.

 

Photo by Caleb Jones on Unsplash