
Node.js 入門教程很多但真正能幫你在 1 小時內把安裝、驗證、編碼、跑通全部走完的并不多。這篇文章以“從下載 Node.js 到寫出第一個 Web 應用”為主線把 60 分鐘拆成四段前 10 分鐘搞清楚 Node.js 是干什么的、版本怎么選中間 15 分鐘完成安裝和 npm 基礎配置接下來 20 分鐘用 Node.js 自帶模塊寫一個能訪問的 Web 頁面最后 15 分鐘排查安裝和運行時最常見的報錯。這樣做的好處是每一步都能驗證結果不會出現“環境配了一下午代碼一跑全是問題”的情況。1. 先搞清楚 Node.js 是干什么的再決定安裝哪個版本1.1 Node.js 不是普通腳本工具而是一個 JavaScript 運行時Node.js 的官方定位是“基于 Chrome V8 引擎的 JavaScript 運行時”。通俗一點說瀏覽器給 JavaScript 提供了window、document、fetch等環境而 Node.js 給 JavaScript 提供了文件讀取、網絡請求、進程管理、操作系統交互等能力。這意味著你不再需要通過 HTML 頁面來運行 JavaScript可以直接在終端執行node -e console.log(hello node)這行命令會創建一個 Node.js 進程執行字符串里的 JavaScript 代碼然后把結果輸出到控制臺。對剛入門的人來說只要理解這一點就夠了Node.js 讓 JavaScript 從“只能操作頁面”變成“可以操作文件和網絡”的通用語言。1.2 事件驅動、非阻塞 I/O 到底影響什么很多資料會提到“事件驅動”“非阻塞 I/O”“單線程”。這里用一句更貼近實際的話解釋Node.js 遇到耗時操作時不會一直卡住等待結果而是先繼續處理其他請求等耗時操作完成后通過回調繼續處理。看一個簡單對比// 模擬耗時讀取不推薦生產環境使用 fs.readFileSync const fs require(fs); console.log(1. 開始讀取); const data fs.readFileSync(example.txt, utf8); console.log(2. 讀取完成, data.length); console.log(3. 繼續執行);上面這段用同步方式讀文件執行到第二行時整個進程會等待文件讀完才繼續執行第三行。如果改用異步方式const fs require(fs); console.log(1. 開始讀取); fs.readFile(example.txt, utf8, (err, data) { console.log(2. 讀取完成, data ? data.length : error); }); console.log(3. 繼續執行);執行順序會變成“1、3、2”。異步 I/O 是 Node.js 能同時處理大量并發請求的重要原因。對于剛入門的第一個 Web 應用你不需要立刻精通它但必須理解fs.readFile的回調不會阻塞后續代碼。1.3 LTS、Current、偶數版本號怎么選安裝 Node.js 前最容易出錯的是版本選擇。官方發布版本大致分兩類版本類型說明適合場景LTSLong Term Support長期支持版本會持續維護和修復漏洞推薦新手、生產環境、企業項目Current當前版本包含新特性但迭代快、可能不穩定嘗鮮、特性驗證、短期學習偶數版本例如 18、20、22通常更容易進入 LTS 周期穩定性優先的項目奇數版本例如 19、21、23通常是過渡版本不建議作為主力實際項目里建議安裝當前最新 LTS而不是最新 Current。原因很直接很多 npm 包對 Node.js 版本有要求LTS 版本生態兼容更好遇到問題時搜索引擎能找到更多答案。1.4 安裝前的環境檢查清單安裝前先檢查操作系統、CPU 架構和是否已存在舊版本# Windows PowerShell systeminfo | findstr /C:OS # Linux / macOS uname -m # 檢查是否已經安裝過 Node.js node -v npm -vWindows 下尤其要注意架構絕大多數現代電腦使用 64 位系統應該下載x64安裝包部分舊電腦是 32 位系統需要下載x86包。如果系統里已經安裝了舊版 Node.js先確認版本避免安裝新版本后 PATH 環境變量混亂。2. 安裝 Node.js 的三種方式以及為什么推薦用 nvm2.1 Windows 圖形化安裝包最快但最不靈活進入 Node.js 官網下載頁選擇適合當前系統的.msi安裝包雙擊運行即可。安裝過程中默認已經包含“添加到 PATH”選項一般不需要修改一直下一步即可。安裝完成后重新打開一個終端窗口執行node -v npm -v如果輸出類似v22.13.1 10.9.2說明安裝成功。需要注意安裝完成后必須新開終端窗口否則當前終端的 PATH 不會刷新仍然提示找不到node命令。這種方式適合只跑一次 Node.js、不打算切換項目的用戶。缺點是當某個項目依賴 Node.js 20另一個項目依賴 Node.js 22 時圖形化安裝包無法靈活切換版本。2.2 Windows 下使用 nvm-windows 管理多版本跨項目開發時推薦使用 nvmNode Version Manager管理 Node.js 版本。Windows 上沒有直接移植原版 nvm常用的是 nvm-windows。安裝方式從 nvm-windows 的發布頁面下載安裝包。安裝到一個不含中文和空格的目錄例如C:\nvm。安裝完成后終端執行nvm version然后安裝并切換 Node.js 版本nvm install 22.13.1 nvm use 22.13.1 node -v執行nvm use后node命令會指向 nvm 管理目錄下的對應版本。這里的關鍵點是不要直接到官網下載安裝包和管理器混用那會讓node命令的來源不確定。我的建議是Windows 新項目統一用 nvm-windows即使以后需要升級 Node.js 或同時維護舊項目也不會被版本問題卡住。2.3 macOS/Linux 下的 nvm 安裝macOS 或 Linux 用戶可以使用官方腳本安裝 nvm但不要直接復制網上來路不明的curl腳本應該先檢查內容再執行。安裝 nvm 后shell 配置文件通常是.zshrc或.bashrc會追加 nvm 初始化腳本。安裝完成要重新加載配置source ~/.zshrc然后安裝 Node.jsnvm install --lts nvm use --lts node -v--lts會安裝當前最新的長期支持版本避免手動指定容易過時的版本號。2.4 安裝完成后的檢查點無論使用哪種方式都要完成以下檢查檢查項命令預期結果Node.js 可用node -v輸出類似v22.13.1npm 可用npm -v輸出類似10.9.2nvm 可用nvm version輸出 nvm 版本號全局路徑npm root -g輸出存在的全局 node_modules 目錄緩存路徑npm config get cache輸出 npm 緩存目錄如果node -v能正常輸出但npm -v報錯通常是因為安裝包損壞、PATH 中存在多個 Node.js 目錄或舊版殘留。不要急著重裝先運行where nodeWindows或which nodeLinux/macOS確認實際執行路徑。3. 用 npm 做基礎配置鏡像源、全局路徑和緩存目錄3.1 npm 的職責與版本npm 是 Node.js 自帶的包管理器負責下載、安裝、卸載第三方依賴并維護項目的依賴關系。它和node是兩套程序Node.js 負責運行 JavaScriptnpm 負責管理 JavaScript 需要的庫。npm 的版本通常不等同于 Node.js 版本。安裝 Node.js 后npm 也一并安裝。日常使用中不要只關注node -v還要關注npm -v。某些 CLI 工具會要求 npm 版本達到閾值如果版本過舊可以通過以下命令升級 npmnpm install -g npmlatest3.2 配置鏡像源避免安裝依賴超時在實際網絡環境里直接從官方源安裝依賴可能很慢常見表現是npm install長時間停留在idealTree階段或者直接超時。可以把 npm 的 registry 切換到國內鏡像npm config set registry https://registry.npmmirror.com/驗證是否生效npm config get registry也可以直接查看配置文件位置npm config ls -l這里要注意的是全局使用鏡像源會影響所有項目。如果某些項目必須使用官方源或公司內網源可以只在項目根目錄創建.npmrc寫入registryhttps://registry.npmjs.org/項目級配置會覆蓋全局配置。這樣就能做到“全局用鏡像個別項目用官方源”。3.3 全局安裝路徑和權限使用全局安裝命令時npm install -g npm-check-updates全局包會安裝到npm root -g指向的目錄。Windows 下全局命令通常會被軟鏈到 npm 前綴目錄如果沒有正確配置會出現“命令安裝成功但終端找不到”的問題。Linux/macOS 下如果直接使用npm install -g遇到權限錯誤不要用sudo強行安裝更推薦修改 npm 的全局目錄到用戶目錄下mkdir -p ~/.npm-global npm config set prefix ~/.npm-global然后在 shell 配置文件中添加export PATH~/.npm-global/bin:$PATH這樣全局安裝的 CLI 工具都可以直接用也避免了權限污染。3.4 驗證 npm 配置配置完成后創建一個臨時目錄測試 npm 是否能正常安裝依賴mkdir npm-config-test cd npm-config-test npm init -y npm install lodash看到node_modules目錄生成并出現package-lock.json說明安裝鏈路正常。檢查點有npm config get registry輸出鏡像地址。npm root -g輸出一個可寫目錄。npm install沒有權限和超時報錯。注意不要在生產環境隨意使用npm cache clean --force。多數安裝問題不是緩存損壞而是鏡像源或版本不對。強行清理緩存反而會拖慢下一次安裝。4. 創建第一個 Web 應用使用內置 http 模塊4.1 初始化項目和目錄結構先創建項目目錄mkdir node-first-app cd node-first-app npm init -ynpm init -y會生成一個默認的package.json內容類似于{ name: node-first-app, version: 1.0.0, description: , main: index.js, scripts: { test: echo \Error: no test specified\ exit 1 } }對于第一個 Web 應用這個文件不是必須修改的但要理解它記錄了三類信息項目名稱與版本、入口文件、啟動腳本。后續添加第三方依賴時dependencies也會寫到這里。4.2 最小可運行的 HTTP 服務器新建server.js文件寫入const http require(http); const hostname 127.0.0.1; const port 3000; const server http.createServer((req, res) { res.statusCode 200; res.setHeader(Content-Type, text/plain; charsetutf-8); res.end(Hello Node.js Web App); }); server.listen(port, hostname, () { console.log(Server running at http://${hostname}:${port}/); });這段代碼的每一行都有明確作用require(http)導入 Node.js 內置的 HTTP 模塊。http.createServer接收一個回調函數每次有請求進來都會執行。req是請求對象包含 URL、請求方法、請求頭。res是響應對象用來設置狀態碼、響應頭和響應體。listening是網絡層面的監聽端口這里指定127.0.0.1:3000。4.3 解析請求參數和返回 JSON第一個 Web 應用如果只有“Hello World”還看不出實用價值。擴展一下根據 URL 返回用戶信息。const http require(http); const url require(url); const server http.createServer((req, res) { const parsedUrl new URL(req.url, http://${req.headers.host}); const pathname parsedUrl.pathname; res.setHeader(Content-Type, application/json; charsetutf-8); if (req.method GET pathname /user) { const name parsedUrl.searchParams.get(name) || anonymous; res.statusCode 200; res.end( JSON.stringify({ code: 0, data: { name, time: new Date().toISOString() } }) ); return; } res.statusCode 404; res.end(JSON.stringify({ code: 404, message: Not Found })); }); server.listen(3000, 127.0.0.1, () { console.log(Server running at http://127.0.0.1:3000/); });訪問http://127.0.0.1:3000/user?namenode返回{code:0,data:{name:node,time:2025-01-01T12:00:00.000Z}}這里用到了URL對象是 Node.js 內置的 URL 解析方式。比手動拆分字符串更可靠也能處理中文參數、編碼問題。4.4 啟動服務和驗證接口執行node server.js輸出Server running at http://127.0.0.1:3000/然后打開瀏覽器訪問http://127.0.0.1:3000/user?namenode或者用命令行驗證curl http://127.0.0.1:3000/user?namenode注意curl在 Windows PowerShell 中默認可能是Invoke-WebRequest的別名。如果輸出格式不同可以改用curl.exe或者使用curl.exe -v查看詳細請求過程。驗證成功后按Ctrl C終止服務器。這里最容易犯的錯誤是修改server.js后沒有重啟進程。Node.js 不會自動加載代碼修改必須結束舊進程再啟動。5. 讓開發更順手腳本、自動重啟和調試5.1 package.json 的 scripts把啟動命令寫進package.json項目就會更規范{ name: node-first-app, version: 1.0.0, main: server.js, scripts: { start: node server.js, dev: nodemon server.js } }保存后執行npm startnpm run dev需要先安裝 nodemon下面繼續講。5.2 使用 nodemon 自動重啟開發時反復手動停止、啟動服務器很低效。可以用 nodemon 監聽文件變化文件被保存時自動重啟進程npm install -D nodemon安裝后啟動npx nodemon server.js這個依賴是開發依賴只有開發環境需要。打包或部署生產環境時不應該依賴 nodemon而應該使用進程守護工具或容器管理。5.3 命令行調試與內置調試器最簡單的故障定位方法是加日志const server http.createServer((req, res) { console.log(${req.method} ${req.url}); // ... });每來一個請求終端都會輸出請求方法和 URL。遇到瀏覽器請求/favicon.ico、請求路徑不對、參數丟失時日志是最快的證據。如果日志不夠可以使用 Node.js 內置調試器node --inspect server.js然后打開 Chrome 的chrome://inspect對 Node.js 進程進行斷點調試。不過這個操作對剛入門的人可能略重先從日志排查更實際。5.4 通過日志和 curl 定位問題下面是一個簡單排查順序先看終端有沒有報錯。沒有報錯再用curl驗證接口而不是只看瀏覽器。比較瀏覽器和curl的響應差異定位請求方法、請求頭、請求參數問題。如果接口返回 404先打印req.url。如果接口返回亂碼檢查Content-Type是否帶charsetutf-8。如果請求一直超時檢查端口是否被占用、server.listen是否配置正確、防火墻是否攔截。6. 常見安裝和運行問題排查6.1 Windows 安裝報錯或缺少 Visual C Runtime在 Windows 安裝某些 Node.js 安裝包時可能輸出“需要 Microsoft Visual C 2015-2022 Redistributable”相關提示。這不是 Node.js 本身損壞而是操作系統缺少運行庫。處理方式安裝微軟官方提供的 Visual C Redistributable 包。安裝完成后重啟電腦再重新安裝 Node.js。不要在同一個系統里反復安裝多個.msi和.zip版 Node.js容易導致 PATH 混亂。6.2 輸入 node -v 提示不是內部或外部命令常見原因有三個安裝完成后沒有新開終端窗口。安裝時沒有勾選“添加到 PATH”。系統存在舊版本殘留多條 PATH 互相干擾。排查方式where node echo %PATH%如果where node找到多個路徑通常說明舊版本或不同架構的 Node.js 混在一起。建議先卸載所有不用的 Node.js只保留 nvm 管理的一個版本再重新配置 PATH。6.3 nvm install 提示 not yet released 或 not available使用 nvm 安裝具體版本時可能看到error installing 22.13.1: Node.js v22.13.1 is not yet released or is not available這通常有兩個原因nvm 本地的版本列表太舊還沒有同步到最新版本。你指定的版本號不正確或者該版本不在當前 nvm 兼容列表中。處理方式nvm list available先查可用版本再選擇列表中存在的版本號安裝。如果列表里仍然沒有嘗試升級 nvm-windows 到最新版本。不要憑感覺手寫版本號版本號必須和官方發布列表一致。6.4 npm install 很慢或超時優先檢查 registrynpm config get registry如果地址是官方源導致速度慢按前面 3.2 節配置鏡像源。如果已經是鏡像源仍然慢檢查是否項目依賴了非常多的大型包以及網絡是否不穩定。不要頻繁刪除node_modules那不是解決慢的首選方法。6.5 端口被占用啟動服務器時出現Error: listen EADDRINUSE: address already in use :::3000說明 3000 端口已經被占用。查看占用進程# Windows netstat -ano | findstr :3000 # Linux / macOS lsof -i :3000找到 PID 后確認進程可以結束再清理# Windows taskkill /PID 1234 /F也可以直接把server.js里的端口改成其他值比如3001。實際開發中端口應該通過環境變量配置不寫死在代碼里。6.6 修改代碼后頁面沒變化Node.js 不會熱更新。如果修改了server.js但瀏覽器頁面還是舊內容優先確認終端里是否重啟了服務器。如果使用 nodemon 卻仍然沒變化檢查正在執行的是不是nodemon server.js以及文件保存位置是否在 nodemon 監聽范圍內。注意瀏覽器自帶緩存也會造成“代碼改了但頁面沒變”的假象。先用curl請求接口如果curl返回新內容問題在瀏覽器緩存如果curl也返回舊內容問題在服務進程沒有重啟。7. 把第一個 Web 應用擴展到接近生產形態7.1 使用 Express 重寫接口內置http模塊適合理解原理但真實項目很少直接用它寫業務接口。更多項目會使用 Express。先安裝npm install express然后創建app.jsconst express require(express); const app express(); const port process.env.PORT || 3000; app.get(/, (req, res) { res.send(Hello Node.js Web App); }); app.get(/user, (req, res) { const name req.query.name || anonymous; res.json({ code: 0, data: { name, time: new Date().toISOString() } }); }); app.listen(port, () { console.log(Server running at http://127.0.0.1:${port}/); });Express 把路由、參數解析、JSON 響應都封裝得更容易使用。學習和實際項目之間順序是先會用http模塊再切換到 Express最后再理解 Express 的中間件機制。7.2 環境變量與默認值第一個應用里端口寫死為3000這沒問題但生產環境通常不會固定端口。推薦方式const port process.env.PORT || 3000;這樣本地不配置時用 3000部署平臺注入PORT時讀取平臺端口。學習環境可以直接在命令行運行。生產環境還要考慮日志寫到文件或集中日志平臺。進程崩潰后自動重啟。配置信息通過環境變量傳入。監聽地址根據部署平臺調整。增加健康檢查接口。7.3 目錄規約和 .gitignore即使只有幾個文件也可以從一開始建立規范node-first-app/ ├── app.js ├── package.json ├── package-lock.json └── .gitignore.gitignore至少要忽略node_modules/ .env *.lognode_modules是依賴安裝后的目錄不應該提交到 Git其他人拉取代碼后通過npm install恢復。7.4 學習環境與生產環境的差異維度學習環境生產環境啟動方式node server.js或 nodemon進程守護工具、容器、CI/CD 平臺端口寫死或process.env.PORT || 3000由平臺注入環境變量日志終端輸出獨立日志文件、日志收集系統異常處理res.end直接返回統一錯誤中間件、告警依賴開發依賴不區分npm ci --production生成可復現依賴安全僅本機訪問鑒權、限流、HTTPS、防火墻策略這里最核心的理解是能跑通不代表能上線。生產環境多出來的不是“更多代碼”而是對異常、可觀測性、回滾和安全的約束。7.5 可復用的檢查清單分享一份適合自己的項目發布前檢查清單node -v與項目要求的 Node.js 版本一致。package.json的scripts.start能正常啟動。接口使用curl -i驗證過狀態碼、響應頭和響應體。node_modules已加入.gitignore。端口沒有寫死支持process.env.PORT。異常分支有日志不會靜默失敗。不使用裸catch吞掉錯誤。不需要在終端手工維持進程時提供進程守護方案。對于剛完成第一個 Web 應用的開發者下一步可以按這個順序擴展先給接口增加表單提交和 JSON 請求體解析然后加上簡單的文件讀寫接著學習 Express 中間件再接觸數據庫連接和 ORM。每一步都保持“先起一個能跑的最小例子再逐步加功能”比一次性啃完 Node.js 所有 API 有效得多。