2018

Baby

2018 年回顧拖了快要半年還沒出來,主要原因是現在空閒時間很少,而且本來想先把記錄組文章的第二篇寫出來,不過想一想還是放棄這個方案,免得到了 2020 年還沒寫好。

去年對我來說變化很大,忙碌到沒有每個月都有拍照,所以放棄以往一個月一張照片的方式,改以文字為主。所以去年有什麼變化呢?去年我換了工作、搬了家、小孩出生然後還買了新車,買車主要是為了方便帶小孩出門時,以前開的是我哥的老車,考慮到安全性和舒適性的問題,決定還是買台新車,然後因為車款熱門所以等很久才拿到車就是。

搬家也是為了小孩,因為考慮到本來住的兩房不夠大才搬的,本來有一間很大環境不錯、價錢不錯還有車位的陰錯陽差沒租到,不過那間缺點是比較偏僻,之後又一直找不太到適合的,然後現在租的也是有點運氣才租到的,本來跟房東約好週末要去看房子,結果前一天房東就打來說租出去了,然後又過了不知道多久那位房東又打來說本來要租的因故無法承租了,然後才輪到我有機會去看,然後一看就覺得不錯就先訂下來,大約是二十年的房子,實際上住進來當然還是有些缺點,不過還算 OK,不過有覺得現在的空間也還無法以後給小孩獨立一間房間,大概過幾年又要再看看了。

工作的部分,其實現在也有點想不起來完整決定離職的原因,不過之前工作有段時間有心理影響生理的狀況出現,現在的工作則是託朋友的福才有的,當時其實最想要的是找國外的遠端工作,第一目標是 Elastic,對於 Kibana 開發還蠻有興趣的,不過可惜連履歷那關都沒過XD,還有一家很想加入的是 DuckDuckGo,其實是第一個投的,履歷的品質和後來的版本差很多,也是一樣沒下文,其它有得到大約兩家的面試機會,不過都沒順利過關,自我評量大概是英文表達能力還明顯不足,現在的工作則是想要的外國公司都失敗後,開始要在國內找時,先有一些朋友來找我,然後我就從中挑了其中一個工作了,其實本來有想公開找的,不過也是還沒機會公開說就確定了。之後大概等小孩大一點就要開始來加強英文了,這部分真的是應該早點開始的。

最後終於要來談談小孩的事了,我家小孩是 5/3 號晚上出生的,剛好預產期同一天,差一點就變成原力寶寶了,不過講真的生產過程也是很辛苦,老婆痛了將近 20 小時,差點就要全餐了,然後還臍帶繞頸,生出來之後給小兒科那邊弄了好久才哭出聲音來,等待的時候真的是很緊張,還好沒什麼其它異狀,大概就是不好帶吧,不愛吃不愛睡,即使到今天已經滿一歲了還是一樣,還好長得很可愛,不然早就忍不住垂下去了(?),說可愛也不是父母視點,是真的客觀來說長得很可愛,在外面常常被當成小女生,睫毛超長,甚至有過一次背著他走路時,路邊一個大叔看到驚呼:「太可愛了吧!」不過隨著年紀越來越大可愛度似乎也有下降了。有小孩之後生活和心境都變化不少,也必須放棄不少東西,要寫的話好像可以寫一堆,所以還是不寫了,不過就是,在某些時候,就突然想起了 About Time 的劇情,曾經一直想著為什麼主角不再穿越時間,似乎現在也明白了。

Baby


W3C and WHATWG and HTML

w3c-whatwg-logos

「天下大勢,分久必合,合久必分」,沒想到 W3C 和 WHATWG 之間的複雜關係就這麼突然的踏上新的里程碑了,今天 W3C blog 發表了一篇文章-W3C and the WHATWG signed an agreement to collaborate on a single version of HTML and DOM,說兩個組織已經簽好合作的協議了,未來算是要共同維護同一份 HTML 和 DOM 的 spec,HTML WG 的章程也因此要重新制訂,現在有草稿可看,詳細一點的摘要可以看 W3C CEO Jeff Jaffe 的文章 -W3C and WHATWG to work together to advance the open Web platform

  • W3C and WHATWG work together on HTML and DOM, in the WHATWG repositories, to produce a Living Standard and Recommendation/Review Draft-snapshots
  • WHATWG maintains the HTML and DOM Living Standards
  • W3C facilitates community work directly in the WHATWG repositories (bridging communities, developing use cases, filing issues, writing tests, mediating issue resolution)
  • W3C stops independent publishing of a designated list of specifications related to HTML and DOM and instead will work to take WHATWG Review Drafts to W3C Recommendations

基本上就是 W3C 相關的 WG 以後都改成貢獻到 WHATWG 那邊(在 GitHub 上),然後 W3C 那邊會拿 WHATWG 標準文件的 snapshot 來作為 CR、PR、REC,或許也可以稱為 Living Standard 的勝利。

如果要看比較細節關於兩個組織間簽的合作內容也有公開在網路上-Memorandum of Understanding Between W3C and WHATWG,裡面還有列出所有相關的 W3C 的標準文件,以前我就一直很好奇到底全部是有哪些,剛好趁這機會一次收集齊全,其實還不少我沒看過的,甚至也有 404 的(?),其中推薦標準(REC)的部分:

  1. https://www.w3.org/TR/html5/including other URLs under this directory
  2. https://www.w3.org/TR/html50/including other URLs under this directory
  3. https://www.w3.org/TR/html51/including other URLs under this directory
  4. https://www.w3.org/TR/html52/including other URLs under this directory
  5. https://www.w3.org/TR/html/including other URLs under this directory
  6. https://www.w3.org/TR/webstorage/
  7. https://www.w3.org/TR/webmessaging/
  8. https://www.w3.org/TR/eventsource/
  9. https://www.w3.org/TR/2dcontext/
  10. https://www.w3.org/TR/dom/

非推薦標準:

  1. https://w3c.github.io/html/including other URLs under this directory
  2. https://www.w3.org/html/wg/drafts/html/master/including other URLs under this directory
  3. https://www.w3.org/TR/websockets/
  4. https://www.w3.org/TR/2dcontext2/
  5. https://www.w3.org/TR/microdata/
  6. https://www.w3.org/TR/staticrange/
  7. https://www.w3.org/TR/workers/
  8. https://dvcs.w3.org/hg/webperf/raw-file/default/specs/RequestAnimationFrame/Overview.html
  9. https://w3c.github.io/dom/
  10. https://www.w3.org/TR/dom41/
  11. https://www.w3.org/TR/DOM-Parsing/
  12. https://www.w3.org/TR/html53/

這些東西在 WHATWG 那邊基本上都寫在HTMLDOM裡面,就是單一份標準文件內塞了比較多東西這樣。

最後就是我還發現一點有趣的,WHATWG投票那邊,四位出來投票的分別是 Apple、Microsoft、Mozilla 和 Google 四間公司的人。然後我只對 Mozilla 的dbaron有印象而已。


SameSite Cookie

Cookie Time

Cookie 的規格是 RFC 文件所定義的,其實一直以來都有在演化,目前為止已經有三個版本,照順序分別是RFC2109RFC2965和最新的RFC6265,像是HttpOnly就是 RFC6265 才出現的,而最近最新的屬性,就是SameStie了,其實它和HttpOnly的起源很接近,都是近年來比較被人重視的安全性和隱私的原因,Google 的 web.dev 有一篇圖文並茂的文章介紹的很詳細-SameSite cookies explained,建議還不清楚什麼是 SameSite cookie 的可以先去看一下。

SameSite Cookie 的標準文件其實還未正式定稿,目前還算是草稿RFC6265bis(bis 在The Tao of IETF有解釋),不過主流瀏覽器都已經支援了,然後其實這篇文章我想說的是最近在 W3C TAG 看到的 Issue 373:SameSite=Lax by default,是由 Google 的 Mike West 提案要把 SameSite 的預設值改為 Lax,現在 Google Chrome 已經有這個實驗選項了,而且除了 SameSite 預設值的改變之外,其實還有一個修改目標是SameSite要在Secure的時候才能設為None,這項改變相對而言是影響比較大的,所以提案的文件(Incrementally Better Cookies)也有提到可以分步進行,另外就是 Firefox 也表示有意願來實做,看起來至少 SameSite 預設改為 Lax 這件事應該是不會太久之後就會發生了。

在花時間看一些文件內的參考資料後,發現 Mike West 還有其它幾份相關的草案:

  • first-party-set是用/.well-known/URL 來跟客戶端溝通,可以提供 first party 的域名清單;
  • First-Party Sets and SameSite Cookies利用上面的 first-party-set 資訊,然後提供兩種新的 SameSite 值:FirstPartyLaxFirstPartyStrict
  • HTTP State Tokens定義了個標準化的 session token,是由瀏覽器端產生的 token,而不是 Web API,至於怎麼傳遞到 server 端,怎樣溝通有效期等都有寫在規範內,Incrementally Better Cookies 的想法也是從這份草案中的特性而來。

這些草案都還蠻有趣的,至於會不會定稿成為規範甚至大家都開始實做,目前就還很難斷定了。


glob

最近在搞 jsctags-oasis 這個專案,因此認真的研究了一下 glob,glob 這東西其實有在使用 CLI 的話,一定是使用過的,例如:

ls *.js

後面的*.js就是 glob,應該可以稱為一種表達式吧,沒有正規表示式(Regular Expression)強大,是專用於匹配檔案的,現在也已經是內建於 Linux shell 內的功能了,所以其實只要man glob.7或是man 7 glob就可以找到官方文件了(不過 macOS 上沒有),然後 glob 和正規表示式相比,有個很關鍵的差異就是 glob 是有判斷路徑階層的,也就是其實?*雖然是任意字元,但是/不屬於任意字元,/又被稱為 path separator,如果要找不同層子目錄的檔案,就要把路徑寫好,不然比對時不會如願找到想要的目標,而這個差異其實也說明了為什麼ls subfolder/*只會印出該層子目錄下的檔案,而不是把第二第三層子目錄下的東西也都印出來,雖然有**這個寫法,不過我是在 nodejs 開始蓬勃發展之後才在 node-glob 文件上看到的。

其實我第一次看到 glob 這個單字也是node-glob,不過當時以為 node-glob 和命令列的那套不相容,只是借用名字而已,因為那個**/*.js的語法我以前沒看過,一直以為是 node-glob 自己做的,直到這次研究才發現其實**bash提供的擴充語法,bash 的 extglob 提供了一些更接近正規表示式的語法:

?(pattern-list)
       Matches zero or one occurrence of the given patterns
*(pattern-list)
       Matches zero or more occurrences of the given patterns
+(pattern-list)
       Matches one or more occurrences of the given patterns
@(pattern-list)
       Matches one of the given patterns
!(pattern-list)
       Matches anything except one of the given patterns

另外還有很多設定可以調整 glob 的行為,其中一樣叫做globstar的,就是讓**可以 recursive 的 match 子目錄的檔案,這個功能是在bash 4.0 alpha版的時候新增的,到今天其實也已經超過十年了。

至於為什麼會研究起 glob 呢?是因為我在做 jsctags-oasis 時,要盡量的支援Exuberant Ctags支援的參數,其中做到exclude的時候,一開始偷懶用了 node-glob 的 ignore,但是實際上要拿vim-gutentags來用時卻行為不如預期,為了能正確支援就研究起這實際上怎麼串起來的,首先是 vim-gutentags 會拿 Vim 那邊的wildignore送給 ctags,wildignore 使用的表達式是 Vim 自己的filepattern,和 glob 有點接近,像是*都是正規表示式的.*,還有?都是正規表示式的.,不過*有特別說到:

Unusual: includes path separators

這行為就和 glob 不一樣了,所以假設 ctags 的exclude也是用 glob 表示式,那是不是表示 vim-gutentags 這邊實做有不正確呢?結果我發現 Exuberant Ctags 的文件是這樣說的:

each pattern specified using this option will be compared against both the complete path (e.g. some/path/base.ext) and the base name (e.g. base.ext) of the file, thus allowing patterns which match a given file name irrespective of its path, or match only a specific path. If appropriate support is available from the runtime library of your C compiler, then pattern may contain the usual shell wildcards (not regular expressions) common on Unix (be sure to quote the option parameter to protect the wildcards from being expanded by the shell before being passed to ctags; also be aware that wildcards can match the slash character, '/').

這時候就要感謝那時期的文件都有寫得很詳細,不用花時間去看程式碼,這邊的說明就是說會比對 basename (檔名加附檔名)和完整的 pathname,另外對於 wildcard 的支援則是看系統,是用shell wildcards,其實就是 glob 表達式,不過照這樣說,應該就和 Vim filepattern 不一樣了,研究許久才注意到關鍵的地方就在上面那段文件的最後一句,提到 wildcards 也會 match 到/字元,也就是最前面提到的 path separator,結果就是, Vim filepattern 和 Exuberant Ctags 的exclude用的表示式基本上是相容的,但是也因為特性就無法用 node-glob 的ignore來支援了。所以我就照著說明自己實做了比對的部分,然後有用到一個叫globrex的 npm package,這個是tiny-glob底層用的工具,算是個偷吃步,不管 path separator 直接把 glob 轉成正規表示式的作法,根據原始碼,它會直接把*轉換成.*,這樣就會 match 到/字元了,本來是偷吃步的作法,卻意外的剛好合用,理論上這樣就可以正確的支援 ctags 的exclude才是吧。


addEventListener 的第三個參數

addEventListener

2007 年我寫過一篇一樣標題的addEventListener 的第三個參數,介紹了事件發生時, DOM Node 的 capture 和 bubbling,事隔十多年,前陣子定睛一看,發現 DOM spec 有變,第三個參數除了可以收 boolean 型別的 useCapture 之外,還可以收options物件,又稱為EventListenerOptions,而這個 options 物件現在支援三個屬性,分別是:

  • capture-就是以前的第三個參數 useCapture,Boolean 型別。
  • once-新的選項,也是 Boolean 型別,用途就像是 jQuery 的one一樣,想不到現在也直接在 DOM 層原生支援了
  • passive-也是新選項,一樣是 Boolean 型別,用途是告訴瀏覽器,這個事件 handler function 會不會呼叫event.preventDefault來停止瀏覽器的原生行為,我最初其實是在 Google 的關於scroll performance 的文件看到的,就是如果你是 scroll event,以前會因為瀏覽器要判斷會不會被preventDefault,所以讓 scroll 的效能變差,加上這個選項可以直接告訴瀏覽器說沒有要 preventDefault 後,原生的事件行為就可以不管 event handler 直接處理了,如果裡面硬是執行event.preventDefault的話,那就會被忽略掉,然後根據使用的瀏覽器的話,有的會有警告訊息出現在 console。

Passive Event 的效果也有人做了影片可以看(來源):

EventListenerOptions 這個東西大概是在 2015 開始討論的,然後2016進到 WICG 討論,瀏覽器開始實做,一開始就是只有passivecaptureonce則是後來才加上的,所以可以看到 MDN 的瀏覽器支援度表格,once還要比較新一點的瀏覽器才支援,像是 Chrome 51 就支援passive,然後要到 55 才支援once,如果再仔細看,會發現最後一列是touchstarttouchmove事件如果是在 document 層的話,預設改為 passive 事件,這是 2017 年 Chrome 主導修改的行為,Firefox 也有跟進,主要就是希望能讓這些事件處理預設效能好一點,這部分的行為修改其實到現在都還沒標準化,目前還是在 WICG 那邊有個open issue,除了 touch 事件外,其實連 document 層的 wheel 事件也在Chrome 73,也就是現在的穩定版本也預設改為 passive 事件了,然後也是有 WICG 的open issue,MDN 的表則是還沒有。

EventListenerOptions 也是有 polyfill 和工具 package 的,首先來說一下 polyfill 吧,我知道的有dom4,其實搜尋一下還蠻容易找到其它的,不過差異沒很大,feature detection 的方式幾乎都是用 Object 的 getter 來看送進去的 options 物件的passive屬性有沒有被讀取過,有的話就表示瀏覽器有支援,然候 polyfill 其實也只有行為上的補完,不會真的讓效能提升,不過 polyfill 在現在的支援度下來看也是不太需要了。Package 的話有個default-passive-events會幫忙把 scroll、wheel、mouse、touch 等等有需要的事件都改為預設passive: true,如果是新專案先加一下似乎不錯,不過感覺上 Google 是很想都改掉的樣子,現在其實也只差 mouse 事件而已,應該是還怕影響太大不敢下手吧。


➡ 看看其它文章