{% embed https://hanzla-beig.netlify.app %}

聽著,我一開始就對你坦誠相待。
2026 年成為全端開發人員比以往任何時候都更容易,也更難。容易是因為工具更完善、資源更豐富,而且你可以比以往任何時候都更快地發布生產程式碼。困難在於,整個產業格局錯綜複雜,人們對你的期望越來越高,而且每個人都希望你無所不知。
我從事這行已經快十年了。我開發過慘敗的最小可行產品(MVP),維護過讓我懷疑自己職業選擇的陳舊PHP程式碼庫,將系統擴展到數百萬用戶規模,並面試過數百位候選人,指導過數十位初級開發人員。你幾乎犯過所有你能犯的錯誤,而且我仍在不斷學習。
這篇文章並非簡潔路線圖或技術清單,而是我希望當初有人能給我的建議——坦誠、實用,並且專注於為真實用戶建置真實軟體時真正重要的事項。

如果你想找一份完整的框架學習清單,你可能會失望。如果你想找人告訴你「完美」的技術棧,我也做不到。但如果你想了解2026年全端開發的實際面貌,哪些技能至關重要,哪些技能被高估,以及如何在不讓自己精疲力竭的情況下打造一份可持續發展的職業生涯,那麼請繼續閱讀。
讓我們從基礎開始。
每隔幾年,就會有人宣稱全端開發已死。 「技術棧太複雜了,」他們說,「你需要的是專家。」你知道嗎?他們說的也有幾分道理。與十年前相比,現代 Web 技術堆疊確實複雜得離譜。
但事實是:全端開發人員不會消失。實際上,我們比以往任何時候都更有價值,只是原因與以前不同了。
小型團隊和新創公司需要通才。當你是一家五人公司,正努力尋找產品與市場的契合點時,你無法負擔分別聘請前端、後端、維運和資料庫專家。你需要的是能夠跨技術棧工作、做出務實決策並快速交付功能的人才。我在三家不同的新創公司親眼見證了這一點。那些能夠接觸系統任何部分的工程師最終都成為了不可或缺的人才。
大型公司需要能夠掌握全局的人才。即使在擁有專業技術人員的大型科技公司,那些能夠理解前端、後端、資料庫和基礎設施如何協同運作的工程師也極為寶貴。他們會成為技術負責人、架構師,打破部門壁壘,真正把產品推向市場。
全端思維能讓你成為更優秀的專家。即使你最終專注於前端或後端,對前端和後端的全面了解也能顯著提升你的專業技能。了解資料庫的前端開發人員能寫出更有效率的查詢語句,了解瀏覽器的後端開發人員能寫出更優秀的API。關鍵不在於成為萬事通,而是擁有足夠的知識來做出明智的決策。
全端的定義已經演變,但並未消失。 2026年的全端開發並不代表你要寫彙編程式碼和像素級完美的 CSS。它意味著你對每一層都有足夠的了解,能夠有效率地運作並做出合理的架構決策。你知道何時應該尋求專家的協助,何時可以自己處理。
但我想先明確一下全端開發不是什麼。它不是要你精通所有框架,也不是要你聲稱自己是十五種技術的專家,更不是要你對所有技術需求都說「是」。它指的是你對整個技術堆疊都足夠了解,能夠建立完整的功能和系統,而不會因為知識缺口而屢屢受阻。

我最尊敬的開發者並非那些自詡無所不知的人,而是那些懂得足夠多、足以有所作為、認識到自身局限並在需要時迅速學習的人。
讓我們具體談談這個角色究竟包含哪些內容,因為圍繞這個術語有很多誤解和限制。
更實際的定義是:全端開發人員能夠完成從概念到部署的整個功能開發過程。他們可以建構使用者介面、編寫伺服器端邏輯、設計資料庫模式、建立部署管線,並除錯生產環境中的問題。他們不需要在任何單一領域都達到世界一流水平,但必須精通各個環節,能夠交付可用的軟體。
注意我沒說的是:「精通前端、後端、資料庫、DevOps、安全性、網路和機器學習」。這樣的人根本不存在。任何聲稱自己是萬事通的人,要嘛是在說謊,要嘛就是對「專家」的定義非常廣泛。
你每天實際做的事情:
早上,你可能正在除錯 Safari 用戶結帳流程崩潰的原因。這是瀏覽器特有的 JavaScript 問題。然後,你編寫了一個用於獲取用戶資料的 API 接口,這意味著你需要考慮資料庫查詢和快取。午餐後,你審查了某人提交的拉取請求,該請求涉及前端和後端程式碼。之後,你深入資料庫,找出報告執行緩慢的原因。下班前,你還在更新部署配置,因為預發布環境出了問題。
看規律了嗎?你一直在切換工作內容。你一天之內不會在任何一個領域深入鑽研,但你卻要解決整個技術棧上的問題。有些人覺得這樣精力充沛,有些人則覺得筋疲力盡。弄清楚自己屬於哪一種。
T型開發者模式:這是一種真正有效的思考模式。你對整個技術棧都有廣泛的了解(T的橫桿),但在一到兩個領域擁有深厚的專業知識(T的豎桿)。也許你最擅長後端架構,但也能寫出出色的React程式碼。或者你是CSS高手,也能建構REST API。關鍵在於,在某個領域擁有深厚的專業知識,同時在其他領域也能有效運作。
當我面試候選人時,我不想找那種能把整個 React API 背下來的人。我尋找的是那些曾經解決過技術棧不同層面的實際問題,並且能夠理性地分析他們所做的權衡取捨的人。
現代全端開發不需要什麼:
你不需要寫編譯器或從零開始實作 TCP/IP。你不需要知道如何最佳化彙編程式碼。你不需要成為 Kubernetes 專家,在凌晨三點除錯 CNI 網路問題。這些都是專業技能。它們固然重要,但並非成為高效能全端開發人員的必備條件。
你也不需要學習每一個新出現的框架。幾乎每週都有新的 JavaScript 框架問世,其中 99% 都可以忽略。專注於理解底層模式和原理,這樣當你真正需要新工具時,你就能輕鬆上手了。
令人不安的事實是:大多數「全端」職位招募實際上要求應徵者完成相當於兩到三個人的工作量。當你看到一份職位描述列出十五項必備技術,並要求五年經驗,而這些技術還是兩年前才出現的,這應該引起你的警惕,而不是對公司能力的合理預期。優秀的公司清楚自己真正需要什麼,並且會坦誠相告。
大多數人犯的錯誤都在這裡:他們不了解底層原理,就直接跳到 React、Node.js 或 Django 上去。然後他們遇到需要理解 Web 實際運作原理的問題,就束手無策了。
我總是能看出誰跳過了基礎知識。他們寫的程式碼技術上能執行,但存在一些不易察覺的bug,因為他們不理解HTTP快取的工作原理,也不理解瀏覽器的事件循環是如何運作的,或者當你在瀏覽器中輸入URL時實際發生了什麼。
永不過時的程式設計基礎知識:
你需要理解資料結構和演算法。這並非為了通過程式設計面試(雖然面試有幫助),而是因為在實際程式碼中你會不斷遇到這些模式。哈希表、陣列、樹、圖、排序、搜尋——這些並非紙上談兵。我每週都會用到它們。
當你除錯頁面載入緩慢的原因時,你需要了解時間複雜度。當你設計資料庫模式時,你需要了解資料結構如何對應到磁碟儲存。當你建立搜尋功能時,你需要了解不同的演算法方法及其優缺點。
但關鍵在於:你不需要記住每一種演算法。你需要理解何時使用哪種方法。我從未在生產程式碼中從頭開始實現過紅黑樹。但我需要理解平衡樹的特性才能有效地使用資料庫索引。
網路的實際運作方式:
這是不容商量的。你必須深入理解HTTP協議,而不僅僅是「GET和POST請求」。你需要理解:
請求/回應生命週期以及所有重要的標頭
狀態碼及其實際意義(不,200 並不總是表示成功)
快取技術在各個層面(瀏覽器、CDN、伺服器)的工作原理
重定向會發生什麼事?它們如何影響安全性?
Cookie、會話以及身份驗證如何透過 HTTP 進行。
CORS及其存在的原因(儘管人人都討厭它)
我見過一些資深開發人員因為從未了解瀏覽器為何強制執行同源策略而遇到 CORS 錯誤。理解 Web 的這一層面至關重要——它是一切的基礎。
JavaScript(或你選擇的任何語言):
你必須真正精通至少一種程式語言。不是淺嚐輒止,而是真正精通。你應該能夠:
閱讀並快速理解他人的程式碼
無需在每一行都使用 console.log 即可偵錯問題
了解語言的特殊之處、陷阱和慣用語模式
要分辨你是在與語言對抗,還是在巧妙地運用語言。
閱讀並理解該語言的文件。
對於大多數2026年的全端開發者來說,JavaScript/TypeScript 就是他們的首選語言。無論你喜歡還是討厭它,它都是 Web 開發的通用語言。前端開發使用 JavaScript,後端開發也常使用 Node.js。深入理解 JavaScript 會帶來豐厚的回報。
但比具體語言更重要的是:理解那些可以跨語言通用的程式設計概念。閉包、async/await、Promise、事件循環、作用域、提升、原型繼承——這些概念在大多數語言中都以某種形式存在。當你了解這些概念,學習新語言就只是學習新的文法而已。
2026 年的 TypeScript:
對於嚴肅的開發案而言,這已不再是可選項。 TypeScript 已經勝出。幾乎所有現代 JavaScript 專案都使用它,原因顯而易見:它能在 bug 進入生產環境之前將其捕獲。
但不要只是把 TypeScript 加入到專案中就萬事大吉了。要真正使用類型系統。編寫正確的類型定義。理解泛型。知道何時使用unknown ,何時使用any 。過去幾年精通 TypeScript 的開發者擁有明顯的優勢。
HTML 和 CSS 並不「容易」:
這是我最不能容忍的事情之一。太多開發者輕視 HTML 和 CSS,認為它們無關緊要。事實並非如此。語意化的 HTML 對網站的可存取性、SEO 和瀏覽器相容性都至關重要。 CSS 功能強大,而且一旦掌握了基本的樣式設置,就會發現它遠比你想像的要複雜得多。
你應該明白:
語意化 HTML 及其重要性
盒模型和CSS佈局(flexbox、grid、定位)
響應式設計原則
CSS 特異性與級聯
現代CSS特性(自訂屬性、容器查詢等)
輔助功能基礎(ARIA、鍵盤導航、螢幕閱讀器)
我看過一些後端開發人員試圖編寫前端程式碼,結果卻導致網站無法存取、回應遲鈍、體驗糟糕,因為他們把 HTML/CSS 當作事後才考慮的東西。千萬別成為那樣的人。
了解瀏覽器:
瀏覽器是前端程式碼的執行環境。你需要了解它的工作原理:
渲染管線(解析、佈局、繪製、合成)
JavaScript 事件循環和微任務佇列
瀏覽器 API(fetch、storage、notifications 等)
開發者工具及其有效使用方法
效能分析與優化
當你的頁面執行卡頓時,你需要知道原因。是佈局頻繁切換? JavaScript 程式碼開銷過大?還是 DOM 節點過多?你無法除錯你不了解的問題。
基本面會帶來複利效應:
原因如下:框架層出不窮,React 或許五年後不再佔主導地位。但 HTTP 協定不會改變,瀏覽器的事件循環也不會改變。如果你的基礎紮實,就能適應任何新出現的工具或框架。
我曾與一些開發者共事,他們在學習 React 時對 JavaScript 一無所知。當他們遇到需要理解閉包或異步行為的問題時,就束手無策了。我也曾與一些開發者共事,他們先深入學習了 JavaScript,一週內就掌握了 React。
投資基本面。這並非花俏的建議,而是真正有效的建議。
讓我們來談談 2026 年前端開發的實際發展方向,以及你需要掌握哪些知識才能勝任這項工作。
核心技術:HTML、CSS、JavaScript
我之前已經講過了,但值得再次強調:這些步驟不可或缺。每個框架最終都會編譯成 HTML、CSS 和 JavaScript。當出現問題時(而問題肯定會發生),你需要了解瀏覽器端實際發生了什麼。
React 的主導地位(以及這是否重要):
React 仍然是前端框架中的巨頭。它擁有最大的生態系統、最多的就業機會和最豐富的社區資源。如果你在 2026 年學習前端,React 仍然是就業前景最穩健的選擇。
但我真正的想法是:React 不錯,但它並不神奇。它只是一個用於建立元件化用戶介面的庫。僅此而已。元件、props、狀態、生命週期這些概念,在所有現代框架中都存在。如果你深入了解這些概念,你就可以學習 Vue、Svelte、Angular,或任何後續的框架。
我2016年學習了React。我也用Vue、Angular、Svelte和原生JavaScript寫過生產程式碼。文法雖然不同,但思考模式是相似的。不要對任何特定的框架過於執著,要理解其底層模式。
React 的哪些概念真正重要:
元件和組合(將使用者介面拆分成可重複使用的模組)
props 與 state(React 應用程式中的資料流)
鉤子函數(useState、useEffect、useContext 和自訂鉤子函數)
元件生命週期以及渲染時機
事件處理與合成事件
受管製成分與非管製成分
超越本地組成狀態的狀態管理
你不需要記住每一個鉤子函數,也不需要了解每一種最佳化技巧。你需要理解 React 的渲染模型是如何運作的,以及如何編寫易於維護且效能足夠的元件。
國家管理(永恆的爭論):
這就是開發者浪費大量時間爭論的地方:Redux、MobX、Zustand、Context API,以及上週新出的那些東西。
事實是:對於大多數應用程式來說,你並不需要複雜的狀態管理函式庫。 React 內建的狀態和上下文就足夠了。我曾經只用 useState、useContext 和幾個自訂 hooks 就建立了服務數十萬用戶的生產應用程式。
什麼時候才真正需要 Redux 或 Zustand 之類的工具?當你的狀態邏輯複雜到用 React 管理起來非常痛苦時;當你需要進行時間旅行式的除錯時;當你的元件嵌套很深,共享大量狀態時。而不是因為有人告訴你「真正的應用都用 Redux」。
最佳的狀態管理方案就是能夠解決實際問題的最簡單方案。從簡單的方案入手,僅在需要時才增加複雜性。
CSS框架與元件庫:
應該使用 Tailwind? Material UI? Bootstrap?還是從零開始建立自己的元件?
務實的答案是:這取決於你的團隊和時間安排。 Tailwind 已經變得非常流行,而且理由充分——一旦你學會了它,它就能顯著提高效率。像 Material UI 或 Chakra UI 這樣的元件庫可以讓你更快地發布產品,但客製化可能比較困難。
我的方法:先理解 CSS,然後再把框架當作提高效率的工具。如果你不用 Tailwind 就無法建立響應式佈局,那就表示你對 CSS 的理解還不夠深入。但一旦你了解 CSS,Tailwind 就成了加速開發的強大工具。
大多數專案我使用 Tailwind 進行樣式設計並建立自訂元件。對於內部工具或 MVP(最小可行產品),我會選擇元件庫以加快開發速度。沒有萬能的解決方案。
現代 JavaScript 工具:
JavaScript 工俱生態系統非常龐大。 Webpack、Vite、esbuild、Rollup、Turbopack。套件管理器:npm、yarn、pnpm。建置工具、打包工具、轉譯器、程式碼檢查器、格式化工具。
好訊息是:你不需要深入了解所有這些內容。你只需要了解足夠的知識,以便在出現問題時能夠解決問題,並為你的專案做出合理的選擇。
2026年,我建議:
Vite 適用於新專案(速度快,預設值合理)
pnpm 或 npm 都可以用來管理軟體套件(兩者都可以)。
ESLint 用於程式碼檢查(配置合理,而非過於嚴苛)
格式更美觀(直接用就好,別再爭論分號的問題了)
用於類型檢查的 TypeScript
大多數現代框架(例如 Next.js、Remix、SvelteKit)都會幫你處理許多這類設定。通常情況下,這樣就足夠了。不要過度設計你的建造設定。
Next.js 與元框架:
Next.js 已成為 React 應用的事實標準架構。它負責路由、伺服器端渲染、API 路由以及其他諸多功能。對於大多數 2026 年的 React 專案而言,從 Next.js 入手無疑是明智之舉。
但要理解 Next.js 的工作原理。它並非魔法——它抽象化了配置,並為常見問題(路由、資料擷取、伺服器端渲染)提供了模式。遇到問題時,你需要理解其底層概念。
其他生態系統也存在類似的元框架(例如 Vue 的 Nuxt、Svelte 的 SvelteKit、React 的 Remix)。它們都在以略微不同的方式解決類似的問題。
無障礙設施並非可有可無:
說實話:大多數開發者都會建立難以存取的介面。他們並非故意如此——只是從未學習過如何建立無障礙使用者介面,而且程式碼審查也無法發現這些問題。
你需要明白:
語意化 HTML 和 ARIA 屬性
鍵盤導航(你的應用程式可以在不使用滑鼠的情況下使用嗎?)
螢幕閱讀器測試(至少使用螢幕閱讀器進行基本測試)
色彩對比度和視覺可存取性
注意力管理和注意力陷阱
圖片和多媒體的替代文本
這並非僅僅為了避免訴訟(儘管避免訴訟也很重要),而是為了開發人人都能使用的軟體。世界上約有15%的人患有某種形式的殘疾。你的軟體應該能夠幫助他們。
表現比你想像的更重要:
我見過太多開發者忽視效能問題,直到它演變成危機。然後,他們才在截止日期的壓力下拼命優化執行緩慢的應用程式。
績效提升應該是持續性的,而不是恐慌性的因應。請理解:
如何分析您的應用程式(Chrome 開發者工具、Lighthouse)
常見的效能瓶頸(軟體包大小、渲染、網路)
程式碼分割和延遲載入
影像優化
快取策略
網路指標及其衡量內容
你無需對每一毫秒都斤斤計較,但應該避免明顯的性能殺手。不要在頁面載入時載入 2MB 的 JavaScript 套件。不要渲染 10,000 個 DOM 節點。不要在每次路由切換時都發出 50 個 API 請求。
測試前端程式碼:
這可能存在爭議,但我的觀點是:前端程式碼不需要 100% 的測試覆蓋率。你需要針對以下方面編寫測試:
複雜的業務邏輯
關鍵使用者流程(身份驗證、結帳等)
應用內可使用的可重複使用元件
任何以前損壞過並導致事故的東西
我混合使用了以下幾種方法:
複雜函數和鉤子的單元測試(Vitest 或 Jest)
關鍵流程的整合測試(React 測試庫)
針對關鍵使用者旅程的端對端測試(Playwright 或 Cypress)
不要測試實作細節,要測試行為。如果你因為重構了元件內部結構而不斷修復測試,那麼你的測試就太脆弱了。
(目前)可以跳過以下內容:
你不需要學習:
每個動畫庫
每個圖表庫
WebGL 和 Three.js(除非你要建立 3D 體驗)
WebAssembly(除非您有特定的效能需求)
每一種設計模式和架構
專注於動手實作。你會在實踐中逐漸了解自己需要什麼。
身為全端開發人員,後端開發可能是你花費時間最多的地方,所以讓我們來探討一下真正重要的內容。
選擇後端語言和生態系統:
2026年最常見的選擇:
Node.js/TypeScript(JavaScript 無所不在,生態系統龐大)
Python(非常適合資料密集型應用,Django/FastAPI 非常出色)
Go(快速、簡單、非常適合服務)
Java/Kotlin(企業級標準,龐大的生態系)
C#(工具強大,企業級應用廣泛)
Ruby(Rails 仍然很有發展潛力)
我給全端開發者的建議是:從 Node.js/TypeScript 入手。既然你已經在學習前端 JavaScript,那麼在後端使用它就能減輕認知負擔。 Node.js 生態系統成熟,工作機會眾多,你可以建立真正的生產系統。
但說實話,具體用哪種語言並沒有你想像的那麼重要。選擇一種語言,精通它,然後根據需要學習其他語言。我大部分專案都用 Node.js 開發,但也用 Python、Go 和 Java 部署過生產環境。一旦你了解後端概念,換語言就只是學習新的文法而已。
了解 HTTP 和 REST API:
你會花很多時間建立 API。請記住:
RESTful 原則(但不要教條式地遵循這些原則)
HTTP 方法及其使用時機(GET、POST、PUT、PATCH、DELETE)
狀態碼及其意義(請正確使用!)
請求/回應結構
重要的標頭(身份驗證、快取、內容協商)
冪等性及其重要性
API 版本控制策略
一個常見的錯誤是:將後端僅視為資料庫代理。後端應該包含業務邏輯、驗證、授權和編排。 API 只是接口,而不是後端的全部。
框架:Express、Fastify、NestJS 等:
對於Node.js來說,其發展格局已經改變了:
Express:老牌經典。簡潔、極簡、應用廣泛。即使到了2026年依然適用。
Fastify:比 Express 更快,對 TypeScript 的支援更好,用戶群正在不斷成長。
NestJS:具有鮮明的設計理念,受 Angular 啟發,非常適合大型團隊和複雜應用程式。
我的看法:Express 適合中小型專案。如果你注重效能,那就用 Fastify。如果你要和團隊一起開發大型應用,並且需要嚴格的規範,那就用 NestJS。
別想太多。選一個框架,做點東西,學習它的模式。以後如果需要,隨時可以切換。
身份驗證和授權:
這是很多開發者都會遇到的難題。身份驗證很複雜,一旦出錯就會造成安全隱患。
你需要明白:
身份驗證(你是誰?)和授權(你能做什麼?)之間的區別
基於會話的身份驗證與基於令牌的身份驗證
JWT:工作原理、適用場景及常見陷阱
OAuth 2.0 和 OpenID Connect(至少掌握基礎)
密碼哈希(bcrypt、argon2)
常見攻擊:CSRF、XSS、會話固定等。
對於2026年的大多數專案,我建議:
如果預算允許,請使用身分驗證提供者(Auth0、Clerk、Supabase Auth)。
如果自行建置:JWT 存取令牌 + 刷新令牌,並妥善儲存。
永遠不要自己創造加密貨幣
生產環境中始終使用 HTTPS
對認證端點實施速率限制
身份驗證就是其中一個例子,使用第三方解決方案通常比自行建立更明智。對於大多數專案而言,節省的時間和安全性的提升足以彌補成本。
資料庫操作(下一節將詳細介紹):
從後端角度來看,你需要:
編寫高效的查詢
理解 N+1 查詢問題以及如何避免它們
使用連線池
正確處理交易
實作資料庫操作的正確錯誤處理
了解何時以及如何緩存
中間件和請求/回應生命週期:
這是一個核心的後端概念,起初可能會讓人感到困惑。中間件是在路由處理程序之前執行的程式碼。它的用途是:
身份驗證/授權
請求驗證
日誌記錄
錯誤處理
CORS
限速
理解中間件模式能顯著提高後端開發效率。它能幫助你組織橫切關注點,避免程式碼重複。
錯誤處理和日誌記錄:
生產後端經常出現故障。網路問題、資料庫逾時、無效使用者輸入、程式錯誤-出錯的方式數不勝數。
你需要:
每層都應妥善處理錯誤。
結構化日誌記錄(JSON 日誌,而不僅僅是 console.log)
錯誤監控(Sentry、Datadog 或類似工具)
請求追蹤(用於跨服務追蹤請求的關聯 ID)
健康檢查終點
優雅關閉處理
不要只是捕獲錯誤然後忽略它們。不要記錄敏感資料。不要因為一個請求失敗就導致整個伺服器崩潰。要優雅地處理錯誤,記錄有用的訊息,並使你的系統可觀測。
API設計原則:
好的 API 設計比看起來難。以下是一些原則:
保持一致性(不要對相似的端點使用不同的模式)
使用清晰、描述性的名稱
從一開始就對 API 進行版本控制。
傳回對應的狀態碼
提供有用的錯誤訊息
編寫 API 文件(使用 OpenAPI/Swagger 或類似工具)
考慮向後相容性
我維護 API 多年,深知破壞性變更帶來的痛苦。設計 API 時,不僅要考慮眼前的需求,更要著眼於未來的發展。
後台任務和隊列:
並非所有操作都應該在請求/回應週期內完成。耗時較長的任務(例如發送電子郵件、處理影像、產生報告)應該非同步處理。
你需要明白:
作業佇列(Bull、BullMQ、RabbitMQ 等)
何時使用後台任務,何時使用請求處理程序
作業重試和錯誤處理
作業調度(類似 cron 的任務)
對於大多數專案來說,像 BullMQ 搭配 Redis 這樣的方案是一個不錯的選擇。除非必要,否則不要把事情搞得太複雜。
即時功能(WebSocket、伺服器發送事件):
如果您正在建立聊天、通知、即時更新或協作功能,則需要即時通訊。
選項:
WebSocket(雙向,全雙工)
伺服器發送事件(更簡單,僅限伺服器到客戶端)
長輪詢(舊版瀏覽器的備用方案)
可以使用 Socket.io(WebSocket)之類的函式庫,或是直接使用原生瀏覽器 API 並配合後端實作。即時性比較複雜-對於真正需要即時性的場景,可以考慮使用 Pusher 或 Ably 之類的服務。
驗證和清理:
永遠不要相信使用者輸入。永遠不要。務必驗證所有內容:
請求體結構和類型
路徑參數和查詢字串
文件上傳
標題
使用驗證庫(例如 Zod、Joi、Yup)定義模式並進行驗證。對輸入進行清理以防止注入攻擊。向使用者傳回清晰的驗證錯誤訊息。
速率限制和安全:
保護您的 API 免於濫用:
速率限制(按用戶、按 IP、按端點)
敏感端點的身份驗證
輸入驗證和清理
CORS 配置
安全標頭(helmet.js 或等效檔案)
SQL注入預防(使用參數化查詢)
XSS 防護(不要渲染未經清理的使用者輸入)
安全不是一份清單,而是一種思考方式。要思考可能出現的問題,並做好防範措施。
我發現錯誤最多的地方就在這裡。開發者不考慮資料模型就匆忙編寫程式碼,最終會得到糟糕的資料庫模式,並為此困擾多年。
SQL 與 NoSQL(永無止境的爭論):
讓我們拋開炒作,看看2026年的真實情況:
SQL資料庫(PostgreSQL、MySQL等):
具有關係的結構化資料
ACID交易
複雜查詢和連接
成熟的工具和生態系統
大多數商業應用
NoSQL 資料庫(MongoDB、DynamoDB 等):
靈活的模式(既可以是優點也可以是缺點)
水平擴展(儘管現代 SQL 資料庫的擴展性很好)
文件儲存
具體應用場景(快取、即時、時間序列等)
我的建議:大多數應用程式都預設使用 PostgreSQL。它非常成熟、功能豐富,能夠滿足絕大多數的使用場景。只有在有特殊原因的情況下才使用 NoSQL,而不是因為它聽起來很酷。
我曾參與過一些專案,因為「可能需要擴展」而選擇了 MongoDB,結果導致資料混亂不堪,不一致,而且缺乏引用完整性。我也參與過一些專案,明明文件資料庫比較簡單,卻強行把所有東西都用 PostgreSQL。選擇資料庫應該基於你的實際需求,而不是盲目跟風。
關係資料建模:
這是一項需要時間培養的技能。優秀的資料建模包括:
了解你的領域和關係
歸一化以減少冗餘(但不要過度歸一化)
選擇正確的主鍵
設計外鍵關係
考慮一下你需要執行的查詢
規劃模式演化
常見錯誤:
儲存 JSON 資料塊時應該使用正確的關係。
過度正常化與製造地獄
不考慮指數
不假思索地使用 VARCHAR(255) 來表示所有資料
命名規則不合理
學習資料庫規範化(1NF、2NF、3NF)。了解何時需要反規範化以提高效能。思考資料將如何成長以及如何查詢這些資料。
編寫優秀的 SQL:
你需要熟練 SQL 編寫,不僅僅是簡單的 SELECT 語句,而是實際的查詢語句:
-- Joins
SELECT u.name, p.title
FROM users u
JOIN posts p ON u.id = p.user_id;
-- Aggregations
SELECT category, COUNT(*), AVG(price)
FROM products
GROUP BY category
HAVING COUNT(*) > 5;
-- Subqueries
SELECT name FROM users
WHERE id IN (SELECT user_id FROM orders WHERE total > 1000);
-- CTEs (Common Table Expressions)
WITH recent_orders AS (
SELECT * FROM orders WHERE created_at > NOW() - INTERVAL '7 days'
)
SELECT user_id, COUNT(*) FROM recent_orders GROUP BY user_id;
ORM 非常強大(下文會詳細介紹),但它們抽象掉了實際發生的情況。當查詢速度慢時,你需要了解實際產生的 SQL 語句以及如何最佳化它。
了解指數:
索引是資料庫保持快速運作的關鍵。你需要了解:
什麼是索引以及它們如何運作(B樹、哈希索引)
何時新增索引(用於 WHERE、JOIN、ORDER BY 子句的欄位)
索引的成本(它們會減慢寫入速度)
複合索引和列順序
覆蓋指數
如何分析查詢效能(EXPLAIN ANALYZE)
常見現象:應用程式在開發環境中處理 100 行資料時運作良好,但在生產環境中處理 1000 萬行資料時卻執行緩慢甚至崩潰。為什麼?缺索引。
不要盲目地為所有內容建立索引,但一定要建立索引:
主鍵(通常是自動的)
外鍵
WHERE 子句中常用的列
連接中使用的列
ORDER BY 中使用的列
ORM:Prisma、TypeORM、Sequelize:
物件關聯映射器 (ORM) 可讓您使用程式語言而非原始 SQL 來操作資料庫。 2026 年,TypeScript/Node.js 將支援此功能:
Prisma :我目前最喜歡的軟體。 DX效能優異,類型安全,遷移功能優秀。
TypeORM :更像傳統的 ORM,功能很多,也更複雜。
Sequelize :老牌產品,仍然被廣泛使用,還不錯。
ORM 簡化了常見操作並防止了 SQL 注入。但如果不小心,它們可能會產生低效率的查詢。務必了解 ORM 產生的 SQL,尤其是在處理複雜查詢時。
N+1 查詢問題是 ORM 的經典陷阱:
// This makes N+1 queries (BAD)
const users = await User.findAll();
for (const user of users) {
const posts = await user.getPosts(); // Additional query for each user
}
// This makes 2 queries (GOOD)
const users = await User.findAll({
include: [{ model: Post }] // Join in the initial query
});
學習 ORM 的查詢最佳化技巧。使用預加載。在開發環境中對查詢進行效能分析。
遷移和模式演化:
您的資料庫架構會隨著時間推移而改變。您需要一個相應的流程:
版本控制的遷移文件
安全的遷移方法(無資料遺失)
復原功能
生產環境前測試遷移
零停機部署
大多數 ORM 都包含遷移工具。請使用它們。切勿手動修改生產環境中的資料結構。
一個實際範例:在一個大型表中新增一個 NOT NULL 欄位。如果只是簡單地新增一個帶有 NOT NULL 屬性的列,遷移程序會鎖定該表,並可能導致逾時。較穩健的做法是:
將該列設為可空。
回填資料
新增 NOT NULL 約束
這是透過犯錯(或從他人的錯誤中學習)而獲得的經驗。
交易和資料一致性:
當多個資料庫操作需要同時成功或失敗時,就需要使用事務:
// Without transaction (BAD - money could be lost)
await updateBalance(fromAccount, -amount);
// Crash here = money disappeared!
await updateBalance(toAccount, +amount);
// With transaction (GOOD)
await db.transaction(async (trx) => {
await updateBalance(fromAccount, -amount, trx);
await updateBalance(toAccount, +amount, trx);
// Both succeed or both fail
});
了解 ACID 屬性、隔離等級以及何時需要事務。
資料庫效能和優化:
當你的應用程式運作緩慢時,通常是資料庫的問題。學習如何:
分析慢查詢(PostgreSQL 中的 pg_stat_statements)
使用 EXPLAIN ANALYZE 了解查詢計劃
加入適當的索引
最佳化查詢(避免使用 SELECT *,減少連接,使用分頁)
實施快取策略(詳見下文)
對於讀取密集型工作負載,可以考慮使用唯讀副本。
使用連線池
效能優化是一個持續的過程,而不是一次性的任務。
快取策略:
快取可以讓慢的程式運作得更快。但如果使用不當,它也可能引入一些不易察覺的錯誤。
快取層:
應用層(記憶體中,變數)
分散式快取(Redis、Memcached)
資料庫查詢快取
CDN快取(針對靜態資源)
HTTP快取(瀏覽器快取)
緩存失效是出了名的難。快取資料時,你需要一個失效策略:
基於時間(TTL)
基於事件的(資料更改時清除快取)
混合方法
Redis 將是 2026 年快取的首選方案。它速度快、可靠性高,並且為每種語言都提供了優秀的客戶端庫。
處理時間和日期:
這一點值得特別一提,因為它會引發無窮無盡的漏洞。
始終以UTC格式儲存時間戳記。
請使用正確的日期/時間類型(TIMESTAMP,而不是VARCHAR)。
向使用者顯示時區資訊時要格外小心。
了解 DATE、TIMESTAMP 和 TIMESTAMPTZ 之間的差異
使用日期處理庫(date-fns、dayjs)
我除錯過無數時區相關的錯誤。儲存時使用 UTC 時間,顯示時再轉換。就這麼簡單,但每個人都會忘記。
讓我們來談談在 2026 年建立和保護 API 的實際情況。這將是理論知識與生產難題相遇的時刻。
REST、GraphQL 和 gRPC:
每個人對此都有自己的看法。以下是我根據實際生產出貨經驗得出的看法:
REST API:
REST 仍然是大多數 Web 應用程式的預設選擇。它簡單易懂,工具齊全,幾乎適用於所有場景。除非你有特殊原因需要使用其他協議,否則 REST 很可能是正確的選擇。
優點:簡單、可快取、無狀態、通用支持
缺點:資料過度取得/取得不足,版本控制可能很麻煩,需要多次往返。
GraphQL:
對於希望靈活獲取資料的前端團隊來說非常棒。但如果沒有完善的規範和治理,那就糟了。
我看過 GraphQL 在管理規範的團隊專案中表現出色,也看過它變成一團難以維護的爛攤子,每個前端開發人員都編寫自訂查詢,對資料庫造成巨大壓力。
優點:資料取得靈活、型別控制強大、單一端點
缺點:複雜度高,快取難度高,可能導致低效率查詢,需要更多基礎設施。
gRPC:
最適合服務間的通訊。不太適合瀏覽器導向的 API(儘管有 gRPC-web)。
我使用 gRPC 來建立內部微服務。它速度快、類型安全,而且工具鏈非常完善。但是對於面向公眾的 API 呢?我會選擇 REST 或 GraphQL。

我的建議:先從 REST 開始。如果你的前端團隊不斷要求加入新的接口,或者你的資料需求變化很大,再考慮遷移到 GraphQL。如果需要高效能和類型安全,內部服務可以使用 gRPC。
API 版本控制策略:
你需要對 API 進行版本控制。這不是是否需要版本控制的問題,而是何時需要版本控制的問題。以下是一些方法:
URL 版本控制: /api/v1/users , /api/v2/users
優點:清晰、簡潔、易於規劃
缺點:基礎設施重複、URL污染
標頭版本控制: Accept: application/vnd.myapp.v1+json
優點:簡潔的URL,RESTful架構愛好者喜歡它
缺點:不太容易被察覺,在瀏覽器中測試起來也更困難
查詢參數: /api/users?version=1
優點:簡單、靈活
缺點:容易忘記,快取複雜
我大多數專案都使用 URL 版本控制。它清晰可見、明確易懂。沒錯,這意味著需要維護多個版本,但這本來就是現實。
關鍵在於:版本控制是為了給客戶爭取遷移時間,而不是為了永遠維護無限多個版本。支援 v1 版本,發布 v2 版本,給客戶 6-12 個月的時間進行遷移,然後棄用 v1 版本。
2026 年的身份驗證模式:
讓我們具體探討一下在生產環境中真正有效的方法。
基於會話的身份驗證:
伺服器儲存會話狀態(記憶體、Redis、資料庫)
客戶端會獲得一個會話 cookie
伺服器在每次請求時都會驗證 cookie
對於傳統 Web 應用來說仍然非常有效。簡單易用,如果操作得當也很安全,而且很容易使會話失效。
JWT(JSON Web Tokens):
包含編碼聲明的無狀態令牌
客戶端儲存令牌(通常儲存在 localStorage 或 httpOnly cookie 中)
伺服器對每個請求驗證令牌簽名
JWT很受歡迎,但也有失誤:
你無法使它們失效(它們是無狀態的)。
如果將它們儲存在 localStorage 中,則容易受到 XSS 攻擊。
代幣大小可能因索賠數量眾多而變得很大。
刷新令牌輪換機制很複雜。
我2026年的方法:
有效期限較短的 JWT 存取權令牌(15 分鐘)
儲存的更長時間的刷新令牌僅支援 http
使用時刷新令牌輪換
伺服器端儲存的刷新令牌用於撤銷
這樣一來,對於大多數請求,JWT 就具有無狀態性,但同時也能夠在需要時撤銷存取權限。
OAuth 2.0 與社群登入:
對於大多數應用程式,您需要支援社交登入(例如 Google、GitHub 等)。不要自己實作 OAuth,請使用現成的函式庫:
Node.js:passport.js、auth.js(原名 NextAuth)
Python:authlib、python-social-auth
或使用身份驗證提供者(Auth0、Clerk、Supabase)
OAuth 非常複雜,涉及許多流程和安全考慮。除非您正在建立身份提供程序,否則最好將其抽象化。
密碼安全:
如果你要儲存密碼(如果可能的話應該避免這樣做),那麼你需要以下幾點:
使用 bcrypt 或 argon2 對密碼進行雜湊處理(切勿使用 MD5、SHA1 或明文儲存)
使用高工作因子(bcrypt 輪數、argon2 參數)
對登入嘗試次數實施速率限制
嘗試失敗後考慮鎖定帳戶
務必在所有地方使用HTTPS(使用明文HTTP傳輸密碼是不可原諒的)。
密碼重置流程應該安全可靠(使用有時效性的令牌,而不是安全性問題)。
使用 bcrypt 的範例:
// Hashing a password
const saltRounds = 12;
const hashedPassword = await bcrypt.hash(plainPassword, saltRounds);
// Verifying a password
const isValid = await bcrypt.compare(plainPassword, hashedPassword);
永遠不要記錄密碼。永遠不要在URL中發送密碼。永遠不要將密碼儲存在原始碼控制系統中(這看似顯而易見,但卻經常發生)。
API 安全要點:
除了身份驗證之外,您還需要保護您的 API:
限速:
防止濫用和DDoS攻擊。實施速率限制:
IP位址(適用於公共端點)
使用者/API金鑰(用於已認證的端點)
端點類型(登入嘗試次數應受到更嚴格的限制)
如果您有多台伺服器,請使用 Redis 進行分散式速率限制。
輸入驗證:
驗證所有內容。使用驗證庫(例如 Zod、Joi)定義模式:
const userSchema = z.object({
email: z.string().email(),
age: z.number().min(18).max(120),
name: z.string().min(1).max(100)
});
// In your route handler
const userData = userSchema.parse(req.body); // Throws if invalid
不要只檢查類型—也要驗證範圍、格式和長度。然後進行清理以防止注入攻擊。
SQL注入防護:
使用參數化查詢或 ORM。切勿將使用者輸入拼接成 SQL:
// NEVER do this
const query = `SELECT * FROM users WHERE email = '${userInput}'`;
// Do this
const query = 'SELECT * FROM users WHERE email = $1';
const result = await db.query(query, [userInput]);
使用 ORM 時,這通常會自動處理。但了解其底層運作原理也很重要。
XSS(跨站腳本攻擊)防護:
永遠不要在 HTML 中渲染未經清理的使用者輸入。使用會自動轉義的框架(React 預設會這樣做)或明確地進行清理(DOMPurify)。
CSRF(跨站請求偽造)防護:
使用 SameSite Cookie
實作 CSRF 令牌以進行狀態變更操作
API 請求需要自訂標頭
雙重提交 cookie 模式
CORS(跨域資源共享):
這是每個人都最頭痛的問題。 CORS 的存在是為了安全,而不是為了惹惱你。
// Don't do this in production
app.use(cors({ origin: '*' })); // Allows all origins
// Do this
app.use(cors({
origin: ['https://yourdomain.com'],
credentials: true // If using cookies
}));
了解預檢請求及其存在的原因。正確配置 CORS,否則將有安全漏洞。
安全標頭:
使用 helmet.js 或類似工具設定安全標頭:
內容安全策略
X-Frame-Options
X-Content-Type-Options
嚴格運輸安全 (HSTS)
這些並非萬全之策,但卻是縱深防禦。
秘密管理:
永遠不要將密鑰提交到版本控制系統。請使用環境變數和密鑰管理方式:
開發環境: .env檔(位於 .gitignore 中)
生產環境:金鑰管理服務(AWS Secrets Manager、HashiCorp Vault 等)
CI/CD:加密環境變數
定期輪換密鑰。限制對生產環境密鑰的存取。
API金鑰、OAuth和使用者會話:
針對不同情況採取不同的身份驗證方式:
面向使用者的 Web 應用程式:會話 cookie 或帶有刷新令牌的 JWT
行動應用:使用刷新令牌的 OAuth
服務間通訊:API金鑰或相互TLS
公共 API:具有速率限制的 API 金鑰
處理敏感資料:
某些資料需要額外保護(個人辨識資訊、付款資訊、健康資料):
靜態資料加密(資料庫加密)
傳輸過程中加密(HTTPS/TLS)
謹慎記錄(切勿記錄密碼、令牌或敏感的個人辨識資訊)
考慮資料駐留要求(GDPR 等)
實施適當的存取控制
制定違規應對計劃
支付資料?請使用 Stripe 或其他支付處理商。不要自行儲存信用卡號。 PCI 合規性簡直是惡夢。
常見的安全錯誤:
我見過所有這些產品的實際生產情況:
信任客戶端驗證-始終驗證伺服器端驗證
公開錯誤詳情-向客戶端顯示通用錯誤訊息,向伺服器端顯示詳細日誌
沒有速率限制——很容易被利用。
會話管理薄弱-會話固定、無逾時、ID可預測
不安全的直接物件參考- 從令牌檢查userId ,但未進行授權檢查
批量賦值漏洞- 允許使用者設定物件上的任何字段
2026年了,不使用HTTPS是不可原諒的。
硬編碼的秘密——它們最終都會洩漏。
安全防護講究多層疊加。沒有哪一種單一措施是完美的,但多層防護能大大增加攻擊難度。
說實話,身為2026年的全端開發人員,你需要了解部署。你不需要成為DevOps專家,但你需要將程式碼部署到生產環境並保持其運作。
雲層景觀:
三大主要玩家佔據主導地位:
AWS(亞馬遜網路服務):
最成熟,服務最多,最複雜
學習曲線陡峭,但功能極為強大
仍然是許多公司的預設選項
Google Cloud Platform (GCP):
良好的開發經驗,精通機器學習/資料
Kubernetes原生
市佔率低於 AWS
Azure:
企業級實力雄厚,尤其是在微軟商店方面。
與 .NET 生態系統良好集成
成長迅速
對於大多數新專案,我建議從比較簡單的方案開始:
Vercel:最適合 Next.js 和前端應用。使用 git push 即可部署。極為簡單。
Netlify:類似 Vercel,非常適合靜態網站和 JAMstack。
Railway/Render:適用於全端應用程式的簡易託管方案。介於 PaaS 和 IaaS 之間的理想選擇。
Fly.io:在全球用戶附近部署 Docker 容器。價格合理,技術先進。
我的建議:從簡單的方案著手。先使用 Vercel 或 Railway,直到需要更強大的功能。等到有具體需求時,再升級到 AWS/GCP。
別一開始就用 Kubernetes。真的。你現在還不需要它。
了解 Docker:
你需要對容器有基本的了解。這並非因為你總是會用到它們,而是因為它們是現代部署的基礎。
一個簡單的Node.js應用程式Dockerfile:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
理解:
圖片與容器
層和快取
針對較小圖像的多階段建置
容器中的環境變數
連接埠對映和網路基礎知識
用於本地開發的 Docker Compose:
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://db:5432/myapp
db:
image: postgres:15
environment:
- POSTGRES_DB=myapp
這為您提供了與生產環境一致的可重現本地環境。顛覆性的變革。
CI/CD 管線:
持續集成和部署。每次提交都應觸發:
語法檢查和格式檢查
執行測試
建立應用程式
部署(如果測試通過)
熱門選項:
GitHub Actions(我目前最喜歡的工具——與 GitHub 緊密整合)
GitLab CI
CircleCI
Jenkins(雖然老舊但仍在企業中使用)
一個簡單的 GitHub Actions 工作流程:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm test
- run: npm run build
- name: Deploy
run: npm run deploy
env:
API_KEY: ${{ secrets.API_KEY }}
先從簡單的入手,再根據需要增加複雜性。目標是自動化那些繁瑣的工作,這樣你就可以專注於開發功能。
環境管理:
您需要多個環境:
本機:您的開發機器
開發/測試環境:共享測試環境
製作:貨真價實
保持相似但不完全相同。產品應具備:
更多資源
更好的監測
更嚴格的安保措施
備份/災難復原
使用環境變數進行配置。切勿將特定於環境的值硬編碼到程式碼中。
生產環境中的資料庫遷移:
部署資料庫變更比部署程式碼變更更令人擔憂。以下是如何安全地執行此操作:
編寫向後相容的遷移
先部署遷移檔案(在使用它的程式碼之前)。
部署新程式碼
移除舊程式碼路徑
清理舊的資料庫結構
例如:重新命名列
步驟 1:新增列,保留原列
步驟 2:部署寫入兩列的程式碼
步驟 3:將資料回填到新列
步驟 4:部署從新欄位讀取資料的程式碼
步驟 5:刪除舊列
切勿在同一部署環境中刪除不再使用的欄位或表格。務必預留回滾路徑。
監測和可觀測性:
你無法修復你看不見的東西。你需要:
應用效能監控(APM):
回應時間、錯誤率、吞吐量
工具:Datadog、New Relic、AppDynamics
錯誤追蹤:
捕獲異常、堆疊追蹤和上下文
工具:哨兵、Rollbar、Bugsnag
日誌記錄:
結構化日誌(JSON 格式)
集中式日誌聚合
工具:CloudWatch、Datadog、ELK 技術棧
指標和儀錶板:
系統指標(CPU、記憶體、磁碟)
應用指標(每秒請求數、查詢時間)
業務指標(註冊量、收入等)
工具:Grafana、Datadog、CloudWatch
需要監測的內容:
我監控每項服務:
錯誤率(應接近0%)
反應時間(第 50、95、99 百分位數)
請求速率(用於偵測流量高峰)
資料庫連線池使用情況
記憶體使用情況(用於檢測記憶體洩漏)
設定關鍵問題警報。但要注意——警報太多,你會全部忽略(警報疲勞是真實存在的)。
基礎設施即程式碼:
不要在雲端控制台裡到處點擊建立資源。用程式碼定義基礎設施:
Terraform:與雲端平台無關、聲明式,非常適合多雲環境
AWS CDK:使用 TypeScript/Python/Java 定義 AWS 資源
Pulumi:使用真正程式語言的現代 Terraform 替代方案
Terraform 範例:
resource "aws_instance" "app" {
ami = "ami-12345"
instance_type = "t3.medium"
tags = {
Name = "app-server"
}
}
這樣一來,您的基礎設施就具有可複現性、版本控制性和可審查性。
規模化考量:
一開始你可能不需要考慮擴展性問題。但當你需要考慮時:
垂直縮放(向上縮放):
更大的伺服器。簡單但有限制。
水平縮放(向外縮放):
更多伺服器。需要無狀態應用程式和負載平衡。
資料庫擴充:
讀取密集型負載的讀取副本
連接池
快取(Redis)
分片(困難,盡量避免)
快取策略:
靜態資源的 CDN
用於應用程式快取的 Redis
資料庫查詢快取
HTTP快取標頭
大多數應用程式如果優化得當,即使在配置一般的硬體上也能處理每秒數千個請求。不要過早地針對你無法達到的規模進行最佳化。
零停機部署:
如何在不關閉網站的情況下進行部署:
藍綠部署:
執行兩個完全相同的環境(藍色和綠色)
部署到非活動環境
切換流量
如果出現問題,請切換回來
滾動部署:
一次部署到一台伺服器
每個伺服器在更新前都會清除連線。
金絲雀部署:
首先在小部分流量上部署
監控問題
逐步增加百分比
大多數平台(Vercel、AWS ECS、Kubernetes)都會自動處理這種情況。
備份和災難復原:
資料最終會遺失。請做好準備:
自動資料庫備份(每日或更頻繁)
測試從備份還原(未經測試的備份毫無用處)
如果可能,進行時間點恢復
異地備份存儲
文件恢復程式
我職業生涯中總共三次需要從備份恢復資料。每次我都慶幸自己沒有使用那些枯燥乏味的自動化備份流程。
SSL/TLS憑證:
務必在所有地方使用HTTPS。到了2026年,沒有任何理由不這麼做。
Let's Encrypt 提供免費的 SSL 憑證
大多數平台(Vercel、Netlify、Cloudflare)都會自動處理這種情況。
在憑證過期前續期(自動執行此操作)
HTTP 協定不安全,會導致您的網站被瀏覽器標記。
不要把事情複雜化:
最常見的錯誤:從一開始就過度設計部署。
你不需要:
Kubernetes(除非你有特殊原因)
服務網格
多區域部署
複雜災難復原
你需要:
自動化部署
基本監控
資料庫備份
SSL憑證
先從簡單的入手。遇到需要複雜化的問題時再逐步增加難度。
讓我們來談談區分專業人士和業餘人士的那些不起眼的工作:測試、除錯和維護程式碼品質。
測試金字塔:
這個模型仍然有效:
單元測試(金字塔底部):
快速、獨立地測試單一功能/元件
你的大部分測試應該都在這裡。
工具:Vitest、Jest、pytest
整合測試(中間):
測試多個元件協同工作的情況
資料庫、API 等。
速度較慢,但能捕捉到更多實際問題。
端對端測試(上圖):
測試整個使用者流程
最慢、最脆弱,但最接近現實
工具:劇作家,柏樹
比例大致應為:單元測試 70%,整合測試 20%,端對端測試 10%。切勿顛倒比例-端到端測試的編寫和維護成本都很高。
測試內容:
並非所有事情都需要測試。重點關注:
關鍵業務邏輯:
// This needs tests
function calculateOrderTotal(items, discounts, taxRate) {
// Complex calculation
}
您修復的極端情況和錯誤:
// Regression test for bug #1234
it('handles empty cart correctly', () => {
expect(calculateOrderTotal([], [], 0.08)).toBe(0);
});
複雜狀態管理:
// Test state transitions
it('moves from pending to completed on success', () => {
// Test logic
});
哪些內容不該測試:
不要測試:
第三方函式庫程式碼(相信他們已經測試過了)
簡單的 getter/setter 方法,不含任何邏輯
樣式和佈局(必要時使用視覺回歸工具)
實作細節(測試行為,而非內部細節)
糟糕的考試:
// Testing React implementation details
expect(component.state.isOpen).toBe(true);
一個好的測試:
// Testing behavior
expect(screen.getByText('Modal Content')).toBeInTheDocument();
測試驅動開發(TDD):
理論是:先寫測試,再實現。
現實情況是:大多數開發者並不完全採用測試驅動開發(TDD),這也沒關係。但是,在開發功能的同時(或緊接著)編寫測試是非常有價值的。
我採用混合法:
對於複雜演算法:先寫測試。
對於 CRUD 操作:在操作完成後撰寫測試。
UI 開發:為關鍵流程編寫整合測試
不要固執己見。 TDD 有用的時候就用,沒用的時候就不用。
模擬和測試替身:
有時你需要偽造外部依賴項:
// Mocking a database call
jest.mock('./database');
it('fetches user data', async () => {
database.getUser.mockResolvedValue({ id: 1, name: 'Alice' });
const result = await getUserProfile(1);
expect(result.name).toBe('Alice');
});
但要注意——過度模擬會導致即使真實程式碼有問題,測試也能通過。應該模擬外部服務(API、資料庫),而不是自己的程式碼。
除錯策略:
除錯是一項需要經驗累積才能提升的技能。以下是我的除錯流程:
1. 重現問題:
如果無法重現問題,就無法修復。請提供詳細的步驟、環境和資料狀態。
2. 找出問題所在:
在程式碼中進行二分查找。逐段註解掉錯誤程式碼,直到錯誤消失。這樣你就知道錯誤在哪裡了。
3. 使用合適的工具:
瀏覽器開發者工具:
用於記錄日誌和執行程式碼的控制台
API 問題的網路選項卡
效能選項卡,用於顯示慢頁面
React DevTools 用於元件檢查
後端除錯:
控制台日誌(但使用結構化日誌)
偵錯器(VS Code 偵錯器、Chrome DevTools for Node.js)
資料庫查詢日誌
應用效能監控
4. 提出假設並進行檢定:
不要隨意改動。先提出問題所在,進行假設,然後再驗證並改進。
5. 找出根本原因,而非僅僅緩解症狀:
如果你加入了空值檢查,請先問為什麼結果是空的。如果你加入了 try-catch 語句,請先問為什麼它會拋出例外。修復實際問題。
常見的除錯錯誤:
隨機程式碼變更: “讓我試試這個…哦,這個不行…讓我試試這個…”
不閱讀錯誤訊息:錯誤訊息很有用!請仔細閱讀。
生產環境中的除錯:盡可能使用預發布環境。
不使用版本控制:只做小的、可逆的更改
不記錄解決方案:未來的你會感謝現在的你
程式碼審查實踐:
程式碼審查是團隊進步的方式。好的程式碼審查:
致審稿者:
及時審核(不要阻礙隊友)
要具體且具建設性。
表揚好的解決方案
多問問題,不要強求改變。
區分「必須解決的問題」和「錦上添花的問題」。
如果程式碼很複雜,請進行測試。
致作者:
盡量保持 PR 的簡潔性(如果可能,最好少於 400 行)。
請寫出清晰的描述。
加入測試
請求審核前先進行自我審核
以專業的態度回應回饋。
別往心裡去。
程式碼檢查和格式設定:
自動進行風格討論:
用於 JavaScript/TypeScript 程式碼檢查的ESLint
更美觀的程式碼格式化
Husky用於 git 鉤子
lint-staged用於對暫存檔案執行程式碼檢查工具
一次配置,終身無憂。從此告別分號、製表符和空格之爭。
package.json 腳本範例:
{
"scripts": {
"lint": "eslint .",
"format": "prettier --write .",
"type-check": "tsc --noEmit"
}
}
在持續整合 (CI) 中執行這些測試。如果測試不通過,則建置失敗。一個有爭議的觀點:我會在提交時自動格式化程式碼。程式碼審查應該專注於邏輯,而不是風格。
技術債:
每個程式碼庫都會累積技術債。問題在於如何管理這些債務。
良性債務:為了更快交付而採取捷徑,並計劃稍後進行補救。
壞帳:粗製濫造且無意改進的程式碼。
追蹤技術債:
程式碼中的待辦事項(但連結到工單)
專門的技術債積壓
抽出時間償還債務(例如,佔衝刺週期的 20%)
不要讓完美主義成為優秀的絆腳石。先發布可執行的程式碼,然後不斷迭代改進。
重要的程式碼品質指標:
別再關注程式碼覆蓋率百分比了。重點關注:
測試能發現 bug 嗎?如果測試通過但生產環境出現問題,表示測試有問題。
新開發者能以多快的速度做出貢獻?好的程式碼應該易於理解。
漏洞多久會再出現一次?同樣的漏洞反覆出現意味著系統性問題。
你對部署有多大信心?如果每次部署都讓你感到忐忑不安,那肯定有問題。
程式碼品質關乎永續性,而非指標。
作為一名全端開發人員,你不需要設計谷歌規模的系統。但你需要對架構概念有足夠的了解,以便做出合理的決策。
單體架構 vs. 微服務架構:
這場爭論由來已久。以下是我基於經驗的看法:
巨石:
單一程式碼庫,單一部署
易於開發、測試和部署
效能良好(無網路開銷)
小型團隊更容易維護
微服務:
多種服務,獨立部署
複雜的編排與測試
網路開銷和延遲
更適合大型團隊和擴展
事實是:大多數認為自己需要微服務的公司其實並不需要。微服務解決的是組織問題(大型團隊各自獨立工作),而不是技術問題。
我曾在一家新創公司工作,他們從一開始就採用了微服務架構。結果慘不忍睹。五個人要維護八個服務,部署複雜,除錯簡直是惡夢。最終我們整合為單體架構,生產力提升了三倍。
我也曾在一家長期使用單體架構的公司工作過。公司有 50 名工程師,部署衝突不斷,測試耗時 30 分鐘,任何改變都讓人提心吊膽。
先從單體架構開始。只有在有明確理由的情況下才提取服務:
團隊規模過大導致單體應用難以管理
需要對特定元件進行獨立擴展
不同的服務有不同的技術要求。
組織邊界清晰
不要因為微服務聽起來很現代就採用它。大多數應用程式並不需要它。
API設計模式:
REST(最常用):
GET /users # List users
GET /users/:id # Get specific user
POST /users # Create user
PUT /users/:id # Update user (full)
PATCH /users/:id # Update user (partial)
DELETE /users/:id # Delete user
基於資源的 URL、標準 HTTP 方法、清晰的語意。
GraphQL(當您需要靈活性時):
query {
user(id: "123") {
name
email
posts(limit: 5) {
title
createdAt
}
}
}
客戶請求的資料正是它所需要的。
RPC 風格(用於內部服務):
POST /api/sendEmail
POST /api/processPayment
POST /api/generateReport
以行動為導向,不太符合 REST 規範,但對於不映射到資源的操作來說,有時更清晰。
選擇適合您使用場景的樣式。保持 API 的一致性。
資料庫架構模式:
單一資料庫:
簡單易用,ACID 事務運作正常,沒有資料同步問題。從這裡開始。
讀取副本:
主資料庫用於寫入操作,副本用於讀取操作。可擴展讀取密集型工作負載。
分片:
將資料分散到多個資料庫。雖然複雜,但可以實現大規模擴展。盡量避免這樣做——操作起來非常棘手。
CQRS(命令查詢職責分離):
讀寫操作採用不同的模型。這對於複雜領域很有用,但也會增加複雜性。
再次強調:從簡單的開始,必要時再增加複雜性。
快取策略:
快取旁路(延遲載入):
async function getUser(id) {
// Check cache
let user = await cache.get(`user:${id}`);
if (user) return user;
// Cache miss, fetch from DB
user = await db.getUser(id);
await cache.set(`user:${id}`, user, { ttl: 3600 });
return user;
}
通寫式:
每次更新資料庫時都要更新快取。雖然一致性更高,但過程更複雜。
快取失效策略:
生存時間 (TTL)
基於事件的(更新時清除快取)
LRU(最近最少使用)
記住:“計算機科學中只有兩件難事:快取失效和命名事物。”
非同步處理:
並非所有事情都應該阻止用戶:
同步(用戶等待):
用戶請求、處理、回應
簡單但速度可能較慢
適用於:CRUD 操作、即時需求
非同步(用戶無需等待):
使用者請求、作業排隊、立即回應
複雜但更適合慢速操作的使用者體驗
適用於:電子郵件、報告、映像處理、外部API
以作業佇列為例:
// API endpoint
app.post('/send-report', async (req, res) => {
await reportQueue.add('generate', { userId: req.user.id });
res.json({ message: 'Report queued' });
});
// Worker process
reportQueue.process('generate', async (job) => {
const report = await generateReport(job.data.userId);
await emailReport(report);
});
使用者可立即獲得回饋,繁重的工作在後台進行。
事件驅動架構:
元件之間不進行直接呼叫,而是透過事件進行通信:
// Traditional approach
async function createOrder(orderData) {
const orde