跳到主要內容

發表文章

目前顯示的是有「Web Development」標籤的文章

JavaScript 優化使用者輸入事件效能技巧: debounce & throttle

debounce 跟 throttle 不是什麼新奇的技巧 但是對部分想理解這個概念的前端開發者來說,障礙可能是如何下搜尋關鍵字 畢竟以字面來說,去抖動跟節流沒很直接從字面上聯想到適用場景 但要如何在使用者持續輸入的過程中 還要盡量避免多餘的同樣函式呼叫在現代卻是越來越重要的開發優化目標

讓 Windows 環境的 localhost 啟用 HTTPS 連線

相信很多 Web 開發人員在 local 的開發環境用的設定跟產品一樣是 HTTPS 不過畢竟 production 用的 TLS  certificate 不是簽給 localhost 用的 所以若沒調整則在瀏覽器會看到 Your connection is not private 的訊息 Chrome 的網址列也會顯示連線不安全 這個當然不是什麼問題,點個忽略警告大家還是可以照常開發 不過開發人員也可以選擇在 local 產生一張簽給 localhost 的 self-signed certificate 調整過後可以從此不需要再去點忽視警告 然後開發時看到的瀏覽器網址列的提示也會是安全連線,視覺爽度加分 這篇說明怎麼在 Windows 環境生效,以下開始步驟

網頁連結的 target = _blank 的隱藏風險

這是偶然間看到的一篇文章 The Hidden Dangers You Have Never Noticed: target = "_blank" and "opener" 並進而找到討論這篇文章的 reddit 討論串 我一開始以為是英文閱讀,所以讓我沒有完全了解原文的感覺 不過看了 reddit 串也是很多人覺得作者的表達能力不好 XD 所以我覺得直接看 reddit 串中的其他人的討論跟摘要會更直接 簡單來說,可能導致的風險是讓使用者導入到偽造的釣魚網站 因為瀏覽器的跨網域保護政策 所以連結網頁中的 window.opener 只有受限的操作權力 目前的主流瀏覽器已經在這方面提供夠好的保護力 只不過在這有限的操作範圍中, opener 可以調用 location object 並操作 惡意的連結網頁藉此把原網頁跳轉到相似度極高的惡意釣魚網站 使用者關掉連結網頁後,很有可能沒注意到他回頭看的已經不是原本網頁而受害 所以如果開發者允許用戶用 target = _blank  的方式到外部連結 最好得加上防範措施免得夜長夢多 原文跟 reddit 串有不少考量的理由的說明,以下直接講建議方式 <a href="https://an.evil.site" target=" _blank " rel=" noopener noreferrer nofollow ">... 如果要用 JavaScript 開啟的話則是 var newTab = window.open(); newTab.opener = null; newTab.location = url;

Chrome Dev Tool 的好用功能 - overrides

Chrome Dev tool 隨著開發演進也增加了很多方便的功能 overrides 是最近發現好用的功能之一 官方說明 https://developers.google.com/web/updates/2018/01/devtools#overrides 有時候會一些網頁錯誤的原因可能是網路因素 如果這錯誤是網頁一載進來就會發生 而且又不好在 local 重現,那麼在過去還真是不好處理 過去的常見做法可能是我們撰寫用 setTimeout 模擬延遲的程式 只是缺點是: 1. 用猜測的參數撰寫的模擬並不能完全表示出實際狀況,所以不一定能解決實際問題 2. 撰寫模擬的 code 有可能會很多且複雜 Chrome 在 65 版後加入這個功能 讓我們可以在實際的線上環境中套用自己的修改測試問題 直接面對實際狀況比過去的方式好用多了 啟用步驟可以直接看Google文章的說明 在 Google dev tool 的 source 頁籤裡的子頁籤的 Page / FileSystem 那邊多了一個子頁籤 overrides 選擇並給予 Chrome 權限能存取並建立修改紀錄在指定的 local 檔案 記得把 Enable Local Overrides 打勾後就能正式啟用 source 裡能修改,完成後按 ctrl + s 儲存變更 之後即使頁面重新整理,Chrome也會使用編輯後的 code 替代原始內容 如此就能用來驗證錯誤的原因跟找出合適的處理方法了

HTML 新標籤 details & dialog

這兩種新元素都算是已經廣泛被需求的原件,然後現在有了HTML的原生支持 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog 目前這兩項都找的到pollyfill 可以在需要用時讓沒跟上新規格的瀏覽器也能用 例如那個號稱新瀏覽器但是進度落後非常多的Edge details 需要搭配 summary tag,可以做出 toggle 觸發區塊的顯示/隱藏 比起目前要達成同效果的實作會簡單些,也少寫了一些 code dialog大家很熟就不多講了 可以預期隨著 PWA 的發展趨勢,這兩項未來都會被廣泛運用吧 Web app 的效能瓶頸跟支援性的問題得到解決的日期可能不太遠了 Web 開發者也能跟著期待未來 Web 會引入更多這類在 Native app 上的需求到 Web 標準裡

避免 scroll bar 影響網頁元件的外觀

Scroll bar 是網頁上常見的設計之一 只是有時候不太能預期你的 element 的內容是否多到需要用 scroll bar 或者是 element 的內容會隨著操作而變動 這種不確定性會對網頁的排版造成影響,很可能 scroll bar 的產生會擠壓到原本的元素 上面的示範提供了兩個例子 先注意原本的外觀後繼續操作 移動滑鼠到 element 上就可以看到 scroll bar 的產生 第一個例子的當 scroll bar 出現後,原本的文字排版也跟著變化 第二個例子則是出現 scroll bar 前後的文字排版都相同 建議不要想著去計算 scroll bar 的寬度 首先是 scroll bar 的寬度依各家瀏覽器廠商的實作而不同 再來是用 JavaScript 計算會有效能上的損耗,以及可能有相容性的問題 第二個例子的處理方式是在外面的 element 及內部的 element 中間塞入了個 div 這個 div 的外觀依需求將寬或長指定的跟外層 element 相同 這樣就能保持內容的外觀,scroll bar 也只會影響這個中介 div 很多 web 的設計都能使用這個想法,插入中介 element 讓外層跟內部的顯示效果區隔

IE IFRAME 不儲存Cookie

參考文章: Cookie blocked/not saved in IFRAME in Internet Explorer 之前沒特別注意過這問題 前一陣子才發現開放給外部嵌入網頁使用的IFRAME元件在 IE 上居然不會有Session存在 以往使用 IFRAME 都是在自家產品內嵌入,使用上都沒碰過問題 這次客戶回報 IE 11的測試有這問題後才發現當網頁網域跟IFRAME網域不同時 IE 會要求提供IFRAME頁面提供 P3P 標籤,否則就不能存Cookie 也因為這個原因,連帶地使得 Session 也不能用了 P3P的相關議題在參考文章的那篇 stackoverflow 討論的滿詳細的 這是一個宣告自己不會蒐集使用者資料或諸如此類的隱私權宣告標籤 參考了許多文章得到的結論是,這是一個逐漸死亡的標準,Chrome跟Firefox都已經放棄了 他的問題包含 1. 不確定有實質法律效力 2. 很難有網站可以完全做到不蒐集使用者資料     再說就算網站說一套做一套,使用者也得有能力證明網站有蒐集資料 結論是碰到這個問題最簡單的作法是在response中加入P3P header 至於實質效力? 看到一個有點酸的評論 Problem solved, and IE is happy :) 連 IE 11也有是比較讓我意外,希望 M$ 新的Edge可以不要再做這種沒實質效益的行為了

用 Firebug 紀錄網頁 DOM 的所有事件

先說結論(?) 大致上有2種狀況你可能會需要查詢 DOM 被觸發的事件 1.瀏覽器行為變動使你的JavaScript運作不正確    例如部分行為不再被觸發,或者是事件的優先順序被調整 2.你撰寫的JavaScript中會自行觸發 DOM 事件,而且有問題需要除錯    例如自行觸發 onchange、onfocus等等 在這些情況下你可能很難判斷問題是由那些事件引發 特別是有部分事件是透過JavaScript引發而非一般輸入(鍵盤、滑鼠)引起的 最好的方式是紀錄該DOM元件中被觸發的所有事件,再依此判斷解決方式 我查過最好的處理方式應該還是透過Firefox的Firebug套件,省掉撰寫測試程式的工 上圖就是Firebug此功能的示意圖 你可以先透過Firebug的選取器選好這次要測試的DOM元件 選好後會看到被選取的原件會顯示為藍底反白 在該區塊按右鍵就會跳出圖片中的選單,選擇紀錄事件->你想紀錄的事件 之後再執行一次操作,就可以看到該元件有那些事件會在操作中被觸發

JavaScript 偵測輸入法(IME)狀態

相關參考文章: http://mdn.beonex.com/en/DOM/CompositionEvent.html 輸入法(Input Method Editor,以下全用IME代稱)的處理一直是我們漢字文化圈的麻煩之一 在前端滿常碰到客製化 key event 的需求 當客戶按了某個鍵或輸入某段文字後會執行我們自訂的程式 只是這樣的處理方式在輸入法啟用狀態滿常有例外 例如:選字時會用到上下移動鍵,刪除、或確定選字用到 Esc、Enter、Backspace 選字的時候我們會希望在這段時間的輸入不會影響原先的狀態 麻煩的點是這一段在瀏覽器的處理並沒有完整的規範 大概是其他國家沒什麼選字的需求,即使在HTML5規格接近定稿的時刻, IME 在W3C依然是草案狀態 該草案推動者是在日本Google工作的日本人,顯得願意投入的資源並不多 也因此目前瀏覽器的實作略有不同,在輸入法狀態甚至有keyup event被吃掉等等的奇怪狀態 最後我找到的是下面這樣簡單的瀏覽器共通實作,起碼在近代的瀏覽器可以簡單的判斷輸入法狀態 document.addEventListener("compositionstart", function(){     window.IMEStatus=1; }); document.addEventListener("compositionend", function(){     window.IMEStatus=2; }); 至少能夠判斷那些時候是在輸入法啟用狀態,避免執行不該啟動的程式碼

收到未預期的重複 HTTP Request

參考文章: What happens when no response is received for a request? 最近碰上的一個問題是後端接收到重覆的 request 在前端的JavaScript留下的 log 也確認送出的 request 只有一個 那麼後端收到重複的 request 的原因反而令人困惑 其實這個問題的原因我在之前就聽過類似的例子 不過直到這次採到痛點才又回想起來 也多虧於此,沒花太多時間就克服了這個問題 根據  HTTP 1.1 RFC 8.2.4 的協定 If an HTTP/1.1 client sends a request which includes a request body, but which does not include an Expect request-header field with the “100-continue” expectation, and if the client is not directly connected to an HTTP/1.1 origin server, and if the client sees the connection close before receiving any status from the server, the client SHOULD retry the request. 也就是HTTP裡有著上述的規範 當 Server 接收了 request 後,理所當然的需要吐出 response 瀏覽器端使用了 Collision Avoidance 的規則 當超過一定時間沒有接收到 response 後,會自動重發 request 所以就會有 JavaScript 的 log 紀錄只有發出一個 request,但 Server 卻收到很多個的狀況 如果後端的頁面需要進行一項長時間的作業 就算你送出這個 request 後並不需要取得任何回應內容也一樣 考量到瀏覽器需要在一定時間內得到回應,那麼可以採取的方式有兩種 第一種就是強迫頁面 flush buffer,先吐些東西讓瀏覽器能接收 當然在這個狀況下,如何讓瀏覽器接收後續的內容就是另一個問題 第二種則是將需...

Android Webview 使用 Basic Authentication 通訊

參考文章: http://en.wikipedia.org/wiki/Basic_access_authentication 這篇沒有技術成分,當成聊聊 Basic Authentication 就好 Basic Authentication 的說明看英文的wiki會比較明顯,中文的wiki我反而看不懂... 作為早期開發的使用者身分認證交換機制 他的優點在於簡單,不需要cookie、session 只需要在瀏覽器送出的Request裡加入header即可,所有瀏覽器均支援此機制 缺點也很明顯,就是安全性不夠好 所以現在的網路身分認證基本上不會用這個方式進行 現在會看到他的場合大多是軟體服務商提供的 API 通訊 不少的公開API服務的進行方式會是: 進行使用者身分認證 -> 取得Token -> 用Token 進行 Basic Authentication,並進行API操作 服務商的Server端會根據Token判別使用者,並依此決定回傳的內容 在JavaScript添加 request header 的需求常見,所以做法好找也不多提了 之前開發 Android 程式時需要用webview 查了下發現做法非常簡單,loadUrl method有一個版本能傳入Header為第二個參數 HashMap<String, String> extraHeaders = new HashMap<String, String>(); traHeaders.put("Authorization", "Basic " + Token); mWebView.loadUrl(url, extraHeaders); 這樣就是常見的API Token在Webview裡的使用方式囉

從user agent辨識新版 IE (IE11)

大家都知道在IE11後,IE就不在 user agent 裡寫上MSIE的訊息 就好像要把新IE跟過去舊IE做的蠢事撇清一樣 只是新版的IE還是有部分行為是沿用過去的,不能辨識時還是有點麻煩 好在 user agent 裡還是保留了些訊息 IE11的 user agent 的內容會是 Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; TAJB; rv:11.0) like Gecko IE10的 user agent 的內容則是 Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Trident/6.0) 其實從這邊可以推測在IE10後,微軟就已經更換了IE的架構 Trident這個字眼應該是微軟內部使用的產品版號 之後辨識這個字眼應該就可以了

網頁連結元素 Javascript Call 之 IE 地雷

相信很多Web開發者都會使用無作用連結做一些項目的設計 例如:<a href="javascript:void(0);" onclick="handler()" > Click me! </a> 設計的原因包含了 link element 的外觀較醒目、預設的mouseover行為的cursor就是pointer等等 你可以注意到其中的href屬性設定了 "javascript:void(0);" href 裡前綴為 javascript: 的內容會被做為 inline javascript call 執行 如此可以避免執行browser的 link element 的頁面跳轉預設行為 void(0); 則表示在JavaScript中什麼也不做 這樣就完成了一個無作用連結 既然 href 可以用來執行JavaScript,當然你也可以用  "javascript : functionA();" 的形式 讓 link element 在被點擊後執行 functionA 聽起來是很方便的做法,既然如此為什麼還會很常聽到不要這樣做的建議? 原因有2點 1是這一段 function 是用eval parse文字後才執行,效率會差一些 當然這個影響並不是那麼大,下一個原因才是重點,也是今天踩到的雷 2.在瀏覽器間的行為並不一致 當使用的function會回傳DOM object,IE會將頁面導到空白頁面並顯示[object HTMLElement]的訊息 而且直到最新的IE11的行為也是如此 這一點算是IE在行為的解讀比較奇怪,都已經是執行JavaScript了卻還保留原本的跳轉頁面行為 所以基於以上理由,少在 link element 的 href 屬性使用 inline JavaScript call 吧

選擇輸入項的提示選項設計方式

這篇來提一個設計上的易用性的小技巧,來自前幾天看到的討論 常見到一個需求是,你會想在選項裡增加提示字眼(例如:請選取選項),但又不是真的想讓使用者選取它 這算是在小地方對使用者更貼心的技巧,那麼要如何達成呢? 先從傳統的透過HTML找看看有沒有方法可以達成,印象中optgroup這個tag似乎有可能? 選項1 code: <select name="demo">     <optgroup label='請輸入選項'>         <option value="1">選項1</option>     </optgroup> </select> 雖然的確有可以提示的部分,但是否符合需求就見仁見智了 第二種方式是透過selected屬性與disabled屬性並用 請輸入選項 選項1 code: <select name="demo">     <option selected disabled>請輸入選項</option>     <option value="1">選項1</option> </select> 選項的預設值透過selected屬性解決,而disabled屬性則會在進行選取時發揮作用 看起來是不錯的方法,只是我在後面有看到一個我更喜歡的方式 第三種方式是透過CSS輔助 請輸入選項 選項1 code: <select name="demo">     <option selected style="display: none;">請輸入選項</option>     <option value="1">選項1</option> </select> display: none;會在選取時發揮作用,讓選單裡乾脆不出現這個選項 目前就看到這幾種方式,設計時可以考慮使用來增加易用性

Even Faster Web Site 讀後

這本書寫的時間點比較早 而最近幾年的browser和網路建設更是日新月異 有些內容可能已經不大適用,不過裡面的多數準則依然可以遵守 一部分的內容在blog其它文章提過了,就不寫在這裡了 追求效率的重點之一便是提高檔案的下載、重繪(render)等處理的效率 很多技巧都是為了追求這個要點而發展出來的