- Published on
一個人扛一整個網站時,我學會放掉什麼
- Authors
-
-
- Name
- Alex Yu
-
前一份工作我帶五個前端,主要的事是分派任務、review、mentor。
現在我是一整條產品線唯一的前端。一個流量主站、一套自己維護的活動微站框架,加上部署和線上事故——從寫產品功能到管伺服器,全是我一個人扛。
剛轉過來的時候我還想用帶團隊的標準要求自己——每個 PR 都要完美、每塊 code 都要最佳化。撐了一陣子發現不對。一個人的時間就這麼多,再用「五個人的產能標準」要求一個人,只會把自己榨乾還做不完。
於是真正要練的能力變成:在「自動化、降標準、不妥協」這三堆之間,快速把每件事分類。
該自動化的:重複的判斷
一個人最貴的是判斷力,最不該浪費在重複勞動上。任何「每次都一樣、不需要思考」的事,都該丟給機器。
最有感的一個是分支清理。我們的流程是一張票會長出好幾條分支——feat/ 開發、candidate/ 待驗、發版時再一條 release/。PR merge 進 main 之後,這些分支就沒用了。
GitHub 有內建的「merge 後自動刪 head branch」開關,但它只刪 PR 的那一條,同一張票的兄弟分支還留在遠端。一個人開發的時候沒有人會提醒你,幾個月下來遠端就是一長串沒人認得的分支。
所以自己寫一支,從分支名解析票號,把整組清掉:
on:
pull_request:
types: [closed]
branches: [main]
jobs:
delete-branch:
if: >
github.event.pull_request.merged == true &&
(startsWith(github.event.pull_request.head.ref, 'feat/') ||
startsWith(github.event.pull_request.head.ref, 'hotfix/') ||
startsWith(github.event.pull_request.head.ref, 'release/'))
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/github-script@v8
with:
script: |
const branch = context.payload.pull_request.head.ref
await deleteBranch(branch) // 先刪 PR 自己那條
// ← 重點:同一張票的兄弟分支也要一起清
const ticket = branch.match(/^(?:feat|hotfix)\/(ticket-\d+)/i)?.[1]
if (ticket) await deleteBranch(`candidate/${ticket}`)(release/ 的 PR 會一次收掉好幾張票,所以那條路徑改成從 PR 標題把票號全撈出來,逐一清掉。刪之前一律先確認分支存在,404 就跳過——它必須能重複執行而不出錯。)
這是一次性投入,之後每次 merge 都自動省一個動作。對一人團隊來說,這種 DX 投資的 ROI 最高——它讓我不用再把這件事記在腦子裡。
當別人的工具每週覆蓋你的 code
另一個例子更棘手,因為它不只是麻煩,是做錯了不會有人告訴你。
我手上有個策展活動頁,內容由策展組用視覺化網站工具產出,每週交一包 HTML 給我,當天要上線。流程很單純:把打包檔覆蓋進 repo、上線。
問題是那包 HTML 是他們的工具產的,不知道我在頁面裡加過東西。每覆蓋一次,我埋的 GA 追蹤腳本就被洗掉一次。還有幾個固定要補的:拿掉會拖慢 INP 的套件、幫 YouTube iframe 補上 enablejsapi=1、把絕對路徑改成相對路徑。
第一層自動化很直觀,把這些修補寫成腳本,覆蓋完跑一次:
# pre-deploy-patch.sh — 每次套用打包檔後執行
# 1. 移除會拖慢 INP 的 script
# 2. 注入追蹤腳本(</body> 前)
# 3. YouTube iframe 補 enablejsapi=1
# 4. 絕對路徑改相對路徑(同 origin 才能用 postMessage)
#
# 冪等設計:重複執行不會重複注入 ← 關鍵,不然手滑跑兩次就爆更麻煩的是,壞掉的時候沒有人會告訴你
但腳本注入成功,不代表追蹤真的有效。
那支追蹤腳本是靠 CSS selector 抓 DOM 的——#PartD-topic 是某個區塊、.nav-link 是導覽按鈕。而策展組在他們的工具裡改版面時,這些 id 和 class 會跟著變。
於是最糟的情況長這樣:打包檔套用成功、頁面看起來完全正常、上線也沒報錯,但某幾個區塊的 GA 事件從那天起再也沒進來過。 沒有錯誤訊息、沒有紅燈,等到有人問起數據才發現,中間已經漏了兩週。
所以第二層自動化是把「這些 selector 還在不在」變成可以檢查的東西。selector 全部抽成設定檔:
{
"index": {
"required": [
{ "id": "GA-07", "pattern": "id=\"PartD-topic\"", "description": "專家訪談區塊" },
{ "id": "GA-10", "pattern": "id=\"PartI-video\"", "description": "影音學堂區塊" },
{ "id": "JS-01", "pattern": "exhibition-tracking\\.js", "description": "追蹤腳本有載入" }
]
}
}再配一支驗證腳本,任何一條對不上就 exit 1,然後讓 CI 每個 PR 都跑。原本無聲失效的東西,變成上線前一定會擋下來的紅燈。
第三層:把整套流程交給 AI
腳本解決了執行,但每週那套流程還有一堆得記在腦子裡的東西:哪些檔案該 stage、哪個資料夾絕對不能 commit、diff 要怎麼對照策展組的文稿逐項確認。
這部分我寫成了 Claude Code 的 skill,把整套工作流固化下來:
---
name: exhibition-weekly-update
description:
策展頁的接手與維運流程:每週打包檔更新、pre-deploy-patch、
validate-tracking-selectors、埋點 selector 失效時的修補、常見地雷。
當使用者提到套用打包檔、tracking selector FAIL 時觸發。
---這裡有個合理的疑問:前面兩層都寫成腳本了,這層為什麼不繼續寫腳本就好?
因為剩下的事情,腳本做不了——它們都要先「讀懂當下的東西」才能決定怎麼做:
- 策展組每週附的更新文稿是白話文(「header 加兩張、學堂多兩支影片、名人區加一位」),我得逐項對照 diff 確認有沒有漏做。腳本沒辦法讀懂一段中文說明,再去跟 DOM 的改動配對。
- selector 驗證失敗時,腳本只能告訴我「GA-10 這條對不上」。但那個區塊現在改叫什麼、該把設定檔改成哪個新 id,得打開新的 HTML 看過才知道。
- 每週改動的檔案範圍都不一樣,該 stage 哪些也就不一樣。
所以分工其實很清楚:確定性的步驟留給腳本(快、可靠、CI 也跑得動),需要讀上下文才能下的判斷交給 AI。而 skill 的角色是把「什麼時候該叫哪支腳本、結果怎麼判讀、哪裡有地雷」這套流程寫下來——它不是取代那些腳本,是指揮它們。
現在的流程變成:我把打包檔丟給它,它照著跑修補、驗證、精準 stage,再對照文稿列出 diff 摘要,我只做最後確認。
重點不是 AI 幫我寫了多少 code,而是我把一次想清楚的流程和判準固化下來,之後每次都不用重想——包括三個月後已經忘光的自己。
判斷哪些該自動化的標準很簡單:這件事需要我的判斷力嗎? 不需要的推給腳本;需要判斷、但每次判準都一樣的,把判準寫下來交給 AI。
該降標準的:80 分就交的事
一個人不可能每件事都做到 100 分。重點是刻意決定哪些事 80 分就好,然後不覺得愧疚。
我的分法大致是這樣:
- 改動範圍小、又不在核心路徑上的 → 80 分,能動就好
- 內部工具、自己用的 script → 60 分,醜沒關係
- 流量大、出錯影響廣的核心頁 → 不在這堆裡,見下一節
以前帶團隊會覺得「降標準」是種失職。但一個人扛的時候,不分輕重地追求完美,本身才是失職——因為你把時間花在不重要的地方,重要的地方反而沒空顧。
「不完美但持續做」這句話,當管理者時是拿來鼓勵團隊的;當唯一前端時,是拿來說服自己放手的。
不能妥協的:核心路徑與不可逆的東西
降標準有界線。流量最大的核心頁、會白屏的地方、不可逆的破壞性操作——這些不在 80 分那堆裡。
判準是「出錯的代價」。一個內部 script 出錯,我自己重跑就好。核心文章頁出錯,是當天全站流量的事。代價不對稱,標準就不能對稱。
破壞性操作也一樣。我可以接受 AI 幫我寫大部分的 code,但真正會刪資料、改 production 設定的動作,一定要人來確認。AI 給建議、人做決策,這一點我很堅持。
漸進式重構,不做 big bang
一個人還有一個現實限制:沒有後援。
帶團隊的時候,可以排一個人花兩週做大重構,其他人扛日常。一個人沒有這種餘裕——你一旦進入 big bang rewrite,日常需求就全部停擺。
所以我偏好 POC 先行、小步重構。先做一個小範圍驗證可行,再一塊一塊換,每一步都保持系統可運作。
big bang:停兩週重寫 → 期間零產出 → 上線即大爆炸
漸進式:每個 sprint 換一塊 → 隨時可上線 → 風險分散當年帶團隊把測試覆蓋率從 0% 推到 56%,也不是某次衝刺一次到位,是每個 sprint 多寫一點累積的。一個人做事更要這樣——因為你輸不起一次「全停下來重做」的賭注。
從帶人到單兵,判斷的優先序變了
帶五個人的時候,我的槓桿是「設計讓團隊跑得更順的機制」——Git Flow、CI cache、測試文化。我自己寫不寫 code 沒那麼關鍵,把五個人的效率拉起來才是。
一個人的時候,槓桿變成「決定什麼不做」。產能就這麼多,多做一件 80 分的事,就少做一件該做到 100 分的事。
技術能力反而不是這個階段的瓶頸。瓶頸是取捨的判斷力——你能不能誠實地承認「這件事我不做」,然後把省下的時間放在真正重要的地方。
幾個帶走的想法
- 該自動化的判準:這件事需要我的判斷力嗎?不需要的推給腳本;需要判斷但判準固定的,寫下來交給 AI。
- 該降標準的判準:出錯的代價多大?代價小的就 80 分。
- 一個人最該練的不是「做更多」,是「誠實地決定不做什麼」。
一個人開發的時候,沒辦法事事都追求完美,因為時間就是有限。所以現在對我來說,這份工作比較像是在做資源分配——每天決定哪些事值得花時間,哪些事到此為止。
延伸閱讀
- AI 時代,務實派工程師靠什麼活下來?——同一條線的另一面:能力該往哪裡放
- 6,401 個 IP、3 分鐘、7,262 個錯誤:一隻普通的爬蟲怎麼打掛我的 search 頁——「不能妥協的那一堆」實際長什麼樣