Node.js installeren: knoppen zonder browser op de server controleren

Om JavaScript op een server uit te voeren, moet je eerst Node.js installeren. Ik heb Node.js 24.21.0 geïnstalleerd op een WordPress-server met Nginx en Apache en met jsdom 30.1.3 zonder browser het knopscript van een webpagina gecontroleerd.
De nodejs in de standaardrepository is 16.20.2, maar jsdom 30.1.3, dat ik voor de scriptcontrole gebruik, vereist Node.js 22.22.2 of hoger. Daarom heb ik geïnstalleerd via dnf-modulestream 24.
1️⃣ Waarom Node.js en jsdom op de server installeren
Om knopscripts op een server te controleren heb je twee dingen nodig: Node.js en jsdom.
🔲 Node.js
JavaScript draait normaal gesproken in de browser, maar met Node.js kan ook de server JavaScript lezen en uitvoeren.
Node.js installeren betekent dat je de JavaScript-runtime die alleen in de browser zat, ook op de server zet. Daarom gebruik je Node.js om webservers te bouwen, commando’s te maken die veel bestanden tegelijk verwerken, of pakketten zoals jsdom te laden en pagina’s te controleren. Ook Ghost is een CMS dat op Node.js draait.
🔲 jsdom
jsdom is een pakket voor Node.js dat HTML inleest en er een document van maakt waarin je net als in een browser op knoppen kunt drukken. Het bouwt de documentstructuur (DOM) die een browser maakt bij het openen van een pagina, zonder scherm na in de server, zodat scripts knoppen vinden en tekst wijzigen alsof ze in een echte browser draaien. Omdat er geen venster opengaat, kun je het op de server met één commando uitvoeren.
Met andere woorden: de controles die iemand deed door een browser te openen en alles één voor één aan te klikken, neemt de server met een commando over. Daarom wordt jsdom ook gebruikt om knopgedrag na elke aanpassing automatisch te testen, alleen inhoud zoals titels en links uit een pagina te halen of de HTML van berichten in één keer bij te werken.
Haal je een pagina op met PHP of curl, dan zie je alleen de HTML die als eerste binnenkomt. Tekst die verandert nadat je op een knop drukt, verschijnt pas als het script draait.
Een browser doorloopt vier stappen: pagina ophalen, pagina lezen, op de knop drukken en op het scherm tonen. jsdom voert alle stappen behalve het tonen op de server uit, dus positie en grootte van een knop controleer je in de browser.
2️⃣ Vóór de installatie: standaardrepository en modulestreams
Controleer vóór [dnf install nodejs] eerst welke versie er geïnstalleerd zou worden. De nodejs in de standaardrepository van AlmaLinux 9.8 is 16.20.2.
dnf list --available nodejsAvailable Packages
nodejs.x86_64 1:16.20.2-8.el9_4 appstreamDe modulerepository heeft vier streams: 18, 20, 22 en 24. Op de controledatum stond stream 22 op 22.23.2 en stream 24 op 24.21.0.
dnf module list nodejsnodejs 18 common [d], development, minimal, s2i Javascript runtime
nodejs 20 common [d], development, minimal, s2i Javascript runtime
nodejs 22 common [d], development, minimal, s2i Javascript runtime
nodejs 24 common [d], development, minimal, s2i Javascript runtimeVolgens de npm-registry vereist jsdom 30.1.3 in de 22-reeks 22.22.2 of hoger, in de 24-reeks 24.15.0 of hoger, of 26 en hoger. Zowel stream 22 als stream 24 voldoet daaraan.
3️⃣ Node.js installeren: dnf module
Deze keer heb ik stream 24 geïnstalleerd en vooraf met de optie [--assumeno] de lijst met te installeren pakketten gecontroleerd.
dnf module install nodejs:24 --assumenoDe lijst bevatte maar vijf pakketten: nodejs, npm, nodejs-libs, nodejs-docs en nodejs-full-i18n. Er zaten geen pakketten voor de webserver, PHP of de kernel bij. Na de controle installeer je met de optie [-y].
dnf module install -y nodejs:24Dependencies resolved.
==============================================================================================
Package Architecture Version Repository Size
==============================================================================================
Installing group/module packages:
nodejs x86_64 1:24.21.0-1.module_el9.8.0+321+1555b6a2 appstream 70 k
npm noarch 1:11.19.0-1.24.21.0.1.module_el9.8.0+321+1555b6a2 appstream 2.1 M
Installing dependencies:
nodejs-libs x86_64 1:24.21.0-1.module_el9.8.0+321+1555b6a2 appstream 24 M
Installing weak dependencies:
nodejs-docs noarch 1:24.21.0-1.module_el9.8.0+321+1555b6a2 appstream 5.3 M
nodejs-full-i18n x86_64 1:24.21.0-1.module_el9.8.0+321+1555b6a2 appstream 8.9 M
Installing module profiles:
nodejs/common
Enabling module streams:
nodejs 24
Transaction Summary
==============================================================================================
Install 5 Packages
Total download size: 40 M
Installed size: 185 M[Installing weak dependencies] toont de zwakke afhankelijkheden (weak dependencies): pakketten die je handig mee kunt installeren. De download is 40M en de installatie 185M.
node -vv24.21.0npm -v11.19.0cat /etc/dnf/modules.d/nodejs.module[nodejs]
name=nodejs
stream=24
profiles=common
state=enablednode is geïnstalleerd als 24.21.0 en npm als 11.19.0. Het enige configuratiebestand dat door de installatie veranderde, is [/etc/dnf/modules.d/nodejs.module], waarin stream 24 en het profiel common als actief staan.
4️⃣ jsdom installeren en een knopscript controleren
jsdom installeer je met npm in een werkmap, en die werkmap maak je buiten de webroot aan.
mkdir ~/jsdom-test && cd ~/jsdom-test
npm init -y[npm init -y] maakt package.json aan met standaardwaarden, daarna installeer je jsdom in dezelfde map.
npm install jsdomadded 36 packages, and audited 37 packages in 2s
8 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilitiesnpm ls jsdomjsdom-test@1.0.0 /root/jsdom-test
└── jsdom@30.1.3Er zijn 36 pakketten geïnstalleerd, waaronder jsdom 30.1.3, met 0 bekende kwetsbaarheden. De map node_modules in de werkmap is 26M.
node -e 'const { JSDOM } = require(`jsdom`); console.log(new JSDOM(`<h1>Hallo</h1>`).window.document.querySelector(`h1`).textContent)'HalloLeest jsdom de HTML met één h1-tag als document in en geeft het de tekst daarin, [Hallo], weer, dan is de controle klaar.
Een knopscript controleren betekent op de server nagaan of de tekst na een klik goed verandert. Als voorbeeld heb ik in de werkmap een HTML-bestand gemaakt waarin een klik op de knop [Kopiëren] de tekst verandert in [Gekopieerd].
cat btn.html<button id="copy">Kopiëren</button>
<script>
document.getElementById('copy').addEventListener('click', function () {
this.textContent = 'Gekopieerd';
});
</script>Het controlescript leest het HTML-bestand met jsdom in, voert de scripts uit en toont de tekst vóór en na de klik. Scriptfouten verschijnen als regels die beginnen met [Fout:].
cat check.jsconst fs = require('fs');
const { JSDOM, VirtualConsole } = require('jsdom');
const vc = new VirtualConsole();
vc.on('jsdomError', (e) => console.log('Fout:', e.message));
const dom = new JSDOM(fs.readFileSync(process.argv[2], 'utf8'), {
runScripts: 'dangerously',
virtualConsole: vc,
});
const btn = dom.window.document.querySelector('#copy');
console.log('Voor de klik:', btn.textContent);
btn.click();
console.log('Na de klik:', btn.textContent);node check.js btn.htmlVoor de klik: Kopiëren
Na de klik: GekopieerdNa de klik verandert de tekst in [Gekopieerd], waarmee je ziet dat het knopscript werkt.
Eén typfout in het script verandert het resultaat. Ik heb dezelfde controle uitgevoerd met een bestand waarin de hoofdletter I in getElementById door een kleine l is vervangen.
sed 's/getElementById/getElementByld/' btn.html > btn-broken.html
node check.js btn-broken.htmlFout: Uncaught [TypeError: document.getElementByld is not a function]
Voor de klik: Kopiëren
Na de klik: KopiërenOp de eerste regel verschijnt een fout en het script stopt, dus de tekst blijft [Kopiëren], ook na de klik.
Ik heb de knop met CSS een breedte van 120px en een hoogte van 40px gegeven en daarna de grootte weergegeven.
cat size.jsconst { JSDOM } = require('jsdom');
const dom = new JSDOM('<button id="copy" style="width:120px;height:40px">Kopiëren</button>');
const btn = dom.window.document.querySelector('#copy');
console.log('hoogte:', btn.offsetHeight, '/ breedte:', btn.getBoundingClientRect().width);node size.jshoogte: 0 / breedte: 0jsdom heeft geen stap die op het scherm tekent, dus hoogte en breedte worden als 0 weergegeven.
🔢 FAQ & aanbevolen content







ℹ️ Affiliatemelding
De content van deze site bevat affiliatelinks. Koopt een bezoeker via een van deze links een product of dienst, dan ontvangt deze site een commissie van de verkoper. Het bedrag dat de koper betaalt (bij acties gaat het omlaag ↓) wordt daardoor niet hoger. De vermelde prijzen, kortingen en voorraad gelden op het moment van schrijven en kunnen afwijken; controleer ze daarom vóór je aankoop bij de verkoper. Producten worden gekozen en beoordeeld volgens onze eigen criteria, en commissies hebben geen invloed op de volgorde of de inhoud van de beoordelingen.