自動前綴 URL — 節省數分鐘的細節小技巧
cutty.dev 會在你貼上不含 https:// 的網址時自動識別並補上。這聽起來微不足道,但在實際操作中,這就是「兩秒鐘搞定」與「點擊『再試一次』」之間的差別。
你在 allegro.pl 的表單中輸入內容。點擊。然後呢?
在大多數的短網址生成器中,此時你會收到一條錯誤訊息。大約像是「這不是有效的 URL」。因為前面缺少了 https://。所以你必須退回一步,加上協定,再次點擊,現在才終於得到了你的短網址。
cutty.dev 不會這樣做。它只是直接加上 https:// 然後繼續執行,就像什麼都沒發生過一樣。
我知道這聽起來是什麼樣子。就像一個甚至不值得用一個段落來描述的功能,更不用說整篇文章了。然而我仍然坐下來寫下這些,因為這個小細節對我來說,正是我對於如何構建 auto-prefix URL 工具以及所有其他那些隱形便利功能的思考縮影。
兩秒對二十秒
讓我們來算一下。真的,用數字說話,否則那只是空談。
第一條路徑:貼上,得到連結,關閉視窗。兩秒鐘。可能三秒。
第二條路徑:貼上、出錯、閱讀訊息(花一兩秒鐘理解發生了什麼)、補上協定、再次點擊,直到這時才點擊連結。十五、二十秒。加上那一小瞬間的挫折感,那種心裡默默說著「喔對了,協定」的感覺,單次看起來沒什麼成本,但累積起來卻很驚人。
現在,請將這個數字乘以你每個月貼上地址的次數。對我來說是幾十次。對於專業管理連結的人來說——則是幾百次。突然間,這個「微不足道」的小細節,每月累積起來就是好幾分鐘。這可是按人頭計算的。
這正是大多數人會忽略的算術,因為每一個單一案例看起來都太小,不值得去在意。
底層到底是什麼樣子
機制非常簡單,我完全不隱瞞這一點。你將文字貼入欄位中。在任何內容傳送到伺服器之前,一段 JavaScript 會檢查你輸入的內容是否以某種協定開頭 — http://、https://、ftp://、mailto:,任何形式皆可。如果不是以這些開頭,系統會假設你的意思是普通網域,並在前面加上 https://。
在實踐中:
allegro.pl變更為https://allegro.plgithub.com/twoj-profil/projekt變更為https://github.com/twoj-profil/projektwww.gazeta.pl變更為https://www.gazeta.pl
如果協議已經存在於那裡,即使很奇怪,系統也不會覆蓋它。它會保留並繼續檢查該如何處理。http://example.com 通過(允許)。ftp://example.com 被丟棄,因為我們只接受 http 和 https。而 javascript:alert(1) 會立即被剔除,因為這不是一個地址,而是一種注入惡意內容的嘗試(經典的 XSS,謝謝,不必了)。
為什麼我有,而市場上一半的人卻沒有
這裡變得有趣起來了,因為答案有點好笑。
在瀏覽器中驗證網址的標準方法是使用建構函式 new URL(string)。而這個建構函式非常嚴格。毫不妥協。如果沒有通訊協定 —— 它就會拋出錯誤。new URL("allegro.pl") 只會回傳一個 TypeError,就這樣。
而且你知道嗎?這是正確的行為。對於絕大多數的應用程式來說,這正是你所需要的。但在縮短網址的表單中,當人們從瀏覽器網址列或他人的訊息中複製地址時,這種嚴謹性就會從優點變成障礙。突然之間,一個本該為你節省時間的工具,卻要求你去修正那些它明明完全可以理解的東西。
繞過這個方法只需要幾行程式碼:
function sanitizeUrl(input) {
const trimmed = input.trim();
const hasProtocol = /^[a-z][a-z0-9+.-]*:/i.test(trimmed);
const normalized = hasProtocol ? trimmed : "https://" + trimmed;
// dalej leci normalna walidacja przez new URL(normalized)
}
五行程式碼。對於每一位需要貼上地址的人來說,每天可以減少十幾秒的摩擦力。說實話,我不知道為什麼這還沒有成為普遍標準。我懷疑是因為「URL 建構器就是這樣運作的」,而且沒人想去動它。這是慣性使然,而非惡意。
關於「標準」意義的一點小插曲
因為這個關於 new URL() 的故事是一個更廣泛現象的絕佳範例。軟體開發中許多被視為「理所當然」的做法,實際上往往只是「某個沒人質疑過的函式庫之預設設定所導致的結果」。建構函式的嚴格模式(Strict mode)並非 cutty 設計師或競爭對手的決定 —— 而是 URL 規範制定者在完全不同的背景下、為了完全不同的用途所做出的決定。
然後整個市場都繼承了這個預設選擇,並稱之為「標準」。我感覺最棒的產品正是誕生於那些有人停下腳步並自問:「等等,這種行為究竟是為了服務我的用戶,還是僅僅為了我的函式庫?」的地方。而答案通常是:為了函式庫。因此,值得用五行程式碼轉向以人為本的視角。
這些細節比看起來的還要多
Auto-prefix 只是眾多你無法在任何功能列表中找到的元素之一。因為如果把它們都寫進去,每一個看起來都會顯得微不足道:
- 在驗證前修剪空格,以防止貼上的網址末尾出現隨機空格導致出錯
- 保留錨點,即
https://example.com/page#section中的#section在縮短後不會消失 - 查詢參數 (
?utm_source=test) 會完整通過,過程中不會被截斷 - 帶有波蘭字符的網域,例如
źdźbło.pl,會自動轉換為 punycode - 自定義結尾中的波蘭字母會轉換為 ASCII (
różowy-link變為rozowy-link) - 危險協定 —
javascript:,data:,file:— 會被攔截並顯示特定的、易懂的訊息
(目前仍計劃在目標伺服器支援加密時,自動將 http:// 提升至 https://。這部分目前在正式環境中尚未生效,所以我不會假裝它已經運作。)
每一處細節都能為某人節省五秒、十秒、三十秒以及一次嘆息。單獨來看,它們微不足道;但加在一起,這就是「還可以」與「使用起來很愉快」之間的差別。
我還想額外賺取的收入
未來的願望清單,因為思考這些事情純粹讓我感到快樂:
- 智慧貼上 — 自動偵測句子中的網址,並從文字中提取出 URL 本身
- 批量貼上 — 輸入每行一個網址的列表,立即為每個網址生成獨立的短連結
- 建議結尾 — 根據目標頁面的標題,提供三個品牌化的 slug 供選擇
- 貼上後立即預覽 Open Graph,甚至在您點擊「縮短」之前
每一個都又是「看起來沒什麼用、只有五行程式碼的函式」。而它們全部加在一起呢?這正是那種「還算可以的工具」與「你會毫不猶豫地每天使用」的工具之間的界線。如果你想現在看看它是如何運作的,請在 cutty.dev 中貼上任何不含協定的內容 — allegro.pl, github.com, news.ycombinator.com — 並發現它完全不會刁難你。
最後,一點個人感言
長期以來,我一直認為產品是靠著強大的功能取勝。那種可以在簡報中展示、能讓大家津津樂道的亮點功能。的確,有時候確實如此。
但我開發的產品(cutty)時間越長,就越強烈地感覺到用戶的忠誠度誕生於其他地方 —— 在那成百上千個無人會刻意察覺的微秒之間。你不會記得工具自動為你加上了 https://。你只記得一種整體的印象,即「用起來感覺還不錯」、「不會讓人感到煩躁」。這種印象並非憑空而來。它是由數十個五行程式碼的小決策所構成,單獨看來,沒有人會認為其中任何一個值得花費時間去開發。
或許這正是工匠精神的所在。不在於那一個偉大的舉動,而是在於那種堅持——一次又一次地在填寫表單時站在使用者這一邊 —— 即使只是為了那微不足道的兩秒鐘。那你呢?最近有沒有什麼工具的小細節讓你感到惱火,小到甚至覺得不好意思說出口?因為通常最好的改進機會,就藏在這些地方。