Установка Node.js: проверка работы кнопок на сервере без браузера

Чтобы запускать JavaScript на сервере, сначала нужно установить Node.js. На сервер WordPress с конфигурацией Nginx и Apache был установлен Node.js 24.21.0, а скрипт кнопки на веб-странице проверен с помощью jsdom 30.1.3 без браузера.
В стандартном репозитории nodejs версии 16.20.2, а jsdom 30.1.3, которым проверяются скрипты, требует Node.js 22.22.2 или новее. Поэтому установка выполнялась из потока модуля dnf 24.
1️⃣ Зачем устанавливать Node.js и jsdom на сервер
Для проверки скриптов кнопок на сервере нужны две вещи: Node.js и jsdom.
🔲 Node.js
JavaScript обычно выполняется в браузере, но после установки Node.js сервер тоже может читать и выполнять JavaScript.
Установить Node.js — значит разместить на сервере ещё одну среду выполнения JavaScript, которая раньше была только в браузере. Поэтому Node.js используют, чтобы создавать веб-серверы, команды для обработки множества файлов сразу или загружать пакеты вроде jsdom для проверки страниц. Ghost — тоже CMS, работающая на Node.js.
🔲 jsdom
jsdom — пакет для Node.js, который читает HTML и превращает его в документ, где кнопки можно нажимать, как в браузере. Он строит ту же структуру документа (DOM), что браузер создаёт при открытии страницы, но внутри сервера и без экрана, поэтому скрипты находят кнопки и меняют текст так, будто работают в настоящем браузере. Окно не открывается, так что на сервере он запускается одной командой.
Иначе говоря, проверку, которую раньше человек делал, открывая браузер и нажимая всё по очереди, сервер выполняет командой. Поэтому jsdom также используют, чтобы автоматически проверять работу кнопок после каждой правки, извлекать со страницы только содержимое вроде заголовков и ссылок или массово править HTML записей.
Если получить страницу через PHP или curl, виден только HTML, отправленный первым. Текст, который меняется после нажатия кнопки, появляется, только когда выполняется скрипт.
Браузер проходит четыре этапа: получение страницы, чтение страницы, нажатие кнопки и вывод на экран. jsdom выполняет на сервере все этапы, кроме вывода на экран, поэтому положение и размер кнопки проверяют в браузере.
2️⃣ Проверка перед установкой: стандартный репозиторий и потоки модуля
Перед запуском [dnf install nodejs] сначала проверьте, какая версия будет установлена. В стандартном репозитории AlmaLinux 9.8 nodejs версии 16.20.2.
dnf list --available nodejsAvailable Packages
nodejs.x86_64 1:16.20.2-8.el9_4 appstreamВ репозитории модулей четыре потока: 18, 20, 22 и 24. На дату проверки поток 22 был на версии 22.23.2, а поток 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 runtimeПо данным реестра npm, jsdom 30.1.3 требует версию 22.22.2 или новее в ветке 22, 24.15.0 или новее в ветке 24 либо 26 и выше. Оба потока, 22 и 24, удовлетворяют этому условию.
3️⃣ Установка Node.js: dnf module
На этот раз был установлен поток 24, а перед запуском список устанавливаемых пакетов был сначала проверен с параметром [--assumeno].
dnf module install nodejs:24 --assumenoВ списке было только пять пакетов: nodejs, npm, nodejs-libs, nodejs-docs и nodejs-full-i18n. Пакетов веб-сервера, PHP и ядра не было. После проверки выполните установку с параметром [-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] перечисляет weak dependencies — пакеты, которые желательно установить вместе. Размер загрузки — 40M, размер после установки — 185M.
node -vv24.21.0npm -v11.19.0cat /etc/dnf/modules.d/nodejs.module[nodejs]
name=nodejs
stream=24
profiles=common
state=enablednode установлен в версии 24.21.0, npm — в версии 11.19.0. После установки изменился только один файл конфигурации — [/etc/dnf/modules.d/nodejs.module], в котором поток 24 и профиль common записаны как включённые.
4️⃣ Установка jsdom и проверка скрипта кнопки
jsdom устанавливается через npm в рабочую папку, а рабочая папка создаётся вне корня сайта.
mkdir ~/jsdom-test && cd ~/jsdom-test
npm init -y[npm init -y] создаёт package.json со значениями по умолчанию, затем 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.3Установлено 36 пакетов, включая jsdom 30.1.3, известных уязвимостей — 0. Размер node_modules в рабочей папке — 26M.
node -e 'const { JSDOM } = require(`jsdom`); console.log(new JSDOM(`<h1>Привет</h1>`).window.document.querySelector(`h1`).textContent)'ПриветЕсли jsdom читает HTML из одного тега h1 как документ и выводит текст внутри него — [Привет], проверка работы завершена.
Проверка скрипта кнопки — это подтверждение на сервере, что после нажатия текст меняется правильно. В качестве примера в рабочей папке создан HTML-файл, где при нажатии кнопки [Копировать] её текст меняется на [Скопировано].
cat btn.html<button id="copy">Копировать</button>
<script>
document.getElementById('copy').addEventListener('click', function () {
this.textContent = 'Скопировано';
});
</script>Проверочный скрипт читает HTML-файл через jsdom, выполняет его скрипты и выводит текст до и после нажатия. Ошибки скрипта выводятся строками, начинающимися с [Ошибка:].
cat check.jsconst fs = require('fs');
const { JSDOM, VirtualConsole } = require('jsdom');
const vc = new VirtualConsole();
vc.on('jsdomError', (e) => console.log('Ошибка:', 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('До нажатия:', btn.textContent);
btn.click();
console.log('После нажатия:', btn.textContent);node check.js btn.htmlДо нажатия: Копировать
После нажатия: СкопированоПосле нажатия текст меняется на [Скопировано] — значит, скрипт кнопки работает.
Одна опечатка в скрипте меняет результат. Та же проверка была запущена на файле, где заглавная I в getElementById заменена строчной l.
sed 's/getElementById/getElementByld/' btn.html > btn-broken.html
node check.js btn-broken.htmlОшибка: Uncaught [TypeError: document.getElementByld is not a function]
До нажатия: Копировать
После нажатия: КопироватьВ первой строке выводится ошибка, скрипт останавливается, и даже после нажатия текст остаётся [Копировать].
Кнопке через CSS заданы ширина 120px и высота 40px, затем выведен её размер.
cat size.jsconst { JSDOM } = require('jsdom');
const dom = new JSDOM('<button id="copy" style="width:120px;height:40px">Копировать</button>');
const btn = dom.window.document.querySelector('#copy');
console.log('высота:', btn.offsetHeight, '/ ширина:', btn.getBoundingClientRect().width);node size.jsвысота: 0 / ширина: 0В jsdom нет этапа отрисовки на экране, поэтому высота и ширина выводятся как 0.
🔢 FAQ & рекомендуемые материалы







ℹ️ О партнёрских ссылках
Материалы этого сайта содержат партнёрские ссылки. Если посетитель покупает товар или услугу по такой ссылке, сайт получает комиссию от продавца. При этом сумма, которую платит покупатель (при акционных скидках сумма снижается ↓), не увеличивается. Указанные цены, скидки и наличие актуальны на момент написания и могут отличаться, поэтому перед покупкой уточняйте их у продавца. Товары выбираются и оцениваются по нашим собственным критериям, а комиссия не влияет ни на порядок, ни на содержание обзоров.