網(wǎng)站實戰(zhàn):從拖拽上傳到自動構(gòu)建)
前陣子受夠了“寫個HTML想發(fā)給別人看結(jié)果發(fā)了zip包對方根本不知道怎么打開”的尷尬我把一個叫spade2的純靜態(tài)項目丟到了Netlify上整個過程從拖拽文件夾到拿到公網(wǎng) HTTPS 鏈接前后不到十分鐘。這篇文章就把這次的部署過程、踩過的坑、以及上線之后才察覺的幾個隱藏細(xì)節(jié)全部記錄下來。如果你手里也有一堆寫好的 HTML/CSS/JS 頁面不想買服務(wù)器、不想配 Nginx、更不想學(xué) Docker那么 Netlify 這套部署方案可能是你最快把東西“變成網(wǎng)站”的路徑。文章會從部署前的目錄準(zhǔn)備開始講再到兩種上傳方式的選擇、Netlify 后臺那些容易被忽略的配置項、最后是上線后我實測遇到的重定向和緩存問題盡量讓你看完之后能一次跑通少走彎路。1. 為什么是 NetlifyHTML 靜態(tài)站部署的定位與優(yōu)勢1.1 靜態(tài)站部署到底在解決什么問題很多剛接觸前端的人會以為“部署”就是把文件傳到某個服務(wù)器上其實這里面藏著幾個容易被忽略的環(huán)節(jié)。一個 HTML 文件想要被別人通過瀏覽器訪問至少需要解決三件事文件得放在一臺 7x24 小時在線的機器上這臺機器得能通過公網(wǎng) IP 或域名被找到訪問的時候還得走 HTTPS 協(xié)議不然瀏覽器會直接攔截。傳統(tǒng)的做法是買一臺云服務(wù)器裝 Nginx配置站點目錄再折騰 SSL 證書。這一套流程對只寫了幾個靜態(tài)頁面的開發(fā)者來說成本和復(fù)雜度都高得不成比例。而 Netlify 這類靜態(tài)托管平臺做的事情本質(zhì)上就是把“服務(wù)器 Web 服務(wù)軟件 HTTPS 證書 CDN 加速”全部打包成一條流水線你只需要把本地文件夾交給它剩下的它自己搞定。1.2 和傳統(tǒng)部署方式相比Netlify 的核心體驗差異拿 spade2 這個項目來說它就是我本地寫的一個純前端項目沒有任何后端接口所有數(shù)據(jù)都是寫死在 JS 里的。這種項目如果用 Nginx 部署我得先去買域名、解析 DNS、配置 Nginx 站點、申請證書、續(xù)期證書中間任何一步出問題都要折騰半天。Netlify 的處理方式完全不同。它支持兩種接入方式一種是直接在網(wǎng)頁上把項目文件夾拖進(jìn)上傳區(qū)叫 Netlify Drop另一種是把項目關(guān)聯(lián)到 Git 倉庫每次 push 代碼它自動觸發(fā)部署。兩種方式我都試過個人感受是對比維度Netlify Drop拖拽上傳關(guān)聯(lián) Git 倉庫自動部署上手門檻極低適合一次性發(fā)布需要基礎(chǔ)的 Git 操作更新流程每次都要手動重新拖拽push 代碼后自動觸發(fā)回滾能力弱只能重新上傳可以一鍵回滾到任意歷史版本適用場景臨時演示、快速分享正式項目、需要持續(xù)迭代spade2 我最終選擇了關(guān)聯(lián) Git 倉庫的方式因為后續(xù)還要持續(xù)改動自動部署省掉了每次手動上傳的重復(fù)勞動。1.3 標(biāo)題里的“Spade2”到底是什么項目形態(tài)這里多說一句 spade2 這個項目本身。它本質(zhì)上是一個無需構(gòu)建工具的靜態(tài)原型目錄里就是 index.html、styles.css、app.js 這幾個文件外加一個 assets 文件夾放圖片和字體。之所以選它做部署實驗是因為它的結(jié)構(gòu)足夠簡單——沒有框架、沒有打包步驟、沒有環(huán)境變量正好可以把 Netlify 部署的底層邏輯看得清清楚楚。如果你是第一次接觸部署我強烈建議先找一個這樣的小項目練手而不是一上來就部署一個 React 工程。因為當(dāng)部署失敗的時候簡單項目能讓你把問題定位在“部署流程”而不是“構(gòu)建過程”排查起來清晰得多。2. 部署前的目錄準(zhǔn)備少走彎路的項目文件規(guī)范2.1 本地項目的目錄結(jié)構(gòu)應(yīng)該長什么樣在拖拽上傳之前有一件事比部署本身更影響成敗項目目錄是否干凈。我見過很多本地項目跑得好好的一旦部署上線就樣式全丟、圖片全裂根因就是目錄結(jié)構(gòu)不規(guī)范——文件沒有放到根目錄、路徑寫的是絕對路徑指向了本地磁盤、甚至混進(jìn)來一堆 node_modules 垃圾文件。spade2 在提交部署前我特意把目錄整理成下面這個樣子spade2/ ├── index.html ├── styles/ │ └── main.css ├── scripts/ │ └── app.js └── assets/ ├── images/ └── fonts/部署時Netlify 的站點根目錄Publish Directory指的就是這個spade2文件夾本身。所有 HTML 文件必須直接放在這個根目錄下或者在子目錄里但通過相對路徑正確引用。尤其注意Netlify 的默認(rèn)首頁文件名必須是index.html如果你把首頁命名為home.html訪問域名時不會自動打開你的頁面會直接返回 404。2.2 路徑寫法相對路徑還是絕對路徑這可能是靜態(tài)站部署中最容易翻車的一個點。本地打開 HTML 文件時瀏覽器用的是file://協(xié)議這時候?qū)懡^對路徑/assets/images/logo.png也能打開因為文件就在你的磁盤上。但部署到 Netlify 之后整個站點的根目錄變成了域名根路徑如果你的資源路徑是從根斜杠開始寫的只要部署目錄層級不一致就會全部指向錯誤的位置。我的建議是在本地寫代碼時就用相對路徑。比如 HTML 在根目錄圖片在assets/images/下引用就寫assets/images/logo.png不要加開頭的斜杠。如果你有子頁面在pages/about.html里想引用根目錄的圖片就寫../assets/images/logo.png。提示路徑問題在本地不一定能暴露因為本地文件系統(tǒng)對路徑的容錯度比服務(wù)器高。部署前最好在瀏覽器開發(fā)者工具的 Console 面板里看一下有沒有資源加載失敗的報錯Network 面板里標(biāo)紅的就是需要修的。2.3 忽略文件與臨時文件的清理另一個隱蔽的問題來自那些“本地必需、線上沒用”的文件。比如你用 VSCode 打開項目后生成的.vscode/配置目錄、macOS 的.DS_Store文件、某些編輯器的自動備份文件。這些文件雖然不影響部署成功率但會讓你的站點倉庫變得很臃腫而且部分文件內(nèi)容可能包含本地路徑信息也就是所謂的“信息泄露隱患”。如果你是關(guān)聯(lián) Git 部署務(wù)必在項目根目錄創(chuàng)建.gitignore文件把下述內(nèi)容寫進(jìn)去.DS_Store node_modules/ dist/ .vscode/ *.log如果你是拖拽上傳那就手動確保拖進(jìn)去的文件夾里只有需要上線的文件。簡單粗暴但很有效。2.4 本地預(yù)覽的正確姿勢在部署之前最好用本地靜態(tài)服務(wù)器預(yù)覽一下項目而不是直接雙擊 HTML 文件。因為直接用file://協(xié)議打開時瀏覽器的安全策略會限制某些能力比如 fetch 請求本地 JSON 文件、某些瀏覽器下的模塊加載都會報跨域錯誤。這些錯誤在你部署到 Netlify 之后因為走的是 HTTP 協(xié)議反而不會出現(xiàn)但它們會干擾你對項目現(xiàn)狀的判斷。如果你是 VSCode 用戶裝一個 Live Server 插件就能解決?;蛘哂?Python 一行命令python3 -m http.server 8080然后在瀏覽器訪問localhost:8080看到的頁面狀態(tài)和部署后基本一致。這一步做踏實了后面部署成功率會高非常多。3. 兩條部署路徑實測Netlify Drop 與 Git 倉庫連接3.1 Netlify Drop 拖拽部署最快三分鐘上線Netlify Drop 是整個平臺里最“反直覺”的功能——不需要注冊賬號甚至可以直接把文件夾拖進(jìn)網(wǎng)頁Netlify 會臨時給你一個鏈接你可以用游客身份訪問也可以順手注冊賬號把這個站點接管到自己的名下。實際操作步驟非常簡單打開 Netlify 官網(wǎng)找到 Drop 區(qū)域。把整個spade2文件夾直接拖進(jìn)去。等待幾秒Netlify 自動完成上傳、構(gòu)建、部署然后給你生成一個隨機子域名格式一般是隨機名稱.netlify.app。點擊鏈接查看線上效果。我第一次用 Drop 部署的時候整個過程快到?jīng)]反應(yīng)過來。唯一的不足是這種方式部署出來的站點和你本地文件是一份靜態(tài)快照后續(xù)你改了本地代碼線上不會自動更新要重新拖一次才行。3.2 關(guān)聯(lián) Git 倉庫從 push 到線上自動更新對 spade2 這個需要持續(xù)改動的小項目我更推薦走 Git 接入這條路。流程是在代碼托管平臺創(chuàng)建倉庫把本地項目 push 上去。進(jìn)入 Netlify 后臺選擇 “Add new site”然后選擇 “Import an existing project”。授權(quán) Netlify 訪問你的代碼托管平臺然后選中 spade2 對應(yīng)的倉庫。配置構(gòu)建選項。由于 spade2 是純靜態(tài)項目不需要執(zhí)行任何構(gòu)建命令構(gòu)建命令留空即可。發(fā)布目錄Publish Directory填.或直接保持默認(rèn)表示倉庫根目錄就是站點根目錄。點擊 “Deploy site”等待系統(tǒng)自動完成部署。部署完成后你每次把代碼 push 到倉庫的指定分支默認(rèn)是 main 分支Netlify 都會自動拉取代碼、執(zhí)行構(gòu)建如果配置了的話、發(fā)布上線。整個鏈路是自動化的你唯一要做的就是寫好代碼并 push。3.3 站點管理與域名的那些事無論走哪條路徑部署成功之后進(jìn)到站點后臺你會看到三個核心信息站點名稱Site name、域名列表Domain management以及部署記錄Deploy log。站點名稱可以直接改改完訪問域名會跟著變。比如 spade2 我改成了一個可讀性比較高的名字域名就變成你喜歡的名字.netlify.app。如果你自己有域名可以在 Domain management 里添加自定義域名。Netlify 會提示你到域名注冊商那邊加一條 DNS 記錄通常是一個 CNAME 記錄或 A 記錄指向Netlify 提供的目標(biāo)地址。這個步驟完成后域名解析有幾分鐘到幾小時的生效延遲不是立刻就能訪問別急著反復(fù)刷新。提示自定義域名的 DNS 設(shè)置里我碰到過一個問題——原域名解析記錄的 TTL 太長了導(dǎo)致改了之后怎么都不生效。如果你遇到類似情況把 TTL 調(diào)小到 300 秒再等會快很多。4. 上線后的隱藏配置Netlify 后臺不容忽視的選項4.1 站點的保護(hù)與訪問策略有些時候你不想讓一個剛部署的站點被全網(wǎng)隨便訪問Netlify 支持在站點設(shè)置里開啟訪問保護(hù)。具體位置在 Site settings 下的 Access control你可以設(shè)置密碼保護(hù)讓訪問者必須輸入密碼才能看到網(wǎng)頁內(nèi)容。這個功能對項目預(yù)演、客戶驗收臨時環(huán)境特別有用。不過我實踐下來有個細(xì)節(jié)要提醒如果開啟了密碼保護(hù)那么某些自動化工具比如網(wǎng)頁截圖服務(wù)、搜索引擎爬蟲可能無法正常訪問你的站點。如果你想先保護(hù)起來給一兩個人確認(rèn)之后再公開記得解除策略。4.2 重定向與 404 頁面不只是“找不到頁面”那么基礎(chǔ)一個 HTML 網(wǎng)站最容易忽視的就是錯誤頁。Netlify 默認(rèn)的 404 頁面是一個極簡的 “Not Found”雖然能說明問題但和站點風(fēng)格完全不搭。spade2 里我特意加了一個 404.html 頁面并在 Netlify 后臺把它設(shè)置成默認(rèn)的 404 頁面。這樣用戶訪問不存在的鏈接時看到的還是網(wǎng)站自己的設(shè)計語言觀感好很多。重定向同樣重要。常見的場景有兩種。第一種是把http請求全部重定向到https這個 Netlify 默認(rèn)就做了不用額外配置。第二種是路徑別名比如想讓用戶訪問/home時實際渲染index.html可以通過 Netlify 的_redirects文件來配置。這個文件放在發(fā)布目錄的根目錄下格式如下/home /index.html 200配置了之后訪問/home不會再遇到 404而是正常渲染首頁內(nèi)容。對純靜態(tài)站點來說這算是最輕量的“模擬路由”方案。4.3 部署日志與回滾出問題時最靠得住的功能Netlify 的部署日志幾乎是調(diào)試的第一現(xiàn)場。你在后臺進(jìn)到 Deploys 頁面能看到每一次部署的狀態(tài)成功是綠色的 Published失敗是紅色的 Failed。點進(jìn)任意一條記錄展開日志能看到系統(tǒng)執(zhí)行了哪些步驟。純靜態(tài)項目的話日志內(nèi)容比較短主要就是上傳文件、處理重定向規(guī)則、發(fā)布這幾步。真正讓我覺得這個功能值錢的地方在于“回滾”。有一次 spade2 改版時我不小心把一整塊頁面的樣式寫崩了本地沒有及時發(fā)現(xiàn)push 之后線上直接一團(tuán)亂。這時候我進(jìn)到 Deploys找到上一個成功的版本點擊 “Rollback to this deploy”系統(tǒng)會在幾秒內(nèi)把線上版本恢復(fù)到上一次正常狀態(tài)。4.4 構(gòu)建與發(fā)布目錄配置的踩坑記錄如果你部署的是純靜態(tài) HTML最穩(wěn)妥的配置方式是什么配置項推薦值說明Build command留空純靜態(tài)項目無需構(gòu)建Publish directory.或dist/取決于你的文件是否在子目錄部署分支默認(rèn)主分支即可可用生產(chǎn)分支區(qū)分使用環(huán)境我第一次部署時沒把發(fā)布目錄設(shè)置對填成了public/結(jié)果 Netlify 在那個目錄下找不到index.html直接報錯。后來仔細(xì)看了一下本地目錄結(jié)構(gòu)才意識到文件就在根目錄里發(fā)布目錄應(yīng)該填.。這個低級錯誤很典型本地項目結(jié)構(gòu)里如果多包了一層文件夾發(fā)布目錄就要填到那一層。5. 部署后的性能調(diào)優(yōu)緩存、預(yù)加載與資源優(yōu)化5.1 Netlify 自帶的 CDN 與緩存機制很多人用 Netlify 單純把它當(dāng)一個“靜態(tài)服務(wù)器”其實它的底層分發(fā)網(wǎng)絡(luò)比我預(yù)想的要復(fù)雜得多。你的站點文件在部署后會被同步到多個不同的網(wǎng)絡(luò)節(jié)點上用戶訪問時系統(tǒng)會根據(jù)用戶的物理位置解析到最近的節(jié)點從而大幅縮短資源加載時間。但 CDN 也帶來了一個緩存問題你更新了線上文件但部分用戶的瀏覽器可能還在使用舊的緩存內(nèi)容。Netlify 默認(rèn)會在響應(yīng)頭里帶上緩存有效期通常對assets/這類帶哈希的文件緩存得比較久對index.html這類入口文件緩存得短一些。5.2 手動調(diào)整緩存策略Correct Headers 的設(shè)置方法如果想精細(xì)控制緩存可以在 Netlify 后臺的 Headers 面板配置響應(yīng)頭。比如給index.html設(shè)置較短的緩存時間讓用戶每次訪問都能拿到最新內(nèi)容/index.html Cache-Control: public, max-age0, must-revalidate給靜態(tài)圖片、字體這類內(nèi)容設(shè)置較長的緩存時間/assets/* Cache-Control: public, max-age31536000, immutable這樣設(shè)置之后每次更新頁面內(nèi)容時入口文件能快速生效而圖片字體這類很少改動的資源又能充分利用瀏覽器緩存。實測下來spade2 在配置完緩存策略后重復(fù)訪問時的加載速度直觀上快了不少。5.3 HTML 靜態(tài)站的輕量性能優(yōu)化手段除了緩存還有幾個不費力的優(yōu)化手段可以順手做掉。比如給每個img標(biāo)簽加上width和height屬性能有效減少頁面布局抖動比如把 CSS 里引用的字體文件從遠(yuǎn)程字體庫改成自托管能減少一次 DNS 查詢和并發(fā)請求。spade2 里我用到了幾張小圖標(biāo)原來的做法是每個圖標(biāo)單獨一個img標(biāo)簽請求。后來我看了眼 Network 面板發(fā)現(xiàn)這些圖標(biāo)請求占掉了將近一半的請求數(shù)量。改成了圖標(biāo)合并成一張雪碧圖之后請求數(shù)量從十幾條降到了三條頁面加載快了一大截。唯一要注意的是坐標(biāo)定位很繁瑣值得權(quán)衡之后再決定要不要上手。5.4 利用 Netlify Forms 給靜態(tài)頁面加上數(shù)據(jù)收集功能純靜態(tài)站點的最大痛點是沒有后端表單提交一般只能靠第三方服務(wù)或者寫接口。Netlify 自帶一個 Forms 功能可以直接把靜態(tài)頁面的表單數(shù)據(jù)收集到后臺。使用方法很簡單在 HTML 表單里加一個>form namecontact methodPOST>