Learning Objectives
- 說明用 file:// 直接開網頁會遇到哪些限制,以及為什麼開發時要用本機伺服器
- 用 Node.js 的 npx http-server、Python 的 http.server 或 VS Code Live Server 開啟本機伺服器
- 說明 localhost、127.0.0.1 與連接埠(port)的意思,並看懂一個網址的各個部分
- 說明 query string 的組成,用 URL 與 URLSearchParams 讀取與組出 query string
為什麼要開一個本機伺服器
在檔案總管裡對 index.html 按兩下,瀏覽器的網址列會出現 file:///C:/Users/…/index.html:
瀏覽器是直接讀取硬碟上的檔案,中間沒有伺服器。只放 HTML、CSS 和簡單的 JavaScript 時這樣沒問題,
但接下來幾課的功能,用 file:// 開就會出問題:
| 想做的事 | 用 file:// 開啟時 |
|---|---|
用 fetch 讀取同一個資料夾裡的 data.json(AJAX 那一課) |
Chrome、Edge 會拒絕,主控台出現錯誤;各瀏覽器的規則不完全相同 |
用 <script type="module"> 載入 ES 模組(模組那一課) |
會出現 CORS 錯誤,模組載入失敗 |
| 測試網址後面帶的 query string、模擬網站真正的運作方式 | 沒有伺服器,看不到網頁與伺服器之間的請求 |
原因是瀏覽器的安全規則:從 file:// 開啟的網頁不能隨意讀取你硬碟上的其他檔案,否則任何一個下載回來的 HTML 都可能偷看你的資料。
解決方法是在自己的電腦上啟動一個網頁伺服器(web server),讓瀏覽器用 http:// 向它要檔案,
就和連上真正的網站一樣。這種只在本機開發、測試用的伺服器,常叫做本機伺服器或開發伺服器(dev server)。
Node.js、npm 與 npx
最常用的工具是 Node.js 生態系裡的 http-server,先認識三個名字:
| 名稱 | 是什麼 |
|---|---|
| Node.js | 讓 JavaScript 在瀏覽器以外執行的環境,以 Google 的 V8 引擎為基礎,常用來寫伺服器端程式與開發工具 |
| npm(Node Package Manager) | Node.js 的套件管理工具,安裝 Node.js 時會一起裝好;可以從 npmjs.com 下載別人寫好的套件 |
| npx | 也隨 npm 一起安裝,可以「直接執行」一個套件提供的指令;本機沒有這個套件時,會先問你要不要下載 |
投影片的做法是先用 npm install -g http-server 全域安裝(-g 表示裝在系統上,任何資料夾都能用),再執行 http-server。
現在更常見的做法是用 npx http-server,不必先安裝,也不會在系統上留下全域套件。兩種方式啟動的是同一個伺服器。
Node.js 請到官方網站 nodejs.org 下載標示 LTS(長期支援)的版本;2026 年 10 月查詢時最新的 LTS 是 v26。
用 npx http-server 啟動本機伺服器
安裝 Node.js 之後,打開終端機(Windows 可用「命令提示字元」、PowerShell 或 VS Code 的終端機),跟著下面幾步做。
-
1
確認 Node.js 已經安裝
node -v(或node --version)會顯示版本號碼;輸入npm -v可以看到隨附的 npm 版本。看到「不是內部或外部命令」之類的訊息,表示還沒安裝,或是安裝後沒有重新開啟終端機。 -
2
進入網頁所在的資料夾
伺服器會把「目前所在的資料夾」當成網站的根目錄。先建立一個資料夾,用 VS Code 在裡面新增
index.html,再用cd進入這個資料夾。 -
3
用 npx 啟動 http-server
-p 8000指定連接埠為 8000(沒有指定時預設是 8080)。第一次執行時 npx 會問要不要下載 http-server,輸入y再按 Enter。看到 Available on 就表示伺服器啟動了,下面列的網址就是瀏覽器要開的位址。版本不同時,設定的列表會略有差異。 -
4
在瀏覽器開啟網頁
打開瀏覽器,輸入
http://127.0.0.1:8000(或http://localhost:8000),就會看到index.html。網址列現在是http://開頭,表示網頁是從伺服器送來的。幾個常用的選項(
npx http-server -h列出全部):選項 作用 -p 8000指定連接埠(預設 8080) -o啟動後自動開啟瀏覽器 -c-1關閉快取。預設會讓瀏覽器快取 3600 秒,改了檔案卻看到舊畫面時可以加上它 --cors允許其他網域的網頁向這個伺服器要資料 -a 127.0.0.1只接受本機連線(預設 0.0.0.0:同一個網路裡的其他裝置也能連進來) 另外,資料夾裡如果有
public子資料夾,http-server 會改用public當網站根目錄。 -
5
停止伺服器
在終端機按 Ctrl+C 就會停止伺服器,瀏覽器重新整理後就連不上了。開發時通常讓它一直開著,另外開一個終端機做其他事。
其他方式:Python 與 VS Code Live Server
沒有安裝 Node.js 也沒關係,下面兩種方式效果相同,選一種順手的就好。
-
1
Python 內建的 http.server
電腦裡有 Python 3 的話,一行指令就能啟動;macOS 與 Linux 通常要打
python3。::代表接受所有網路介面的連線,瀏覽器一樣開http://127.0.0.1:8000。每收到一個請求,終端機就會多一行紀錄:請求的路徑(包含 query string)與狀態碼 200。 -
2
只讓自己的電腦連線
加上
--bind 127.0.0.1,同一個網路裡的其他裝置就連不進來,開發時這樣比較安全。 -
3
VS Code 的 Live Server 擴充功能
在 VS Code 的擴充功能市集搜尋 Live Server(作者 Ritwick Dey)並安裝。開啟網頁資料夾後,點視窗右下角狀態列的 Go Live,或在 HTML 檔上按右鍵選 Open with Live Server,瀏覽器會自動開啟(網址通常是
http://127.0.0.1:5500)。它的特色是存檔後瀏覽器會自動重新整理;再按一次狀態列的按鈕就會停止。
localhost、連接埠與網址的組成
localhost 是「這台電腦自己」的名字,對應的 IP 位址是 127.0.0.1。瀏覽器連到 localhost,就是連到你自己電腦上的伺服器,資料不會離開你的電腦。
一台電腦可以同時跑好幾個伺服器,靠連接埠(port)區分,像同一棟大樓的不同門牌: http-server 預設 8080、Python 常用 8000、Live Server 常用 5500。兩個程式不能同時使用同一個連接埠, 啟動時看到「address already in use」(連接埠已被使用),就換一個號碼。
一個網址可以拆成好幾個部分:
| 部分 | 範例 http://127.0.0.1:8000/test.html?username=amy&lang=zh-TW#top |
URL 物件的屬性 |
|---|---|---|
| 通訊協定 | http: |
protocol |
| 主機名稱 | 127.0.0.1 |
hostname |
| 連接埠 | 8000 |
port |
| 路徑 | /test.html |
pathname |
| query string | ?username=amy&lang=zh-TW |
search |
| 錨點(hash) | #top |
hash |
JavaScript 的 URL 物件可以幫你拆:new URL(網址) 之後讀取上面這些屬性。
在網頁裡,目前這一頁的網址是 location.href,所以常寫成 new URL(location.href)。
用 URL 物件拆開網址
逐步播放,對照下方輸出:每一行印出網址的一個部分。注意 search 包含開頭的 ?,hash 包含 #;用 https 預設的連接埠(443)時網址裡不寫連接埠,port 就是空字串。
query string:網址後面帶的資料
網址 ? 後面那一段叫 query string(查詢字串),用來把簡單的資料傳給網頁或伺服器:
- 從
?開始,由好幾組參數組成,參數之間用&隔開 - 每組參數是
key=value,用=連接,例如username=amy&age=20 - 同一個 key 可以出現好幾次,例如
tag=js&tag=web - 中文、空白等特殊字元要經過編碼(URL encoding),例如空白變成
+或%20
例如 https://github.com/search?q=querystring&type=Code 的 query string 是 q=querystring&type=Code。
表單用 GET 送出(<form action="result.html"> 預設的方式)時,瀏覽器也會把每個欄位的 name=值 組成 query string 接在網址後面。
讀取 query string 不要自己用 split('&') 切字串,交給 URLSearchParams:它會處理編碼、重複的 key 與找不到的情況。
| 方法 | 作用 |
|---|---|
params.get('age') |
取得第一個值(一律是字串);沒有這個 key 時回傳 null |
params.getAll('tag') |
取得所有同名的值,回傳陣列 |
params.has('age') |
有沒有這個 key |
params.set('page', '3')、params.append('tag', 'css') |
設定(取代同名的)或新增一組參數 |
params.toString() |
組回 query string(自動編碼) |
不要把密碼等敏感資料放在 query string:網址會留在瀏覽器的歷史紀錄與伺服器的紀錄檔,也可能被別人看到或分享出去。
用 URLSearchParams 讀取參數
看右邊變數的值:get 拿到的一律是字串,要計算就先用 Number() 轉換;getAll 回傳陣列;找不到的 key 是 null。最後的 for…of 會依序取出每一組 key 與 value。
反過來:組出 query string
想把資料放進網址時,用 append、set 加入參數,再用 toString() 組成字串。看第 8 行的輸出:中文被編碼成 %E5%8F%B0…,空白變成 +;用 get 讀回來時會自動解碼。
在網頁裡測試送出 query string
把下面的 test.html 放進伺服器的資料夾,在瀏覽器開啟 http://127.0.0.1:8000/test.html?username=amy&age=20,
畫面就會顯示網址裡帶的名字。改掉網址裡的值再按 Enter,畫面跟著變;終端機裡也會看到這一次請求的紀錄。
<!DOCTYPE html>
<html lang="zh-Hant">
<head><meta charset="utf-8"><title>測試 query string</title></head>
<body>
<p id="msg"></p>
<script>
const params = new URL(location.href).searchParams;
const name = params.get('username') ?? '訪客';
document.getElementById('msg').textContent = '你好,' + name;
</script>
</body>
</html>
?? 的意思是「左邊是 null 或 undefined 時改用右邊」:網址沒有帶 username 時顯示「訪客」。
放進頁面時用 textContent 而不是 innerHTML:網址是任何人都能改的,不能讓別人在網址裡塞進 HTML。
想一想:本機伺服器
直接在檔案總管對 index.html 按兩下,用 file:// 開啟。在 Chrome 裡,下列哪一件事最可能失敗?
在終端機執行 npx http-server -p 8000 之後,瀏覽器要開哪一個網址?
關於 localhost 與連接埠,下列哪一個說法正確?
想一想:query string
下面的程式會印出什麼?
const url = new URL('https://github.com/search?q=querystring&type=Code');
console.log(url.search);
下面的程式會印出什麼?
const p = new URLSearchParams('a=1&b=2&a=3');
console.log(p.get('a'), p.getAll('a').length);
下面的程式會印出什麼?
const p = new URLSearchParams('name=amy');
console.log(p.get('age'));
下列哪一種資料不應該放在 query string 裡?
實作:從網址讀出訂單
網址 http://127.0.0.1:8000/order.html?item=latte&qty=2&size=L 帶了一筆飲料訂單。用 URL 與 searchParams 讀出三個參數,印出 latte x 2(L),再用單價 60 算出總價,印出 總價 120。
重點精華回顧
- 用
file://直接開網頁時,fetch讀本機檔案、ES 模組等功能會被瀏覽器的安全規則擋下;開發時改用本機伺服器,以http://開啟。 - Node.js 是瀏覽器以外的 JavaScript 執行環境,npm 是它的套件管理工具;
npx http-server -p 8000不必先安裝就能啟動伺服器,Ctrl+C 停止。 - 其他選擇:Python 的
python -m http.server 8000、VS Code 的 Live Server(存檔自動重新整理)。 - localhost(127.0.0.1)是自己的電腦,連接埠用來區分同一台電腦上的不同伺服器。
- 網址由通訊協定、主機名稱、連接埠、路徑、query string、hash 組成,
new URL()可以拆開它。 - query string 從
?開始,key=value之間用&隔開;用URLSearchParams的get、getAll、has讀取,get回傳字串或null。 - 密碼等敏感資料不要放在 query string。