儘量不使用 JavaScript 的前端設計...

在「A JavaScript-Free Frontend」這邊看到的,目前看起來還是很辛苦啊...

首先是可以看到他對 Asana 的抱怨:

First, I live in a rural area with only 2 Mbit/s down Internet connection. With a warm cache it takes 14 seconds for the Asana UI to become usable. Second, you can see below that the app is comprised of over 10MB of uncompressed JavaScript. That is a huge amount of code to execute. How is this acceptable?

現在前端頁面的 JavaScript 愈來愈大,除了下載時間之外,其實最卡的應該還是瀏覽器要處理編譯的時間。作者試著用現有的元素開發他的產品 Slimvoice,然後把心得整理出來... 其實還蠻考驗對 CSS 的基本功,有些東西是你根本不知道存在,另外有些東西是支援度的問題。

這個概念應該就是十多年前倡導的 Unobtrusive JavaScript,不過在這幾年前端框架雨後春筍般冒出來後就不太有人在管了 (一堆站台關掉 js 就不會動),而這也大幅「促進」了瀏覽器對 js 執行速度的改善...

用 CSS 貼 3D 場景的圖

看到一個 demo 展示瀏覽器內 CSS 的處理能力,看起來已經足夠到可以處理不少貼圖與光線效果的部分了:「CSS FPS」。

This is demo of a CSS powered 3D environment. Geometry is created with HTML elements and CSS transforms. Textures and lightmaps are composed by layering multiple background-images and colour is applied using CSS blend-modes.

不過遊戲應該會需要更多種類的效果,這部份目前應該還是得靠 javascript 來產生... (如果要在瀏覽器裡面跑)

用 link="preload" 提高下載的優先度

除了讓 browser 自己決定優先權外,在「Preload Scripts」這邊看到的技巧,可以跟 browser 說明哪些資源比較重要,請儘快先下載:

<link rel="preload" href="main.js" as="script">

Link rel=preload is useful for downloading any important resource more quickly, such as stylesheets that contain critical CSS, fonts that are used in important design elements, and hero images. It's especially important for scripts because they block page content from rendering and consume the most CPU during page load.

以作者的想法,這個技巧應該用在會卡住頁面呈現的部分,確保這些資源可以優先下載。

另外作者也提到了可以直接把這個資訊放到 HTTP header 裡面,理論上會更快:

Link: <main.js>; rel="preload"; as="script"

尤其是 sync script 應該會有幫助,建議可以跑 A/B test 看看效果:

We know that synchronous scripts block rendering, which makes the user experience feel slow. And we know that most scripts today are downloaded synchronously (rather than async). And yet only 1% of sites are using link rel=preload to download their scripts. If your site has any synchronous scripts, do an A/B test adding link rel=preload for them. It's likely this will be a win and help you create a more joyous experience for your users.

另外一套將新版 Gmail 介面改回舊版的 CSS

先前是用「Gmail Old 2018 Nov」撐著,後來在「shellscape/gmail-classic」這邊看到另外一組 css,看起來這組好一些... 拿作者的圖片:

圓框與各種浮誇的 hover 效果都儘量關掉,用起來會好一些。

在手機上看 Trac 的套件

這邊講的是 Safari 這些瀏覽器看 Trac,而不是講 app...

這次從高雄回來,在高鐵上想說用手機看看 Trac,發現桌機版的界面是會動,但在手機上不太好用,所以找看看有什麼套件可以改善...

回到家後找到 BlueFlatTheme 這套 (需要透過 ThemeEnginePlugin 啟用),標語是「A responsive, flat, blue theme using Bootstrap」,拿官方的 screenshot 可以看出來有特地為了寬度比較窄的情況調整:

裝好後用手機測了一下,還是有不滿意的地方,不過改善不少了,先這樣撐著...

MDN 上的 CSS Layout cookbook

MDN 上看到「CSS Layout cookbook」,目前整理了六種情境,包括了設計方式與瀏覽器的支援度。

看到「Center an element」有種苦笑的感覺啊... 以前弄這個都是 workaround,現在都有對應的 CSS 可以處理了。

Trac 關票時的資訊...

Trac 關票時一般都是由開票的人關 (i.e. Reporter),今天遇到的情況是這樣,在關票時的畫面上你會不知道是誰開的:

只要往上一點拉就會看到 Reporter 資訊 XD 這通常會發生在螢幕沒打直的人,直接拉到最下方的情況 XD

試著用 CSS 的 position: sticky 但抓不太到要的效果,決定還是開 jQuery 下去解決 XD

        // Copy reporter information to action section
        if ($('#action_resolve_resolve_resolution').length > 0) {
            var reporter = $('#h_reporter').parent().find('.trac-author, .trac-author-user')[0].outerHTML;

            $('#action_resolve_resolve_resolution').each(function(){
                $(this).parent().append('<span class="hint">(This ticket is created by ' + reporter + ')');
            });
        }

當下寫得很隨性,之後也許會再改... (會更新到「Trac - Gea-Suan Lin's Wiki」這邊)

相對路徑的攻擊方式 (Relative Path Overwite,RPO)

在「Large-scale analysis of style injection by relative path overwrite」這邊看到的,記得這個方式不是新方法,不過還是有人會中...

這種攻擊是組合技,基礎是引用 css 或是 js 時使用相對路徑 (像是 static/style.css 這樣的引用法),再加上 https://www.example.com/a.php 這樣的頁面通常也可以吃 https://www.example.com/a.php/,甚至是後面再加東西... 在某些情境下組不出來,但精心策劃後就有機會在頁面上弄出奇怪的 xss 或是其他攻擊了。而論文內列出了常見的的組合:

然後拿 Alexa 的排名來看,其實還是有些站台可以打:

防禦的方式也不算太難,absolute path 是個還不錯的方式:

One option is to use only absolute URLs, taking away the relative path expansion.

base tag 也是個方式 (不過在 IE 上還是有問題):

Alternatively you can specify a base tag, though Internet Explorer did not appear to implement the tag correctly (i.e., was still vulnerable) at the time of the evaluation.

另外作者也提到了 document type 的方式 (看起來是建議用 html5 的 <!DOCTYPE html>),然後 IE 另外做些處理避免失效:

One of the best mitigations is to avoid exploitation by declaring a modern document type that causes rendering in standards compliant mode. This defeats the attack in all browsers apart from IE. For IE it is also necessary to prevent the page being loaded in a frame by using X-Frame-Options , using X-Content-Type-Options to disable ‘content type sniffing,’ and X-UA-Compatible to turn off IE’s compatibility view.

不過大型站台本來就因為業務需求,會把 asset domain 切開 (然後透過 CDN 加速),而且會設計系統讓 programmer 很容易使用這樣的架構,反而因此比較不會用到 relative path,中這個攻擊的機會就低多了...

Bootstrap 的 CDN 從 MaxCDN 換到 StackPath (Highwinds) 了...

最近在寫網頁時發現 Bootstrap 的網站上給的 CDN 網址改了,從本來用的 maxcdn.bootstrapcdn.com (MaxCDN) 變成 stackpath.bootstrapcdn.com (StackPath,本來的 Highwinds)。

而且看起來跟 MaxCDN 的合作已經全部停了,現在 maxcdn.bootstrapcdn.com 也是指到 StackPath 上。

翻了 Wayback Machine 上的記錄,看起來是在 2018040904501720180410051321 這之間換的,也就是大約是在 2018/04/10 前後換的。不知道後面的交易是什麼...

可以參考 K 社的 SmokePing 資料「SmokePing Latency Page for netdna.bootstrapcdn.com (NetDNA, Bootstrap)」:

可以看到 HiNet 走的點的latency 比之前好不少...

fontconfig fallback 機制與 CSS font-family fallback 機制的衝突...

自己搞不定,加上需要有圖才比較好理解,所以發篇文章問看看...

起因是在 Twitter 上發現某篇文章的截圖,在我的機器上顯示是 sans-serif 類的字型,而對方顯示的是 serif (看起來像是 Mac 的機器上):

而翻了網站本身的 CSS 設定,發現是設成 serif,所以表示我這邊的設定有問題...

找了些資料並且測試,發現是 Linuxfontconfig 所設計的 fallback 機制跟一般人認知的不一樣,使得 CSS font-family fallback 機制直接失效...

在那篇文章的 font-family 設定是「medium-content-serif-font,Georgia,Cambria,"Times New Roman",Times,serif」,所以你會假設 medium-content-serif-font (這是 Medium 設定的 web fonts) 內沒有的字型會去 Georgia 找,然後依序是 CambriaTimes New RomanTimes,最後到 serif

但在 Linux 下的 fontconfig 的設計則跟這點衝突。當你丟 medium-content-serif-font 查詢時,系統會將全系統有的字型都給你 (但是排序好),而不是只有找 medium-content-serif-font 這個字型:

gslin@GSLIN-HOME [~] [22:11/W2] fc-match -s 'medium-content-serif-font' | wc -l
122
gslin@GSLIN-HOME [~] [22:11/W2] fc-match -s 'medium-content-serif-font' | head 
FreeMono.ttf: "FreeMono" "Regular"
FreeSans.ttf: "FreeSans" "Regular"
FreeSerif.ttf: "FreeSerif" "Regular"
opens___.ttf: "OpenSymbol" "Regular"
LinLibertine_R_G.ttf: "Linux Libertine G" "Regular"
Norasi.ttf: "Norasi" "Regular"
KacstOne.ttf: "KacstOne" "Regular"
FiraSans-Regular.otf: "Fira Sans" "Regular"
NanumGothic.ttf: "NanumGothic" "Regular"
fonts-japanese-gothic.ttf: "TakaoPGothic" "Regular"

而因為將所有系統內有的字型都放進去了,所以 font-family 第二個設定基本上都沒用了,因為我裝了一堆語系的文字... Orz

而我想要關閉這套機制,卻發現看起來關不掉:「How to block glyph fallback on Linux?」。

後來想要找 workaround 來解這個問題,不過看起來沒有堪用的 workaround。所以就來問問看有沒有人有建議...?