Instalacja Node.js: sprawdzanie działania przycisków na serwerze bez przeglądarki

Aby uruchamiać JavaScript na serwerze, najpierw potrzebna jest instalacja Node.js. Zainstalowałem Node.js 24.21.0 na serwerze WordPress z Nginx i Apache, a za pomocą jsdom 30.1.3 sprawdziłem bez przeglądarki skrypt przycisków na stronie internetowej.
nodejs w domyślnym repozytorium to wersja 16.20.2, a jsdom 30.1.3, którego używam do sprawdzania skryptów, wymaga Node.js 22.22.2 lub nowszego. Dlatego zainstalowałem go ze strumienia modułu dnf 24.
1️⃣ Po co instalować Node.js i jsdom na serwerze
Do sprawdzania skryptów przycisków na serwerze potrzebne są dwie rzeczy: Node.js i jsdom.
🔲 Node.js
JavaScript zwykle działa w przeglądarce, ale po zainstalowaniu Node.js także serwer może czytać i uruchamiać JavaScript.
Instalacja Node.js oznacza umieszczenie na serwerze środowiska uruchomieniowego JavaScriptu, które wcześniej było tylko w przeglądarce. Dlatego Node.js służy do budowania serwerów WWW, tworzenia poleceń przetwarzających wiele plików naraz albo wczytywania pakietów takich jak jsdom i sprawdzania stron. Ghost to również CMS działający na Node.js.
🔲 jsdom
jsdom to pakiet dla Node.js, który wczytuje HTML i robi z niego dokument, w którym można klikać przyciski jak w przeglądarce. Odtwarza w serwerze, bez ekranu, strukturę dokumentu (DOM) tworzoną przez przeglądarkę przy otwieraniu strony, więc skrypty znajdują przyciski i zmieniają tekst tak, jakby działały w prawdziwej przeglądarce. Ponieważ nie otwiera okna, uruchamia się go na serwerze jednym poleceniem.
Innymi słowy, sprawdzanie, które człowiek wykonywał, otwierając przeglądarkę i klikając po kolei, serwer przejmuje jednym poleceniem. Dlatego jsdom służy też do automatycznego testowania działania przycisków po każdej poprawce, wyciągania ze strony tylko treści takich jak tytuły i linki albo hurtowego poprawiania HTML wpisów.
Pobierając stronę przez PHP lub curl, zobaczysz tylko HTML przesłany na początku. Tekst, który zmienia się po kliknięciu przycisku, pojawia się dopiero po uruchomieniu skryptu.
Przeglądarka przechodzi przez cztery kroki: pobranie strony, odczytanie strony, naciśnięcie przycisku i wyświetlenie na ekranie. jsdom wykonuje na serwerze wszystkie kroki poza wyświetleniem, dlatego położenie i rozmiar przycisku sprawdza się w przeglądarce.
2️⃣ Przed instalacją: domyślne repozytorium i strumienie modułów
Przed uruchomieniem [dnf install nodejs] najpierw sprawdź, która wersja zostałaby zainstalowana. nodejs w domyślnym repozytorium AlmaLinux 9.8 to 16.20.2.
dnf list --available nodejsAvailable Packages
nodejs.x86_64 1:16.20.2-8.el9_4 appstreamRepozytorium modułów ma cztery strumienie: 18, 20, 22 i 24. W dniu sprawdzenia strumień 22 był w wersji 22.23.2, a strumień 24 – 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 runtimeWedług rejestru npm jsdom 30.1.3 wymaga wersji 22.22.2 lub nowszej z linii 22, 24.15.0 lub nowszej z linii 24 albo 26 i wyżej. Strumienie 22 i 24 spełniają ten warunek.
3️⃣ Instalacja Node.js: dnf module
Tym razem zainstalowałem strumień 24, a przed uruchomieniem sprawdziłem opcją [--assumeno] listę pakietów do instalacji.
dnf module install nodejs:24 --assumenoNa liście było tylko pięć pakietów: nodejs, npm, nodejs-libs, nodejs-docs i nodejs-full-i18n. Nie było pakietów serwera WWW, PHP ani jądra. Po sprawdzeniu instaluje się z opcją [-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] pokazuje słabe zależności (weak dependencies), czyli pakiety, które warto zainstalować razem. Pobieranie zajmuje 40M, a instalacja 185M.
node -vv24.21.0npm -v11.19.0cat /etc/dnf/modules.d/nodejs.module[nodejs]
name=nodejs
stream=24
profiles=common
state=enablednode zainstalował się w wersji 24.21.0, a npm w 11.19.0. Jedynym plikiem konfiguracyjnym zmienionym przez instalację jest [/etc/dnf/modules.d/nodejs.module], w którym strumień 24 i profil common są zapisane jako aktywne.
4️⃣ Instalacja jsdom i sprawdzanie skryptu przycisku
jsdom instaluje się przez npm w folderze roboczym, a folder roboczy tworzy się poza katalogiem głównym strony.
mkdir ~/jsdom-test && cd ~/jsdom-test
npm init -y[npm init -y] tworzy package.json z wartościami domyślnymi, a następnie w tym samym folderze instaluje się jsdom.
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.3Zainstalowano 36 pakietów, w tym jsdom 30.1.3, przy 0 znanych podatnościach. Folder node_modules w folderze roboczym ma 26M.
node -e 'const { JSDOM } = require(`jsdom`); console.log(new JSDOM(`<h1>Cześć</h1>`).window.document.querySelector(`h1`).textContent)'CześćJeśli jsdom wczyta jako dokument HTML z jednym znacznikiem h1 i wypisze tekst w środku, [Cześć], test działania jest zakończony.
Sprawdzanie skryptu przycisku polega na upewnieniu się na serwerze, że tekst po kliknięciu zmienia się prawidłowo. Jako przykład utworzyłem w folderze roboczym plik HTML, w którym kliknięcie przycisku [Kopiuj] zmienia tekst na [Skopiowano].
cat btn.html<button id="copy">Kopiuj</button>
<script>
document.getElementById('copy').addEventListener('click', function () {
this.textContent = 'Skopiowano';
});
</script>Skrypt sprawdzający wczytuje plik HTML przez jsdom, uruchamia skrypty i wypisuje tekst przed kliknięciem i po nim. Błędy skryptu są wypisywane w wierszach zaczynających się od [Błąd:].
cat check.jsconst fs = require('fs');
const { JSDOM, VirtualConsole } = require('jsdom');
const vc = new VirtualConsole();
vc.on('jsdomError', (e) => console.log('Błąd:', 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('Przed kliknięciem:', btn.textContent);
btn.click();
console.log('Po kliknięciu:', btn.textContent);node check.js btn.htmlPrzed kliknięciem: Kopiuj
Po kliknięciu: SkopiowanoPo kliknięciu tekst zmienia się na [Skopiowano], co potwierdza, że skrypt przycisku działa.
Jedna literówka w skrypcie zmienia wynik. Uruchomiłem ten sam test na pliku, w którym wielką literę I w getElementById zamieniono na małe l.
sed 's/getElementById/getElementByld/' btn.html > btn-broken.html
node check.js btn-broken.htmlBłąd: Uncaught [TypeError: document.getElementByld is not a function]
Przed kliknięciem: Kopiuj
Po kliknięciu: KopiujW pierwszym wierszu pojawia się błąd i skrypt się zatrzymuje, więc tekst pozostaje [Kopiuj] nawet po kliknięciu.
Nadałem przyciskowi w CSS szerokość 120px i wysokość 40px, a potem wypisałem jego rozmiar.
cat size.jsconst { JSDOM } = require('jsdom');
const dom = new JSDOM('<button id="copy" style="width:120px;height:40px">Kopiuj</button>');
const btn = dom.window.document.querySelector('#copy');
console.log('wysokość:', btn.offsetHeight, '/ szerokość:', btn.getBoundingClientRect().width);node size.jswysokość: 0 / szerokość: 0jsdom nie ma etapu rysowania na ekranie, więc wysokość i szerokość są wypisywane jako 0.
🔢 FAQ & polecane treści







ℹ️ Informacja o linkach partnerskich
Treści tej witryny zawierają linki partnerskie. Jeśli odwiedzający kupi produkt lub usługę przez taki link, witryna otrzymuje od sprzedawcy prowizję. Kwota płacona przy tym przez kupującego (podczas promocji spada↓) nie wzrasta. Podane ceny, rabaty i dostępność odnoszą się do chwili pisania i mogą różnić się od stanu faktycznego, dlatego przed zakupem sprawdź je u sprzedawcy. Produkty wybieramy i oceniamy według własnych kryteriów, a prowizja nie wpływa ani na kolejność prezentacji, ani na treść ocen.