安裝 Node.js:不用瀏覽器在伺服器上檢查按鈕運作

要在伺服器上執行 JavaScript,必須先安裝 Node.js。在 Nginx 與 Apache 構成的 WordPress 伺服器上安裝了 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 也是在 Node.js 上執行的 CMS。
🔲 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 registry,jsdom 30.1.3 要求的版本是 22 系列 22.22.2 以上、24 系列 24.15.0 以上,或 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 profile 為啟用狀態。
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包含 jsdom 30.1.3 在內共安裝了 36 個套件,已知漏洞為 0 個。工作資料夾的 node_modules 大小為 26M。
node -e 'const { JSDOM } = require(`jsdom`); console.log(new JSDOM(`<h1>你好</h1>`).window.document.querySelector(`h1`).textContent)'你好jsdom 把只有一個 h1 標籤的 HTML 讀成文件,並印出其中的文字 [你好],就完成運作確認。
檢查按鈕腳本,就是在伺服器上確認按下後文字是否正確改變。作為範例,在工作資料夾建立了一個 HTML 檔,按下 [複製] 按鈕後文字會變成 [已複製]。
cat btn.html<button id="copy">複製</button>
<script>
document.getElementById('copy').addEventListener('click', function () {
this.textContent = '已複製';
});
</script>檢查腳本會用 jsdom 讀取 HTML 檔並執行其中的腳本,再印出按下按鈕前後的文字。腳本錯誤會印在以 [錯誤:] 開頭的行。
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點選前: 複製
點選後: 已複製按下後文字變成 [已複製],可以確認按鈕腳本有在運作。
腳本只要有一個錯字,結果就會不同。以把 getElementById 的大寫 I 改成小寫 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 / 寬度: 0jsdom 沒有在畫面上繪製的步驟,因此高度與寬度都印出 0。
🔢 FAQ & 推薦內容







ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。