尋找 YouTube 進度條上的流星

January 23, 2016

開始讀正文之前先來聽首歌吧!

記得當年 YouTube 進度條出來的時候好像造成一片轟動,突然之前大家爭先恐後 implement 它,蔚為風潮;而當年 implementation 中的佼佼者就是 NProgress,到了現在還是盤據一方(?)。

其實之前也不乏做過類似的進度條效果,不過從來沒有特別對 peg 的部分雕琢(或著說根本沒有加)。

什麼是 peg 呢? 來看一下 NProgress 裡面的一段 CSS code

/* Fancy blur effect */
#nprogress .peg {
  display: block;
  position: absolute;
  right: 0px;
  width: 100px;
  height: 100%;
  box-shadow: 0 0 10px #29d, 0 0 5px #29d;
  opacity: 1.0;

  -webkit-transform: rotate(3deg) translate(0px, -4px);
      -ms-transform: rotate(3deg) translate(0px, -4px);
          transform: rotate(3deg) translate(0px, -4px);
}

實際上看起來的效果是

nprogress_peg.png

這個小小的點綴其實為這個進度條增色了非常多,因為進度條本體的高度並不高,透過這個 peg 可以再它動作的時候達到比較好的吸引注意力的效果,讓使用者更容易意識到有什麼東西在動作中。

這個效果其實 YouTube 版本的進度條上面就有,不過我從來沒有好好正眼看過它(一閃即逝嘛)。最近的專案又做了類似 YouTube 的進度條,於是默默決定應該要好好地看一看 YouTube 的 peg 是怎麼做的,便開始了這次尋找流星的旅程。

Read on 

週末長知識: 不換行空格

January 23, 2016

最近處裡一些 HTML 裡面的字串空白,發現在出現   的時候好像用 ' ' 會消不完全… 沒道理啊?

舉個例子

有沒有感覺到一點點的微妙,為何中間的空白不會被 split() 切開呢? 難道從 $(...).text() 取得的中間有些空白不是一般的空白?

接著把上面實驗中的字串拿來研究一下。

// 來源: 上面範例中的 $.trim($('#content').text())
var str = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit.';

console.log(str.charCodeAt(str.indexOf('sit') - 1)));
// output: 160

知道 charcode 是 160 之後應該就很好搜尋囉,於是用 「charcode space 160」 去 google 了一下找到這篇文章:

White-space and character 160

So I used charCodeAt and found it was ASCII character 160. I looked up char code 160 and saw that it is a “Non-breaking space”. You would think that a “space” character would be trimmed. I looked at the jQuery code that does the trimming and the grep pattern uses \s. So, evidently you can’t use \s to catch the “Non-breaking space” in IE. I wonder why no one else has seen this.

乍看好像是古早年代的 IE 問題? 那我怎麼現在會在 modern browser 裡面碰到呢?

接著來試著搜尋中文 「char 160 空白」,發現相關的問題在各種地方出現…

char_160_whitespace.png

突然就看到了 Wikipedia 的連結

眼尖的話會注意到原來在 HTML 裡面的 &nbps; 竟然是也是不換行空格的實現!!!!! 小時候填鴨式學的 HTML,只知道   是一種輸入空白的方法,原來它還有這層特別的含意… 更何況原來它根本不是空白!(說是也可以是啦)

原來 2009 年的 IE 是對的。(根據上面 2009 年的文章,當時的其他瀏覽器都把   輸出為一般的空白 ' ',但 IE 裡面用 regular expression /\s/ 還是 match 不到 '\u00a0')

總之現在 modern browser 們也都是把   轉為這個 '\u00a0',以後碰到類似的東西就不需要大驚小怪囉! 心裡有個底的話,debug 起來會快很多的。

最後補充一下,上面 2009 那篇文章的內容已經與現在瀏覽器的情況不符了。 文中附的 test 頁面 ,展示的 jQuery trim(text) 結果現在看起來是正確的,因為現在的瀏覽器已經確實把 '\u00a0' 視為空白的一種囉!

用 code 來說就是

'\u00a0\u00a0'.replace(/\s/g, '') === '';  // true

React 碎碎念: 艱困的新手之路

January 16, 2016

其實關注 React 的東西已經很久,直到最近剛好有機會就在新的專案跳坑下來,寫了兩個星期之後有很多事情覺得應該要寫下來做個紀錄。

至於為什麼叫碎碎念而不叫做筆記呢? 因為文章中個人抒發感想的部分可能也不在少數,又或著可能我沒有真心喜歡它(React)吧。

碎碎念大部分是個人意見,客觀部分敘述有錯誤歡迎指證。

正文

我真心覺得現在的 React 超難上手。

在 JS 的生態系統推進,以及各種工程師大大們的持續努力之下,想要上手現在的 React (可謂是 modern React)大概需要了解、會操作下面這些東西:

再補上一些可選的項目

當然如果上述這些都有統一而且很直覺的學習路徑也就罷了(用現在的英文說是 opinionated),但我想現在的 JS 精神就是要把所有東西都 modulize,所以往往我們光是 configure 環境就要花掉大把的精神與時間。

可以看一下 AngularClass 在去年年底對 React developers 做的調查,就知道是一個多麼充滿選擇的環境(菸)。

Read on 

三個不要再用 jQuery Promise 的理由

December 20, 2015

Update 2016/04/05 20:27 話說 beta 中的 jQuery 3.0 確定 Promise 的部分會是相容於 Promises/A+,到時候出了正式版本可以開心升級!


其實不要用 jQuery promise 這回事兒,時有所聞,最主要的原因是其實它實作的內容跟外面大部分的 Promise library (Promises/A+)都不一樣。

所以很多人覺得 jQuery 的 Promise 只是名為 Promise 的「某種東西」,並不是真正的 Promise。

想了解詳情可以看一下 2012 年的這篇文章 You’re Missing the Point of Promises

然而我一直不以為意。

到這個星期我才切身的實際體會不要用的原因,這邊列出三點,應該是比較容易碰到的情況。

1. 面對靜態結果,$.when() 不會以非同步的方式產出 resolved promise

這個我想應該很多人已經有經驗 XD

舉例如下:

// 期待中,結果會是以 async 的方式取得
function xhrGet(something) {
    if (cache) {
        return $.when(cache);
    }
    return $.get(something);
}

/**
 * 在送出 XHR request 之後清空頁面,取得 response 之後重繪頁面
 * 
 * 沒有 cache - 正常運作
 *   有 cache - 在 `renderPage()` 之後才 `clearPage()`,頁面就沒了
 */
xhrGet(...).then(function (res) {
	renderPage(res);
});
clearPage();

那麼我們實際來確認一下大家的情況,下面用了三家的 library 來做測試: (其中 Promise 的部分是用 polyfill 的方式,如果你的瀏覽器有原生支援就會用瀏覽器內建的)

Read on 

週末長知識: scrollable <div> 的捲動重繪問題

December 05, 2015

Update 2020/05/05 12:00 Chrome 瀏覽器在當前版本(v81)已經沒有這個問題,本文就留做記念吧!(我想應該更早就已經修正了,但我遲遲沒有重新檢查)

前端也是做了很久,直到最近才發現這個事實,感覺有點羞愧 ww 為了讓同樣的事情不要再重演,決定專文說明之!

以下文章的內容基本以 Chrome 瀏覽器作為展示用的平台,所以一些 render performance 的問題不見得會出你家的瀏覽器上,畢竟各家瀏覽器為了讓使用者能夠順暢瀏覽網頁,可能還是有做一些各自的調整。

現在已知的是 Opera 在本文主題的範圍內所受的影響與 Chrome 是一樣的(同為 Blink引擎)。

scrollable <div>

其實直接看一下 CSS 就明白我的意思啦

.scrollable {
    height: 100%;
    overflow: auto;
}

其實就是帶有捲軸的 <div> 而已,它的特性是在內容超出設定的 寬度/高度 之後會出現捲軸(用 overflow: scroll 的話,會一直有捲軸)

捲動重繪問題,初次見面!

其實就是在新版的 手打 首頁。

其實一開始還感覺不大出來,但多捲幾下之後發現這個捲動的吃力程度連我的(三年前的)超級遊戲桌機都有點受不了,馬上來用 Chrome DevTools 看兩把!

before.png

從圖中可以清楚的看到每個 frame 中有很長的時間用在 painting,並且很多 frame 的運作時間超過 16~17ms,造成整體的 fps 沒辦法達到 60。

簡單的重現

Preview 的時候先按「Launch the preview in a separate window」在新視窗開啟,再來打開 DevTools 觀察比較準(原本擺在 iframe 裡可能會影響結果)

確認的方法就是開啟 DevTools 裡的「Enable paint flashing」,就可以在捲動的時候看到重繪的區域。

Read on