🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

簡介

大家好! 🤗 如果你是後端開發新手,或者你已經掌握了一些基礎知識,但想更深入地了解伺服器背後的邏輯、請求路由以及所有這些基礎概念,我真心希望這篇文章能對你有所幫助。 🥰

一開始感到困惑或無法立即理解所有內容都是完全正常的,你最終會在適當的時機弄清楚!或許這篇文章能幫你解惑,或許只是印證了你已經知道的事情!


我們將討論以下概念:

  1. 路由:前端與後端

  2. 來源伺服器

  3. 開發與生產:不僅僅是一條指令

  4. 訂單處理:快遞中的關鍵路徑管理


路由:前端與後端

路由是指當使用者存取特定URL (路徑或「路由」)時,決定傳回哪段程式碼哪個頁面。這正是這兩個世界之間的第一個主要差異

前端路由(Vite、React Router)

當我們使用現代前端框架(例如 React with Vite 或 Create React App)時,我們不需要處理靜態檔案的路由:

開發伺服器很聰明:Vite 的開發伺服器旨在幫助我們快速編寫程式碼。它知道如何讀取我們的原始檔案( src/目錄下的檔案),並自動透過相應的 URL 提供這些檔案。

自動路由:如果我們的 HTML 或 React 程式碼引用了/styles/main.css伺服器會立即知道在哪裡找到該檔案(在記憶體或檔案系統中),並立即將其傳送瀏覽器。我們無需為此編寫任何特殊程式碼❗

專注於應用邏輯:使用 React Router 等函式庫,我們只需專注於應用邏輯(例如,「如果 URL 為/profile ,則顯示 Profile 元件」)。路由操作在瀏覽器端進行,在 JavaScript 檔案載入完畢後完成。

圖片描述


後端手動路由(Express.js)

Express.js 只是一個極簡框架。它沒有任何假設,也沒有任何內建的「魔法」。

路由是手動的:一旦我們將 Express.js 設定為主伺服器,我們就必須明確地告訴它如何處理到達它的每個請求。

我們是否希望POST /api/login請求驗證資料庫中的密碼❓ 我們必須寫app.post('/api/login',...)

我們是否希望GET /api/users請求返回使用者清單❓ 我們必須寫app.get('/api/users', ...)

靜態檔案辨識錯誤:如果沒有明確指示,當 Express 收到對/main.css的請求時,它無法辨識這是一個靜態檔案。它會尋找 API 路由或渲染邏輯。由於沒有找到,它會隱式回傳404 Not Found 錯誤

在啟動時,Vite 開發伺服器會默默地執行一些神奇的操作,它會自動處理所有靜態檔案(如 CSS 和圖片)的路由和提供,直接從記憶體中讀取。

然而,當我們引入 Express.js 時,一切就變得複雜了。 Express 並不具備這種特性,它需要明確的指令。我們必須手動定義 API 路由(例如app.get('/api/data') ),更重要的是,我們必須使用express.static()手動告訴 Express:「這裡存放著網頁所需的所有靜態文件。」 如果沒有這一步,伺服器將無法存取我們的 CSS 和 JavaScript 文件,從而導致頁面無法正常顯示!


從來源到伺服器

開發中的靜態文件:

在開發過程中,當我們在 React 專案中執行npm run dev時:

無實體資料夾:Vite 伺服器直接從src/目錄讀取檔案( .jsx.css ),並將它們保存在 RAM(記憶體)中。它不會建立存放編譯文件的實體資料夾。

速度:我們儲存的任何變更都會透過 HMR(熱模組重載)立即傳輸到瀏覽器,使編碼體驗流暢。

尚未準備好投入生產:雖然速度很快,但這種模式並不穩定不安全,也沒有針對網路上成千上萬的真實用戶進行最佳化


從來源到分發:

何時以及為何需要編譯❓ 在發布應用程式(上線生產環境)之前,我們必須編譯程式碼:

指令npm run build

優化:此命令獲取我們所有的來源檔案( ReactCSS等),對其進行壓縮(使其體積更小),將其合併(將其放入更少的包中),並對其進行優化以獲得最大的加載速度。

結果dist :所有這些最佳化後的檔案都會被放入一個新的實體資料夾中,通常名稱為distbuild 。此資料夾包含前端的最終靜態版本,隨時可以提供服務。


輸入express.static()

如何提供 dist 資料夾? ❓ 現在我們有了優化後的 dist 資料夾,我們必須告訴 Express(後端)它需要公開提供的資料夾

解決方案是使用express.static() :這行程式碼是我們給 Express 伺服器的指令:

// in production, Express serves the frontend's 'dist' folder
app.use(express.static(path.join(__dirname, 'client/dist')));

→如何運作:每當伺服器收到HTTP 請求,且該請求與我們定義的API 路由不符(例如,不以/api開頭)時,Express 都會在dist 資料夾中尋找!如果找到與請求 URL 相符的檔案(例如, /style.css ),它會立即將該檔案傳送給用戶端,並停止路由程序!


開發與生產:

→ 如果我們在前端(React)和後端(Express)專案目錄中都看到了npm run dev指令,我們可能會認為它們的作用相同。但事實並非如此❗這是一個至關重要的區別,尤其是在考慮安全性效能時。

圖片描述


npm run dev :兩台伺服器,兩種用途

當我們談到開發模式(Dev)和生產模式(Prod)時,我們是在描述我們正在執行的程式碼的狀態目的

開發模式(我們的工作台):

開發模式是我們的工作台,它針對速度和除錯進行了最佳化。

目的:唯一目標是促進快速編碼測試除錯

前端設定:伺服器在一個連接埠(例如5173 )上執行Vite Dev Server

後端工具:我們使用nodemon等工具,以便在儲存變更後立即自動重新啟動伺服器。

錯誤:錯誤訊息會以醒目的方式詳細顯示(堆疊追蹤),並直接列印到您的控制台,幫助您立即解決問題

最佳化:檔案按原樣提供,優化程度極低,因為檔案大小和速度不是主要考慮因素。


生產模式(線上公共伺服器)

生產模式是最終的、經過優化的版本,面向公眾發布,其設計注重穩定性安全性

目的:目標是提供大眾穩定、快速安全的體驗。

前端設定:前端程式碼首先被建置(編譯和壓縮),然後由單一Express 伺服器在其指定連接埠(例如3000 )上提供服務。

後端工具:我們使用高度最佳化的進程管理器(如 PM2)來保持伺服器持續穩定地運作。

錯誤:錯誤訊息會在內部記錄,但絕不會向公眾使用者顯示,從而防止安全漏洞❗

最佳化:檔案經過大量壓縮和積極緩存,以實現最佳效能,並為所有用戶提供更快的載入速度。


安全風險:

為什麼我們不在生產環境中執行開發模式

在執行中的公共伺服器上以開發模式執行 Express 伺服器是一個重大的安全漏洞強烈不建議這樣做

安全漏洞:開發錯誤通常會洩漏敏感資料,例如伺服器上的檔案路徑、環境變數,甚至是資料庫結構的細節。將這些資訊洩漏給攻擊者是一個嚴重的安全漏洞

效能:開發模式旨在提供便利,而非追求速度。在實際用戶負載下,您會遇到響應速度慢、資源管理不善以及可擴展性有限等問題。

穩定性:像nodemon這樣的工具會在你儲存變更時重新啟動程式碼。對於需要 24/7 全天候執行的面向公眾的應用程式來說,這種行為不可預測且極不穩定❗


訂單處理:快遞中的關鍵路徑管理

現在,讓我們來看看設定路由和中介軟體的關鍵流程,確保 Express 能夠正確處理所有請求。

中介軟體的作用:app.use()

在 Express 中,中間件就是一個在請求-回應週期中執行的函數。它可以存取請求物件req回應物件res以及週期中的next一個函數next

app.use(middleware) : 此方法主要用於註冊中間件。它會對所有HTTP方法( GETPOST等)和所有路徑(除非我們指定路徑前綴)執行提供的函數。

黃金法則:中間件必須依照程式碼中定義的順序執行。一旦某個中間件發送了回應(例如, res.send('Hello') ),循環就會停止,後續的中間件路由處理程序都不會執行❗

流程範例順序

  1. app.use(cors)

  2. app.use(express.json)

  3. app.use('/api', apiRouter)

  4. app.use(express.static(dist_path)) <- 這是關鍵的分離點❗

  5. ……其他路線…


React Router 的陷阱:

為什麼我們需要app.get('*') ❓這是將我們的後端邏輯與前端應用程式連接起來的最後一塊拼圖。

用途app.get('*')路由是通配符處理程序。它使用通配符*來匹配任何尚未被任何中間件或之前定義的路由處理的GET請求

場景:當使用者在瀏覽器中輸入類似mysite.com/profile直接連結時,伺服器會看到對/profile請求。

  1. Express檢查API路由(例如/api )。未找到匹配項❗

  2. Express 使用express.static()檢查是否存在名為 profile 的檔案。未找到匹配項。 ❗

  3. 該請求由app.get('*')處理

解決方案:我們告訴 Express 對於任何不匹配的路徑,直接提供主應用程式檔案( index.html )。


app.get('*', (req, res) => {
    // we tell Express: "Send the HTML file and let React Router handle the URL."
    res.sendFile(path.resolve(FRONTEND_BUILD_PATH, 'index.html'));

});

結果:瀏覽器載入index.html ,React 接管,React Router 讀取/profile URL 並顯示正確的元件,從而實現流暢的單頁應用程式體驗❗


結論❤️

如果你是後端開發新手,一開始沒能理解這些概念,別灰心,它們一開始確實會讓人困惑。我想我們剛開始的時候都遇到過這些問題……我一定也遇到過! 🙃

主要挑戰在於我們需要轉變思維方式,從像 Vite 這樣的前端工具的自動記憶體服務,轉變為 Express更手動、更結構化的路由方法。

希望這篇文章對你有幫助,或是能讓你想起當初後端開發初期遇到的種種困難。 🤗

我很好奇有多少人一開始也經歷過同樣的困惑,如果你也覺得後端開發很難,請留言告訴我!我很想知道我不是唯一一個。 🤗🥰

祝您閱讀愉快!如果這篇文章對您有幫助或您覺得有用,請按個讚! 🤗


更多文章:

Node.js-建構第一個伺服器的步驟❗

我的第一個 Node.js:掌握基礎知識❗


原文出處:https://dev.to/cristea_theodora_6200140b/frontend-to-backend-from-vite-to-express-2c83


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝28   💬4   ❤️7
828
🥈
我愛JS
📝2   💬8   ❤️2
111
🥉
御魂
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付