<?xml version="1.0"?>
<rss version="2.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007" xmlns:atom="http://www.w3.org/2005/Atom">
   <channel>
      <title>Othree4MozTW</title>
      <description>Pipes Output</description>
      <link>http://pipes.yahoo.com/pipes/pipe.info?_id=oM_MwWPI3RGN5pxX1ZzWFw</link>
      <atom:link rel="next" href="http://pipes.yahoo.com/pipes/pipe.run?_id=oM_MwWPI3RGN5pxX1ZzWFw&amp;_render=rss&amp;page=2"/>
      <pubDate>Thu, 01 Oct 2015 22:36:05 +0000</pubDate>
      <generator>http://pipes.yahoo.com/pipes/</generator>
      <item>
         <title>React 入門</title>
         <link>http://feedproxy.google.com/~r/othree/~3/b7esD9E8t3Q/</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/13990963771/&quot; title=&quot;&amp;#x004eac;&amp;#x0090fd;&amp;#x005d50;&amp;#x005c71; by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm6.staticflickr.com/5237/13990963771_028f39af66_b.jpg&quot; width=&quot;1024&quot; height=&quot;683&quot; alt=&quot;&amp;#x004eac;&amp;#x0090fd;&amp;#x005d50;&amp;#x005c71;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;其實這篇想寫一陣子了，不過拖太久本來想放掉，是後來又看到 TonyQ 在說他的經驗，就覺得還是寫一下，搞不好可以幫到人(?)，然後其實我對 React 沒深入研究，目前也只寫過一次，也沒做到複雜的　App，所以這篇純粹是我的觀察啦。&lt;/p&gt;

&lt;p&gt;先講結論，寫過目前一般 Web App 的人，要來寫 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://facebook.github.io/react/&quot;&gt;React&lt;/a&gt; 大概都要一些撞牆期吧，我的狀況是要寫 React + &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://facebook.github.io/flux/&quot;&gt;Flux&lt;/a&gt; 架構的 Web App，但是一開始對 Flux 的介紹沒認真看，在一知半解的狀態下就開始做了，結果就一直出現些靈異現象，大部分是覺得應該要更新畫面了但是沒有，追到後來大概就兩個原因：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;亂用 props 和 state，總之就是 React 只會在 state 變化的時候更新畫面，props 變化的時候不會（其實設計上是 immutable 的），而用 props 的時機基本上是父層 component 要設定資料給子 component 的時候才會用，至於父層收到不同的資料給子 component 時，同樣是改 props，為什麼畫面就會更新了，事實上是因為父層 component 更新的時候，才有機會改動到子 component 的 prop，而因為有重新 render，子 component 的內容也會一起更新，也才更新了畫面。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;想要只更新子 component，這個問題就是沒把 flux 的設計弄清楚，Flux 的 store 其實有點代表所有的資料的意思，而不管是什麼動作，都要把整包的 store 資料更新回去，根 component 會綁事件在 store 的更新事件上，發現 store 資料有更新就開始重新 render component，然後跟著它的子 component 就會因為 prop 更新而跟著更新。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;當然 store 是可以有多個的，重點在於每次更新都要整個 store 的資料重新給根 component，不能從 store 裡面某一層開始送，然後想要只更新某個子 component，這樣結果就很容易發生靈異事件，當然 React 可以不用 Flux 架構，不過我覺得那條路走起來更困難，所以還是乖乖使用 Flux 架構，其實我後來做的結構很簡單，action 就只是一個事件，store 就是 POJSO 而已，沒用到一些市面上的 Flux framework。&lt;/p&gt;

&lt;p&gt;最後一點要提的就是每次都整包 store 更新，可能就會有人想到效能問題，當然 React 本身效能不錯，不過資料量要是超大，可能還是會有出現狀況，我想這也是為什麼 Facebook 要發展 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://facebook.github.io/immutable-js/&quot;&gt;Immutable.js&lt;/a&gt; 的原因，其實我仔細瞭解後，發現 Immutable 配合 Flux 架構真的是超適合的，而且他在大量資料更新的時候，可以保持蠻不錯的效能，因為只有 reference 的變化，而不是真的重新產生整包資料，沒變化的資料都是本來就已經在記憶體裡面的，整體的資源消耗少很多。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=b7esD9E8t3Q:DPr4M5Lgf5E:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=b7esD9E8t3Q:DPr4M5Lgf5E:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=b7esD9E8t3Q:DPr4M5Lgf5E:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=b7esD9E8t3Q:DPr4M5Lgf5E:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=b7esD9E8t3Q:DPr4M5Lgf5E:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/b7esD9E8t3Q&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/08/21/react-intro/</guid>
         <pubDate>Thu, 20 Aug 2015 16:38:04 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>fetch is the new XHR</title>
         <link>http://feedproxy.google.com/~r/othree/~3/mYyVIHQU1eQ/</link>
         <description>&lt;p&gt;這次 COSCUP 講的是新的 Web API: fetch，其實這個東西要用只要看 HTML5 Rocks 那篇文章就好了，只是我在使用和做 fetch-er 的時候發覺很多的細節和問題（投影片裡面的 facts），有一些不跟最新進度也不知道狀況是怎樣，連 Stack Overflow 上也沒有，可能有人遇到但是不知道，所以就和我的 fetch-er 專案一起投稿。&lt;/p&gt;

&lt;p&gt;和 fetch-er 專案一起投稿的另一個考量是，在 COSCUP 和 OSDC 分享這麼多次，年初我突然才發現我的講題和 Open Source 的關連度實在太低（嚴格說來我在那時才認真意識到 open source 和社群的差異），只有 2013 的 COSCUP 是講我在 Vim Plugin 開發上的歷程，其他有一場有介紹到 underscore，之外就大部分是在介紹 Web 的新東西，所以認真的覺得今年要投和 Open Source 相關的東西，而不是只是 Web 相關的而已。&lt;/p&gt;

&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=mYyVIHQU1eQ:S36A0Vo2b5w:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=mYyVIHQU1eQ:S36A0Vo2b5w:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=mYyVIHQU1eQ:S36A0Vo2b5w:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=mYyVIHQU1eQ:S36A0Vo2b5w:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=mYyVIHQU1eQ:S36A0Vo2b5w:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/mYyVIHQU1eQ&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/08/17/fetch-is-the-new-xhr/</guid>
         <pubDate>Mon, 17 Aug 2015 10:28:00 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>My First Patch to Firefox</title>
         <link>http://feedproxy.google.com/~r/othree/~3/9vuI-4IQApc/</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/20310084805/&quot; title=&quot;zh download dialog by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm1.staticflickr.com/261/20310084805_2c8ed51b8e_b.jpg&quot; width=&quot;424&quot; height=&quot;223&quot; alt=&quot;zh download dialog&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OSX 自從升級到 10.10 之後，繁體中文版 Firefox 就冒出了一個 bug，一堆使用到作業系統原生的視窗，像是下載圖片，開啟檔案等等的，都會變成簡體中文介面，這個問題在 Bugzilla 上的編號是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1089363&quot;&gt;1089363&lt;/a&gt;，畫面看起來就像上面的圖一樣，這個問題的狀況，推測是 OSX 本來在這種系統對話框，會使用使用者現在設定的系統 locale，但是 10.10 改成應用程式正在運作的 locale，然後 Firefox 本來會用 locale &lt;code&gt;AB_CD&lt;/code&gt; 中的 &lt;code&gt;AB&lt;/code&gt; 段而已，所以 &lt;code&gt;zh_TW&lt;/code&gt; 和 &lt;code&gt;zh_CN&lt;/code&gt; 就都會變成 &lt;code&gt;zh&lt;/code&gt;，然後 OSX 的 &lt;code&gt;zh&lt;/code&gt; 又會變成簡體中文，結果就變成這樣了。&lt;/p&gt;

&lt;p&gt;其實這個 bug 的解法， Steven Michaud 很早就提出了，就是把本來 locale 的 resource 目錄的名稱改成 &lt;code&gt;zh_TW&lt;/code&gt;，大概 diff 如下：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; AB_CD = $(MOZ_UI_LOCALE)

-AB := $(firstword $(subst -, ,$(AB_CD)))
+ifeq (zh-TW,$(AB_CD))
+LPROJ_ROOT := $(subst -,_,$(AB_CD))
+else
+LPROJ_ROOT := $(firstword $(subst -, ,$(AB_CD)))
+endif
+LPROJ := Contents/Resources/$(LPROJ_ROOT).lproj&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其實不會很難，不過因為 Firefox 的程式碼變動很快，連 build script 也常常變動，那個 patch 檔出來的時候已經不能用了，然後又沒人處理就這樣一直拖下去，前陣子 Moztw 那邊又被提出來一次，剛好我為了弄 WebIDL 相關應用的時候有 build 過 Firefox，想說應該可以處理看看，就接下來嘗試了，build 本身蠻簡單的，就照著網路上的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://developer.mozilla.org/en-US/docs/Simple_Firefox_build&quot;&gt;文件&lt;/a&gt;就好，比較難的是要 build 成特定語系的，找很久才在 Moztw 討論區找到&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://forum.moztw.org/viewtopic.php?f=18&amp;amp;t=34806&quot;&gt;答案&lt;/a&gt;，要在 &lt;code&gt;.mozconfig&lt;/code&gt; 裡面加上：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ac_add_options --with-l10n-base=/d/lang
ac_add_options --enable-ui-locale=zh-TW
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其中第一行設定的路徑要指定到你指定的位置，而且要絕對路徑，然後在該目錄 clone 翻譯的 repository 下來，可以在 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://hg.mozilla.org/l10n-central/&quot;&gt;l10n-central&lt;/a&gt; 那邊找自己的語系，以 &lt;code&gt;zh-TW&lt;/code&gt; 來說：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd /d/lang
git clone http://hg.mozilla.org/l10n-central/zh-TW/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然後這樣就可以 build 中文版了，build 完執行就看到精美的黃底紅字 XML 解析錯誤視窗。&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/19687462694/&quot; title=&quot;Firefox Missing String by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm1.staticflickr.com/382/19687462694_626110d91c_b.jpg&quot; width=&quot;375&quot; height=&quot;190&quot; alt=&quot;Firefox Missing String&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;還好我有點經驗，知道 Firefox 的介面是 XUL 寫的，然後字串是用 XML entity 方式存在，所以很快就想倒是翻譯問題，於是上去找了 l10n dashboard 看看&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://l10n.mozilla.org/teams/zh-TW&quot;&gt;繁體中文&lt;/a&gt;的狀況，看的是 &lt;strong&gt;fx_central&lt;/strong&gt; 這棵樹下的字串：&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/20301676302/&quot; title=&quot;Firefox l10n stat by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm4.staticflickr.com/3682/20301676302_3c488073c1_b.jpg&quot; width=&quot;991&quot; height=&quot;738&quot; alt=&quot;Firefox l10n stat&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;可以看到目前有缺哪些字串，因為字串還沒穩定所以也還不會有翻譯，所以就需要手動進去把這些 entity 的定義補上，內容隨便填，然後重新 build 一次，結果就修好了！&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/19689109663/&quot; title=&quot;nightly zh_TW download dialog by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm1.staticflickr.com/517/19689109663_81ff6a8f9a_b.jpg&quot; width=&quot;973&quot; height=&quot;777&quot; alt=&quot;nightly zh_TW download dialog&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;然後就開始想辦法生 patch 檔案了，中間也有用過 &lt;code&gt;hg mq&lt;/code&gt;，最後都固定改好，commit 後用 &lt;code&gt;hg export . &amp;gt; fix.patch&lt;/code&gt;，總之改好我就丟上 bugzilla 了，結果第一個 patch 只改到一個檔案，實際上應該有五個檔案要改，而且才隔一天，Makefile 就被別人改過了，只好重新找位置修改，重新生 patch，到最後一個 review 過，build 也過的 patch 中間還發生了不少事情，包括 Makefile 被別人又改動一次，用 &lt;code&gt;AB&lt;/code&gt; or &lt;code&gt;LPROJ&lt;/code&gt; 的命名問題，字串的變化造成假翻譯又要增加，還有 build 工具 mach 被人改壞，和推上去之後有 build 失敗的狀況等等，非常的一波三折。&lt;/p&gt;

&lt;p&gt;其中 build 失敗是 b2g 的 build 失敗，原因是我有地方改錯，不過要測試也是要重新設定，參考的是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://developer.mozilla.org/en-US/Firefox_OS/Building_the_Firefox_OS_simulator&quot;&gt;Building the Firefox OS Simulator&lt;/a&gt; 這份文件，把 &lt;code&gt;.mozconfig&lt;/code&gt; 改成：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;. &quot;$topsrcdir/b2g/config/mozconfigs/common&quot;

mk_add_options MOZ_OBJDIR=../build
mk_add_options MOZ_MAKE_FLAGS=&quot;-j9 -s&quot;

ac_add_options --enable-application=b2g
ac_add_options --disable-libjpeg-turbo
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;重新 build 看能不能過。&lt;/p&gt;

&lt;p&gt;改完產生的 patch 檔上傳到 bugzilla 時，要勾選 Content Type 是 patch，然後 review flag 設定成 &lt;code&gt;?&lt;/code&gt;，選一個 reviewer，通常會有 mentor 來跟你說選誰好，我的情形是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.timc.idv.tw/&quot;&gt;timdream&lt;/a&gt; 在幫忙，接著就等 reviewer review，他 review 過的話， review flag 就會變成 &lt;code&gt;+&lt;/code&gt;，然後就會收到一封「Congratulations on having your first patch approved」的信件，說了一些後續可以做的事情，接著要做的就是讓 patch 真的進去 repository，可以在票的 keyword 加上 &lt;code&gt;checkin-needed&lt;/code&gt;，就會有機器人自己來把你的 patch check in 進 mozilla-inbound 這個 repository，然後丟上機器人自動編譯和測試，例如這個我 B2G build 失敗的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://treeherder.mozilla.org/#/jobs?repo=mozilla-inbound&amp;amp;revision=b1b8616162b4&quot;&gt;例子&lt;/a&gt;，都過了就會進 mozilla-central，之後才&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://wiki.mozilla.org/Tree_Rules&quot;&gt;照順序&lt;/a&gt;進 mozilla-aurora、mozilla-beta、mozilla-release，現在進去 mozilla-central 的大概要等 Firefox 42 才會上線了，應該是和 OSX 10.11 同時吧。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9vuI-4IQApc:pI7Qozx-on8:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9vuI-4IQApc:pI7Qozx-on8:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9vuI-4IQApc:pI7Qozx-on8:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=9vuI-4IQApc:pI7Qozx-on8:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9vuI-4IQApc:pI7Qozx-on8:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/9vuI-4IQApc&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/08/07/first-patch-to-firefox/</guid>
         <pubDate>Fri, 07 Aug 2015 01:06:43 +0000</pubDate>
         <category>web</category>
      </item>
      <item>
         <title>Electron 入門</title>
         <link>http://feedproxy.google.com/~r/othree/~3/fzSh0Lr4ShM/</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/20249299982/&quot; title=&quot;electron by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm1.staticflickr.com/312/20249299982_763c6a25a6_b.jpg&quot; width=&quot;1024&quot; height=&quot;683&quot; alt=&quot;electron&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;前陣子花了些時間用 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/tutorial/quick-start/&quot;&gt;Electron&lt;/a&gt; 寫了個桌面應用程式，覺得有些資訊應該記錄一下，其實我覺得 Electron 的文件弄得超爛的，非常沒有 Github 的水準，Github 當初能夠起來，我認為一個很大的原因就是文件做的很好，而且在頁面上都會提供相對應操作的說明文件，不只讓網站的易用性提昇很多，連帶的也推廣了 Git 的使用，算是相輔相成起來的，不過 Electron 剛推出的時候，我就覺得，這是有文件嗎？甚至讓我有個印像是，我們雖然推出 Electron 但是沒很想讓你們用，所以文件隨便寫寫。&lt;/p&gt;

&lt;p&gt;為什麼這樣說，拿現在最新版 0.3.0 來說，其實這應該只是自動產生的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/&quot;&gt;文件&lt;/a&gt;，整頁的第一篇文章是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/tutorial/application-distribution/&quot;&gt;Application distribution&lt;/a&gt;，這真的沒有哪裡搞錯嗎？而且這份文件還很爛，有關鍵的地方沒說，之後會講。總之，要開始寫 Electron App 應該要看的是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/tutorial/quick-start/&quot;&gt;Quick Start&lt;/a&gt; 才對，這份文件用了一個很簡單的範例讓你開始可以跑 Electron App，只要會寫網頁，從這邊就可以開始做 Electron App，但是一個應用程式哪有這麼單純，只靠 Web 端的技術一定是有不足的，例如我要做的程式就需要讀取 key 去登入 SSH 然後做事情，這登入 SSH 然後做事的部分用的是 node 的 code，不能跑在瀏覽器環境，在 Electron 的架構下，瀏覽器環境稱為 renderer，而另外一邊用來起始 renderer process 的則稱為 main process，要登入 SSH 的 code 就要寫在 main process 這邊，那兩邊要怎麼溝通呢？Electron 提供了 IPC 模組來用。&lt;/p&gt;

&lt;p&gt;IPC 模組應該是稱為 Inter Process Communication 吧，我覺得這在 Electron App 開發當中應該是超重要的一部份，結果在 Quick Start 那篇文章中竟然沒有範例介紹，只有簡單的一句話說如果兩邊要溝通要用這個（或是另外一個 remote 模組），而且點過去也只有 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/api/ipc-renderer/&quot;&gt;API 文件&lt;/a&gt;，沒有範例，後來出的 remote 模組的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/api/ipc-renderer/&quot;&gt;文件&lt;/a&gt;才有範例說明，總之這樣弄來弄去還是有解決兩邊的溝通問題，所以下一個遇到的，就是我要怎麼讓使用者選檔案了。&lt;/p&gt;

&lt;p&gt;因為 Electron 是跨平台的，我的程式設計是用 private key 去登入遠端的機器做事情，Linux 或 OSX 都可以假設 key 的位置，但是 Windows 不行，所以我就要提供可以讓使用者選檔案的功能，這部分文件也是沒有好好的連結，你看完 Quick Start，看一遍文件目錄，其實都看不出來到底要怎麼做到這件事，事實上它被稱為 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://electron.atom.io/docs/v0.30.0/api/dialog/&quot;&gt;dialog&lt;/a&gt;，這不把整份 API 文件翻完真的不知道是放在這名字下面。&lt;/p&gt;

&lt;p&gt;然後，Electron 的 renderer process 端雖然和瀏覽器環境幾乎一樣，不過還是有些差異，一部份是 Chrome 引擎的問題，例如最近的 &lt;code&gt;fetch&lt;/code&gt;，在 renderer process 會受到 CORS 限制，但是 XHR 不會，這是因為 fetch 還沒有檢查 Chrome 的 safety flag，所以如果要用 fetch API 接 ES6 Promise 的話，就要用 Github 的 polyfill，自己把檢查的程式碼拿掉，另外一個類似的問題是，如果要在 renderer process 中，引入第三方的 library，有兩種用法，一個是用新出現的 &lt;code&gt;require&lt;/code&gt; 來引入 npm module，或是像一般網頁一樣，直接用 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 標籤引入 js 檔案，但是就會發生一個問題，因為 jQuery 會判斷現在的環境，然後來決定要不要 expose &lt;code&gt;$&lt;/code&gt; 變數到 global scope 下，剛好，Electron 的環境下，雖然是要當成瀏覽器環境，但是又多了 &lt;code&gt;require&lt;/code&gt; 可以用，結果就是被誤判成在 Node 環境，想當成一般網頁環境用 jQuery 就會找不到 &lt;code&gt;$&lt;/code&gt;，結果也是要自己去修改檢查部分的程式碼。&lt;/p&gt;

&lt;p&gt;最後，把程式功能弄得差不多了，要打包給其他人時，發現竟然無從下手，本文開頭提到的 Application distribution 這份文件說的很簡單，就是把某個目錄換掉就好了，可是真的到了這一步才意識到，是換掉哪裡的目錄？結果只好上網找別人弄好的打包工具，這邊我用的是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.npmjs.com/package/electron-packager&quot;&gt;electron-packager&lt;/a&gt;，研究一下才發現，原來是要抓 Github 上 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/atom/electron/releases&quot;&gt;release&lt;/a&gt; 那的檔案下來處理，整個過程其實還蠻不愉快的，因為根本不是難懂，而是文件作不好造成一堆時間浪費啊。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=fzSh0Lr4ShM:kjlt1Rjk4nM:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=fzSh0Lr4ShM:kjlt1Rjk4nM:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=fzSh0Lr4ShM:kjlt1Rjk4nM:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=fzSh0Lr4ShM:kjlt1Rjk4nM:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=fzSh0Lr4ShM:kjlt1Rjk4nM:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/fzSh0Lr4ShM&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/08/03/electron-intro/</guid>
         <pubDate>Mon, 03 Aug 2015 13:27:43 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>webappsec</title>
         <link>http://feedproxy.google.com/~r/othree/~3/80_uXObUSsI/</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/mujitra/15191563939/&quot; title=&quot;Safety first. by MIKI Yoshihito (&amp;#xb4;&amp;#x00ff65;&amp;#x0003c9;&amp;#x00ff65;), on Flickr&quot;&gt;&lt;img src=&quot;https://farm3.staticflickr.com/2948/15191563939_80db3b1c3c_b.jpg&quot; width=&quot;1024&quot; height=&quot;576&quot; alt=&quot;Safety first.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;這幾天才注意到 W3C 的 Web Application Security Working Group，簡稱為 webappsec，專門負責安全相關的規範制訂，是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.w3.org/2011/webappsec/&quot;&gt;2011&lt;/a&gt; 年就成立的，算是很後知後覺吧，其實現在很多已經很廣為人知的 Web 安全機制都是出自他們之手，像是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://developer.mozilla.org/zh-TW/docs/HTTP/Access_control_CORS&quot;&gt;CORS&lt;/a&gt; 和 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://devco.re/blog/2014/04/08/security-issues-of-http-headers-2-content-security-policy/&quot;&gt;CSP&lt;/a&gt;，然後他們現在也很跟的上潮流，把標準的制訂也移到 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/w3c/WebAppSec&quot;&gt;Github&lt;/a&gt; 上了，其實會發現這個 Github repo 是因為最近在看 fetch 的 spec，裡面多了蠻多內容，而且有不少引用到其它新標準的地方，然後看這看著就看到 webappsec 這邊，順便就看了一下，有幾個新草稿好像還蠻有趣的，想說可以介紹一下，不過這些東西大部分都還不能用就是了。&lt;/p&gt;

&lt;p&gt;第一個是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://w3c.github.io/webappsec/specs/powerfulfeatures/&quot;&gt;Secure Contexts&lt;/a&gt;，這個新東西目的很簡單，就是判斷現在的連線狀況是否安全，以前的話，前端只能看是不是使用 https protocol 連線，不過 Secure Context 有比較多的判斷流程，例如用 SSL 就不會被當成是安全的，要 TLS 才會被認為是安全，如果不是 TLS 連線則還會判斷連到哪裡，看看白名單黑名單之類的機制。&lt;/p&gt;

&lt;p&gt;第二個是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://w3c.github.io/webappsec/specs/credentialmanagement/&quot;&gt;Credential Management&lt;/a&gt;，主要是為了因應現在瀏覽器很多都有記下使用者填的表單資料，包括登入的表單，而這等於是把使用者某個網站的帳號密碼都記錄下來，不過其實瀏覽器要做這些功能也是會遇到很多問題，像是他要怎麼判斷現在的表單是登入表單，哪些欄位是帳號密碼，或是網站用不一樣的機制，例如 XHR 來登入，這樣瀏覽器如果無法知道是什麼機制，就無法替這些特殊機制的網站的使用者提供方便的功能，所以 webappsec 就提出 Credential Management 這個功能讓網站開發者可以透過設計好的介面來告訴瀏覽器他們的網站是怎樣登入的，然後可以儲存帳號密碼在瀏覽器端，之後提供 API 給 JavaScript 呼叫出來送到 Server 端驗證，不過說是呼叫出來，其實 JavaScript 也看不到密碼明碼，而只能直接送出 login 的 request：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;navigator.credentials.get({ &quot;password&quot;: true }).then(
  function(credential) {
    if (!credential) {
      // The user either doesn't have credentials for this site, or
      // refused to share them. Insert some code here to show a basic
      // login form (or, ideally, do nothing, since this API should
      // really be progressive enhancement on top of an existing form).
      return;
    }
    if (credential.type == &quot;password&quot;) {
      credential.send(&quot;https://example.com/loginEndpoint&quot;)
        .then(function (response) {
          // Notify the user that signin succeeded! Do amazing, signed-in things!
        });
    } else {
      // See the Federated Sign-in example
    }
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;這是從 spec 內複製出來的 sample code，一個重點是，JavaScript 程式碼其實碰不到你的密碼，只能直接把 credential send 出去，其它也還支援像是 Facebook 那種第三方登入的設計，以及把 credential 存進 store 等等機制。&lt;/p&gt;

&lt;p&gt;第三個是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://w3c.github.io/webappsec/specs/subresourceintegrity/&quot;&gt;Subresource Integrity&lt;/a&gt;：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;script src=&quot;https://analytics-r-us.example.com/v1.0/include.js&quot;
        integrity=&quot;sha256-Rj/9XDU7F6pNSX8yBddiCIIS+XKDTtdq0//No0MH0AE=&quot;
        crossorigin=&quot;anonymous&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;這是個看範例馬上就能理解幹什麼用的，就是對網頁要用到的其它 resource 檔案包括：js、css 等加上驗證檔案正確性的 hash，為的是避免有第三方的檔案內容被惡意攻擊者修改過。&lt;/p&gt;

&lt;p&gt;第四個是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://w3c.github.io/webappsec/specs/upgrade/&quot;&gt;Upgrade Insecure Requests&lt;/a&gt;，這是唯一目前已經可以用的，為的是解決 mixed content 的問題，也就是有的網站可能最近才改為 HTTPS 連線，但是網站內部用到的一些內容還是寫死 URL 用 HTTP，這時候瀏覽器就會跳出說網頁內容可能不安全，然而，這些使用 HTTP 的檔案其實可能用 HTTPS 連線也找的到，像是 Flickr、TED 等都有支援 HTTPS 連線，而 Upgrade 就是跟瀏覽器說如果這些內容找得到 HTTPS 的就用 HTTPS 的，而不是指看寫死的 URL，目前 Chrome 43 已經開始支援了，有個線上 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://googlechrome.github.io/samples/csp-upgrade-insecure-requests/&quot;&gt;demo&lt;/a&gt; 可以看，設定方法可以透過 CSP header 加上 &lt;code&gt;upgrade-insecure-requests&lt;/code&gt; 或是寫到 meta 標籤裡面（demo 用的）&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;upgrade-insecure-requests&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;其實這個標準我一開始以為是類似 HSTS，是對現在開的網址本身做判斷是不是有 HTTPS 可供選擇，有的話就改用 HTTPS 連線，仔細看之後才發現是用來處理 mixed content ，可是又看一看發現也有一部份比較新的草稿有講到這個功能，目前討論的版本是用 header：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTPS: 1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;很簡潔不過還沒瀏覽器支援就是了。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=80_uXObUSsI:L5Z1v5BFL8k:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=80_uXObUSsI:L5Z1v5BFL8k:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=80_uXObUSsI:L5Z1v5BFL8k:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=80_uXObUSsI:L5Z1v5BFL8k:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=80_uXObUSsI:L5Z1v5BFL8k:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/80_uXObUSsI&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/07/03/webappsec/</guid>
         <pubDate>Fri, 03 Jul 2015 15:13:21 +0000</pubDate>
         <category>web</category>
      </item>
      <item>
         <title>GHCJS</title>
         <link>http://feedproxy.google.com/~r/othree/~3/X2q7Fvw7zuM/</link>
         <description>&lt;p&gt;最近幾天把 GHCJS 研究了一遍，一開始的需求是因為開始用 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://pandoc.org/&quot;&gt;pandoc&lt;/a&gt;，然後想要用 JS 提供即時的預覽，因為 Pandoc 是 Haskell 寫的，所以看下來自然是看到 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ghcjs/ghcjs&quot;&gt;GHCJS&lt;/a&gt; 了，其實網路上以經有人成功的把 Pandoc 轉成 JS 了，叫做 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://markup.rocks/&quot;&gt;markup.rocks&lt;/a&gt;，我後來也是基於他在 github 上公開的這些程式碼來研究。&lt;/p&gt;

&lt;p&gt;要安裝 GHCJS 有點麻煩，以 OSX 為例，要先去&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.haskell.org/ghc/download_ghc_7_8_3#macosx_x86_64&quot;&gt;下載&lt;/a&gt; GHC 的 binary distribution 壓縮檔（ghc-7.8.3-x86_64-apple-darwin.tar.xz），解壓縮後，進目錄執行：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;./cofigure
make install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;安裝完 GHC 後要更新 &lt;code&gt;cabal&lt;/code&gt; 這個套件管理工具：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cabal install cabal-install
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然後這樣會把 cabal 裝到自己 home 目錄下面，所以還要更新一下 $PATH：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;PATH=$HOME/Library/Haskell/bin:$PATH
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;接下來才是安裝 GHCJS：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone https://github.com/ghcjs/ghcjs-prim.git
git clone https://github.com/ghcjs/ghcjs.git
cabal install ./ghcjs ./ghcjs-prim
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;要用 GHCJS 之前，還要安裝一下環境的基本套件：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ghcjs-boot --dev
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如果一切順利的話就可以開始把 Haskell 程式轉成 JS 了，不過事情當然沒這麼簡單，首先 GHCJS 的套件和 GHC 的套件在本地是分開的，要裝給 GHCJS 環境的話，要加上 &lt;code&gt;--ghcjs&lt;/code&gt; 的選項，例如：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cabal install --ghcjs pandoc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;這樣裝的套件才能夠讓 GHCJS 轉譯時使用，然後第二個問題就是上面這個指令其實裝不起來，因為 Pandoc 和 GHCJS 不相容，markup.rocks 的作者 Ozan Sener 其實有 fork 一份 Pandoc 針對這個問題作 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/osener/pandoc&quot;&gt;patch&lt;/a&gt;，所以安裝改成下面的指令：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;git clone git@github.com:osener/pandoc.git
cabal install --ghcjs ./pandoc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;不過還是會有些問題，基本上就看缺什麼用 cabal 裝一下，然後有些錯誤要簡單修改一下程式碼，詳情不是很重要，因為接下來馬上有第三個問題，就是這樣裝起來後，會發現要成功的轉 markup.rocks 還是有問題，其中 reflex-dom 一直裝不起來，這個套件主要是拿來做網頁介面的，所以我把 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/osener/markup.rocks/blob/master/src/Main.hs&quot;&gt;Main.hs&lt;/a&gt; 內只和 pandoc 相關的抽出來，想建立一個只有 pandoc 單純一點的 Haskell 程式，然後一番努力後，終於成功了，這時同時出現兩個問題，第一個是產出的檔案超大，有 20MB 左右，markup.rocks 線上 demo 放的是有過 closure-compiler 的也還有 2.2MB，而另外一個問題，是我找不到程式可以讓我抓到輸出入的位置（嚴格來說有找到但是無法用），後來又查了些資料才發現，GHCJS 目前還沒辦法把 Haskell library 單獨轉譯然後開 API 出來，一定是一個完整的 Haskell 應用程式，然後編譯出來的 JS 就是執行這個程式，沒有外面插手的餘地，換句話說，就是所有事情都要用 Haskell 完成，然後用 GHCJS 編譯成一個獨立的 JavaScript 應用程式，GHCJS 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ghcjs/ghcjs/issues/194&quot;&gt;Issue 194&lt;/a&gt; 就是在講這個問題，看起來離有結果還有些距離。&lt;/p&gt;

&lt;p&gt;總之結論是，目前 GHCJS 還不到真的可拿來做應用的程度，最後遇到的兩個問題算是比較大的，就是輸出檔案太大和只能把整個應用程式轉譯成 JS 這兩個問題，不過事情總是要有開始，希望未來有一天這兩個問題能解決，就能夠把 Haskell 的一些工具轉到 JS 上了。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=X2q7Fvw7zuM:kxTbBu1GvLU:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=X2q7Fvw7zuM:kxTbBu1GvLU:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=X2q7Fvw7zuM:kxTbBu1GvLU:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=X2q7Fvw7zuM:kxTbBu1GvLU:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=X2q7Fvw7zuM:kxTbBu1GvLU:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/X2q7Fvw7zuM&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/06/18/ghcjs/</guid>
         <pubDate>Wed, 17 Jun 2015 16:08:03 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>TypeScript, AtScript, ES Decorator</title>
         <link>http://feedproxy.google.com/~r/othree/~3/9C4_U9os_Gk/</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/16813714825/&quot; title=&quot;AtScript by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm8.staticflickr.com/7639/16813714825_e15ff55b8b_b.jpg&quot; width=&quot;1024&quot; height=&quot;573&quot; alt=&quot;AtScript&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;前陣子花了些時間研究了 TypeScript 和一些相關的發展，包括了 Google Angular Team 的 AtScript 和推進 ES 標準的部分，會開始感興趣深入研究主要是因為 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blogs.msdn.com/b/typescript/archive/2015/03/05/angular-2-0-built-on-typescript.aspx&quot;&gt;Angular 2 說改用 TypeScript 寫&lt;/a&gt;，好奇為什麼會有這樣的發展才下去搜尋資料的，這篇文章算是記錄用的，不過其實離寫好已經一陣子了，因為剛好遇到 Modern Web Conf，想說拿這題目去分享，就讓文章晚點上線了，後來投影片還有補充些內容，這篇文章就沒再更新了，所以兩邊會有些差異就是～&lt;/p&gt;

&lt;p&gt;ECMAScript 標準一直以來都是動態型別的，雖然資料有不同的型別，但是變數本身是沒限制型別的，而在 ECMAScript 發展的過程中，靜態型別第一次出現是在已經被廢棄的 ECMAScript 4 裡，網路上還可以找到一些&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.ecmascript.org/es4/spec/overview.pdf&quot;&gt;資料&lt;/a&gt;，可以看看當時設計的語法，和現在常看到的 &lt;code&gt;:type&lt;/code&gt; 的寫法很接近，後來這個設計也在 ActionScript 3 中被使用，微軟現在的 TypeScript 也是用這種寫法。那加入靜態型別的特性會有什麼好處呢，我認為有兩個主要的優點，第一個是可以讓程式碼更可靠，減少一些 bug 發生的機會，對於大型專案來說，多了這個限制的差距是蠻大的，另外一個優點則是 JS Engine 更好最佳化，以前也有提過現在的 V8 引擎就已經會判斷變數的型別會不會有變化來做最佳化了。&lt;/p&gt;

&lt;p&gt;或許是因為微軟對於大型專案開發的關注比較多吧，他們於 2012 年推出了 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;，為 JavaScript 加入了靜態型別，用的語法很簡潔：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var i:int;
var message:string;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;另外還提供了當時沒有的 class 和之前提過的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://blog.othree.net/log/2014/12/04/typescript-definition/&quot;&gt;定義檔&lt;/a&gt;等東西，TypeScript 一開始是基於 ECMAScript 5 設計的，不過在 ECMAScript 6 差不多定案後，微軟也開始著手把 ES5 based 改成 ES6 based，像是 class 就會改用 ES6 原生的，而 TypeScript 所提供的靜態型別檢查功能其實是靜態分析而已，也就是只有在把 .ts 檔案編譯成 .js 檔案時會做檢查，而由於 JavaScript 還沒有 type 的特性，所以這些型別的資訊其實在編譯過後都會被拿掉。目前除了 AngularJS 2 改用 TypeScript 之外，還有像 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://eng.asana.com/2014/11/asana-switching-typescript/&quot;&gt;Asana&lt;/a&gt; 和 Mozilla 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/mozilla/shumway&quot;&gt;Shumway&lt;/a&gt; 都是用 TypeScript。&lt;/p&gt;

&lt;p&gt;Google Angular Team 似乎對此還不夠滿足，因此他們開始發展 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.atscript.org/&quot;&gt;AtScript&lt;/a&gt;，在 TypeScript 上再加入 annotation 的功能，名稱的 At 代表的是 &lt;code&gt;@&lt;/code&gt; 這個符號，因為這個符號是很多語言寫 annotation 用的符號，自然 AtScript 也是用這個符號來標記 Annotation：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@Component({selector: 'foo'})
class MyComponent {
  @Inject()
  constructor(server:Server) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Annotation 簡單翻起來也是註解，不過他和 comment 不一樣，不是給人看，而是要給 compiler 和 JS engine 看的，而且實際上也會影響程式的一些運作，annotation 應該是一種完全沒有也不影響程式執行的 metadata，不過細分下去應該可以分為兩類，第一種是 Java 的 annotation，以 metadata 為主，像是物件的角色、物件間關係等，另外一種則是 decorator annotation，可以讓函數加上各種不同特性，其實就是 decorator pattern 的簡易語法，看到一些範例當中，最讓我覺得厲害的就是 memorize 了吧，如果程式引擎支援，加上一行 memorize 的 annotation 就可以讓那個函數自動有 memorize 特性，如果使用不支援此特性的引擎來執行程式，函數的輸出也不會有錯，就是沒有 memorize 的效果，效率會比較差，Python 中就有 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://docs.python.org/3/library/functools.html#functools.lru_cache&quot;&gt;lru_cache&lt;/a&gt; 這個 decorator 可以做到這樣的效果（Python 的 decorator 語法是提供 syntax sugar，不過寫法和其它語言的 annotation 很像）:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@lru_cache(maxsize=None)
def fib(n):
    if n &amp;lt; 2:
        return n
    return fib(n-1) + fib(n-2)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;AtScript 一個很重要的原則是這些附加的資訊，都要在 runtime 可以使用，所以就不像 TypeScript 那樣只是把不支援的東西拿掉而已，像上面費氏數列的程式碼如果改用 AtScript 寫會變成：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;@lru_cache()
function fib(n) {
  if (n &amp;lt; 2) { return n; }
  return fib(n - 1) + fib(n - 2);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然後用 AtScript compiler 編譯過後會多上一段程式碼做類似下面的事情：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;fib.annotations = [
  new lru_cache(),
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;這個 &lt;code&gt;annotations&lt;/code&gt; 屬性在 runtime 時就是可以取用的資訊，目前 AtScript 的 annotation  就是比較偏重於 metadata 而不是 decorator，所以這些資料並不會直接讓函數有不同特性，而 AtScript 另外一個新東西 introspection 也是和 runtime 有關，是 TypeScript 所沒有的 runtime 時的型別檢查，JavaScript 要怎樣做執行階段的型別檢查呢？沒錯，基本上就是土法煉鋼，不過 AtScript 是引入一個 rtts（run time type assertion） 的 library 來做這件事，目前主要也是用 Angular Team 維護的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://angular.github.io/assert/&quot;&gt;assert.js&lt;/a&gt;，本來的 fib 再改寫一下：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function fib(n:number):number {
    if (n &amp;lt; 2) { return n; }
    return fib(n - 1) + fib(n - 2);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然後編譯過後大概會變成：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function fib(n) {
  assert.argumentTypes(n, number);
  if (n &amp;lt; 2) {
    return assert.returnType((n), number);
  }
  return assert.returnType((fib(n - 1) + fib(n - 2)), number);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;可以看到不管是在函數開頭還是要回傳之前，都會多了用 assert.js 做型別檢查的程式碼，當然，多做的這些型別檢查是會造成效能影響的，所以 AtScript 把 runtime 的型別檢查分成兩個階段，開發階段和成品階段，成品階段，要上線的時候，就輸出不包含型別檢查的 js 程式碼，這樣就不會影響效能。AtScript 其實目前沒有自己的編譯器，而是使用 Google 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/google/traceur-compiler&quot;&gt;Traceur&lt;/a&gt;，Traceur 基本上是個 ES6 to ES5 compiler，不過實際上他還多一些非 ES6 標準的語法支援，包括了前面提到的 Type、Annotation，不過使用時要加些參數：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;traceur --annotations true --type-assertions --types true fib.ats --out fib.js
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;在 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://ngeurope.org/&quot;&gt;ng-europe&lt;/a&gt; 研討會，就有一場關於 AtScript 的演講：&lt;/p&gt;

&lt;div class=&quot;embed_16_9&quot;&gt;
 
&lt;/div&gt;

&lt;p&gt;裡面除了基本的介紹，為什麼會發展 AtScript 之外，還有很重要的未來發展，Angular Team 是有打算把 Type、Annotation 等等特性推回 ECMAScript 未來的標準之中的。在 ECMAScript 標準的發展上，其實早在之前就有一些變數型別相關的功能在討論，包括了 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wiki.ecmascript.org/doku.php?id=strawman:types&quot;&gt;type&lt;/a&gt;、&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wiki.ecmascript.org/doku.php?id=strawman:guards&quot;&gt;guard&lt;/a&gt;，不過都沒有進到目前的 ECMAScript 6(2015)，目前 AtScript 和 TypeScript 兩者正在逐漸互相同步，也有共同合作，而且 AtScript 還沒有嚴謹的 spec 文件，所以會看到官方發佈說 AngularJS 2 用 TypeScript 開發，而不是用 AtScript，目前看到 TC39 討論裡面，除了 type 之外，幫其它新東西提出 proposal 的，很令人意外，竟然是 Yehuda Katz，可以看到去年四月的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/rwaldron/tc39-notes/blob/master/es6/2014-04/apr-10.md#decorators-for-es7&quot;&gt;會議記錄&lt;/a&gt;就有他提出 decorator 特性的討論，另外 TypeScript 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/Microsoft/TypeScript/issues/1557#issuecomment-77709527&quot;&gt;Issue 1557&lt;/a&gt; 是關於在 TypeScript 中加入 AtScript 的 annotation 支援，Yehuda Katz 也有提到他正在整理相關資料，幾週後會在 TC39 會議提出，在他的 github 帳號上也可以找到相關的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/wycats/javascript-decorators&quot;&gt;資訊&lt;/a&gt;，我個人對 Yehuda Katz 評價很高，不過實在是想不太到為什麼會是他跑出來推動這部分的發展，不過總之 Yehuda Katz 打算提出的是比現在 metadata 為主更進一步的 annotation，也就是包含像 Python decorator 特性的 annotation，如果真的順利成案，其實也不知道是好是壞，好的是一些程式碼可以更簡潔，壞的是 JavaScript 語法越來越多，入門要學的東西也變多很多。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9C4_U9os_Gk:CtpwPjL97X0:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9C4_U9os_Gk:CtpwPjL97X0:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9C4_U9os_Gk:CtpwPjL97X0:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=9C4_U9os_Gk:CtpwPjL97X0:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=9C4_U9os_Gk:CtpwPjL97X0:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/9C4_U9os_Gk&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/05/18/typescript-atscript-es-decorator/</guid>
         <pubDate>Mon, 18 May 2015 10:24:37 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>TypeScript 過去、現在、未來</title>
         <link>http://feedproxy.google.com/~r/othree/~3/3rTHWFsHaug/</link>
         <description>&lt;p&gt;今年 Modern Web Conf 的投影片喔，其實整份演講最重要的點就是 type 看來就是會進入 ECMAScript 了。&lt;/p&gt;

&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=3rTHWFsHaug:UVJM3YnRa7g:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=3rTHWFsHaug:UVJM3YnRa7g:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=3rTHWFsHaug:UVJM3YnRa7g:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=3rTHWFsHaug:UVJM3YnRa7g:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=3rTHWFsHaug:UVJM3YnRa7g:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/3rTHWFsHaug&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/05/16/typescript-future-and-past/</guid>
         <pubDate>Sat, 16 May 2015 07:03:02 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>Aster 與 PostCSS</title>
         <link>http://feedproxy.google.com/~r/othree/~3/yOKvJZCJLAs/</link>
         <description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/17133620000/&quot; title=&quot;&amp;#x0053f0;&amp;#x005357; by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm8.staticflickr.com/7771/17133620000_64aac917c8_b.jpg&quot; width=&quot;1024&quot; height=&quot;683&quot; alt=&quot;&amp;#x0053f0;&amp;#x005357;&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;前端為了 performance 需求，把網站推上 server 時會需要把 JavaScript、CSS 之類的文字檔案合併和最小化，如果開發時寫的是 CoffeeScript 或是 SASS 之類的還需要先轉成 JavaScript 和 CSS 這些主流格式，要做這些動作其實第一個想到的是可以用 Makefile，優點是常見、各平台都有，不過寫起來並不像這幾年流行的 build tool 那樣直覺，而前端領域流行的主要是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt; 和 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://gulpjs.com/&quot;&gt;Gulp&lt;/a&gt; 這兩個，兩者之中我個人是比較喜歡後起的 Gulp，不過前陣子意外發現一個看起來超正確的 build tool，叫 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://asterjs.github.io/aster/&quot;&gt;aster&lt;/a&gt;，是 Ingvar Stepanyan 做的，他在 Zurich 的 Frontend Conference 2014 的演講算是比較大規模的發佈：&lt;/p&gt;

&lt;div class=&quot;embed_16_9&quot;&gt;
 
&lt;/div&gt;
&lt;p&gt;Aster 這個名稱的來由是 AST，Aster 的特別之處就在於他所有的修改都是在 AST 上做修改：&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/17141309009/&quot; title=&quot;Aster by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm8.staticflickr.com/7680/17141309009_fac4a51d86_b.jpg&quot; width=&quot;1024&quot; height=&quot;640&quot; alt=&quot;Aster&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;相較於 Gulp：&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/17327152261/&quot; title=&quot;Aster by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm8.staticflickr.com/7662/17327152261_6de37ae977_b.jpg&quot; width=&quot;1024&quot; height=&quot;640&quot; alt=&quot;Aster&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;和 Grunt：&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/17327152081/&quot; title=&quot;Aster by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm8.staticflickr.com/7717/17327152081_7bd3f29f74_b.jpg&quot; width=&quot;1024&quot; height=&quot;640&quot; alt=&quot;Aster&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;很明顯的是正確許多的設計，理論上 parse 成 AST 之後，一口氣在 AST 階段把需要的變更做完，然後再用 code generator 產生成果的程式碼，應該省去很多來回轉換的工作，不論是效能還是程式碼處理的正確性都應該是最好的，不過這看似正確設計下的產品，卻沒什麼人用，我嘗試使用過程中還發了幾個 PR 回去，結果到現在都還沒有回應，有種是不是作者都已經放棄的疑問。&lt;/p&gt;

&lt;p&gt;然後這兩天，又看到一個其實已經出來蠻久的 compile to CSS language，叫 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/postcss/postcss&quot;&gt;PostCSS&lt;/a&gt;，號稱比 SASS 之類的快上 3-30 倍，還可以做到一些 SASS/LESS 做不到功能，也有很多大企業採用，像是 Google、VK、Alibaba 之類的，應該就是目前最夯的 CSS 工具，然後我看介紹的投影片看到這張：&lt;/p&gt;

&lt;p&gt;&lt;a rel=&quot;nofollow&quot; class=&quot;thumbnail&quot; target=&quot;_blank&quot; href=&quot;https://www.flickr.com/photos/othree/17301590026/&quot; title=&quot;PostCSS by othree, on Flickr&quot;&gt;&lt;img src=&quot;https://farm8.staticflickr.com/7763/17301590026_184c69e66f_b.jpg&quot; width=&quot;1024&quot; height=&quot;638&quot; alt=&quot;PostCSS&quot;/&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;覺得，這根本和 Aster 是一樣的想法，不過一個處理 JavaScript，做 ES6 to ES5、concat、minimize 甚至是細微的程式碼修改，另外一個處理 CSS，也是做類似的工作，為什麼結果發展的差距會這麼大？想了一陣子之後，我覺得大概狀況是，SASS、LESS 之類的工具目前還是會造成一些讓開發者痛苦的問題，像是 nesting rule 讓 selector 太長太複雜、mixin 和 include 的混淆等等，所以開發者還會一直嘗試不同的新工具，甚至自己開發來解決這些問題，而相對於 CSS，JavaScript 的相關工具比較沒這些問題，二來 JavaScript 的 AST 比 CSS 的 AST 要複雜許多，要參與工具的開發難度是高上許多，Aster 作者的功力還蠻強的，除了 AST 操作之外，他的整個流程控制還用上很先進的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://rxjs.codeplex.com/&quot;&gt;RxJS&lt;/a&gt;，其實也算是增加了參與的難度吧，而我想就是這沒有強烈需求加上進入難度高兩點，結果讓 Aster 並不太受到人注意，沒什麼人參與，開發的完整度不夠，我實際用起來，就覺得目前還只是核心完整，但是真的要離實用到專案上還有些距離，加上不知道還有沒有要繼續發展下去，覺得實在很可惜。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=yOKvJZCJLAs:bxZSawhkzos:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=yOKvJZCJLAs:bxZSawhkzos:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=yOKvJZCJLAs:bxZSawhkzos:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=yOKvJZCJLAs:bxZSawhkzos:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=yOKvJZCJLAs:bxZSawhkzos:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/yOKvJZCJLAs&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/05/02/aster-postcss/</guid>
         <pubDate>Sat, 02 May 2015 03:35:38 +0000</pubDate>
         <category>web</category>
      </item>
      <item>
         <title>React.js Conf</title>
         <link>http://feedproxy.google.com/~r/othree/~3/AZ_zOAdJ7tg/</link>
         <description>&lt;p&gt;今年的 React.js Conf 雖然是單一 library 的研討會，不過議程的水準卻是蠻高的，而且蠻多內容並不是只限於 React.js，加上也是對於前端領域一些比較新的概念，所以我覺得是這兩年最讓人感到印象深刻的一場研討會了吧，下面介紹幾場我覺得收穫比較多的講題：&lt;/p&gt;

&lt;h4&gt;React Native&lt;/h4&gt;

&lt;p&gt;React Native 是 React.js 最近最重大的發展，把本來抽出來的 DOM 底層換成 native app 的操作，原來寫 JavaScript 的開發者就可以直接用寫 React.js App 的方式來做原生介面的 Mobile App，發表時讓很多人眼睛一亮，沒想到會把 React.js 的 Virtual DOM 這樣用，而表現出來的效果也很讓人滿意，因為是用原生的控制元件，也不會有額外的親和力問題，加上現有的很多 JavaScript Library 都可以用，也不會有太多東西要自己從頭開始，&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://cordova.apache.org/&quot;&gt;Apache Cordova&lt;/a&gt; 的 plugin 也都可以使用，最近也正式對外&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://facebook.github.io/react-native/&quot;&gt;公開&lt;/a&gt;了，有興趣的可以試試看。&lt;/p&gt;

&lt;div class=&quot;embed_16_9&quot;&gt;
 
&lt;/div&gt;

&lt;h4&gt;CSP&lt;/h4&gt;

&lt;p&gt;之前我也有介紹過的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://blog.othree.net/log/2015/02/14/csp/&quot;&gt;CSP&lt;/a&gt;，在 React.js Conf 也有講者介紹，雖然我覺得現在用 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ubolonton/js-csp&quot;&gt;js-csp&lt;/a&gt; 來做 Channel 溝通還不是很好用，不過應該 async function 可以用之後會比較普遍吧，就算之後沒真的派上用場，要是轉行寫 Go 也會用的上才是。&lt;/p&gt;

&lt;div class=&quot;embed_16_9&quot;&gt;
 
&lt;/div&gt;

&lt;h4&gt;Immutable&lt;/h4&gt;

&lt;p&gt;Immutable Data 已經聽說很久了，不過這場演講算是讓我第一次真的能有些體會到底優點在哪，雖然 Facebook 有 JavaScript 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://facebook.github.io/immutable-js/&quot;&gt;Immutable library&lt;/a&gt; ，不過這場主要是在介紹資料結構的特性，而不是在介紹自家 library，如果對他們底層如何實做的話還可以看看 Polymatheia 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://hypirion.com/musings/understanding-persistent-vector-pt-1&quot;&gt;Understanding Clojure's Persistent Vectors&lt;/a&gt; 系列文章，單純要實做 Immutable Data 並不難，不過要考慮到不對效能產生影響其實還要考慮蠻多細節的，我後來也嘗試實做了一個 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/othree/immutable-quadtree-js&quot;&gt;Immutable Quad Tree&lt;/a&gt;，做的過程中則更實際的體會到所謂的只要簡單的 &lt;code&gt;==&lt;/code&gt; 比對就可以知道資料是否相同的好處。另外還要補充一點，Immutable Data 可能在下一版的 ES7(2016) 也會有，總之又是個先學起來不吃虧的。&lt;/p&gt;

&lt;div class=&quot;embed_16_9&quot;&gt;
 
&lt;/div&gt;

&lt;h4&gt;AST&lt;/h4&gt;

&lt;p&gt;這場演講是在講修改 Abstract Syntax Tree 來做一些程式碼的修改，算是把 AST 的應用講得很淺顯易懂的一場演講，還順便介紹到很多相關的工具，像是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/estools&quot;&gt;estools&lt;/a&gt;，其實一個程式語言的 spec 通常只有定到語法的部分，後面 compiler 要產生什麼樣子的 AST 是他們自己決定的，不過通常會有個主流的格式，而目前 JavaScript 領域則是 Mozilla SpiderMonkey 的 AST 格式為主，不過其實因為應用太多，也有人在做標準化的工作，叫 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/estree/estree&quot;&gt;estree&lt;/a&gt;。&lt;/p&gt;

&lt;div class=&quot;embed_16_9&quot;&gt;
 
&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=AZ_zOAdJ7tg:3Yb7xUwxArE:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=AZ_zOAdJ7tg:3Yb7xUwxArE:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=AZ_zOAdJ7tg:3Yb7xUwxArE:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=AZ_zOAdJ7tg:3Yb7xUwxArE:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=AZ_zOAdJ7tg:3Yb7xUwxArE:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/AZ_zOAdJ7tg&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/04/25/reactjs-conf/</guid>
         <pubDate>Sat, 25 Apr 2015 07:41:59 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>srcset</title>
         <link>http://feedproxy.google.com/~r/othree/~3/w5SJRGTClv4/</link>
         <description>&lt;p&gt;Responsive Image 大概定案成 &lt;code&gt;srcset&lt;/code&gt; 和 &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; 都有了，src-N 已經消失，雖然我還蠻喜歡，不過總之最近發現 &lt;code&gt;srcset&lt;/code&gt; 和我當初&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://blog.othree.net/log/2012/12/02/srcset/&quot;&gt;介紹&lt;/a&gt;時已經差蠻多，中文資源有找到 Zhusee 有另外一篇&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://blog.zhusee.in/post/248199/basic-responsive-image-with-srcset-property&quot;&gt;介紹&lt;/a&gt;，不過其實我去看現在的 spec 的時候發現，又有些修改了！最早 srcset 後面是用類似 media query 的設計，後來改成對圖片的 metadata，spec 裡面稱為 descriptor，分別有 width descriptor 用 &lt;code&gt;w&lt;/code&gt; 和 density descriptor 用 &lt;code&gt;x&lt;/code&gt;，而且限制 srcset 裡面只能用同一種 descriptor，例如全部用 &lt;code&gt;x&lt;/code&gt; 或是全部用 &lt;code&gt;w&lt;/code&gt;，所以：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;不能在一張圖片裡面同時有 &lt;code&gt;w&lt;/code&gt; 和 &lt;code&gt;x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;全部都用 &lt;code&gt;w&lt;/code&gt; 或是全部都用 &lt;code&gt;x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;不可有相同的數值，例如兩個 &lt;code&gt;1x&lt;/code&gt; 或是兩個 &lt;code&gt;760w&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Descriptor 可以算是該圖片的資訊&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不過最新的 spec 裡面少了第二點的限制，所以會有一組 srceset 混和 width descriptor 和 density descriptor 的情形，然後怎麼挑選圖片的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://html.spec.whatwg.org/multipage/embedded-content.html#select-an-image-source&quot;&gt;地方&lt;/a&gt;寫說：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;In a user agent-specific manner, choose one image source from source set. Let this be selected source.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;就是叫瀏覽器自己想辦法的意思，我就很好奇，如果我想設定一組規則，要分成四個組合：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;小螢幕低密度&lt;/li&gt;
&lt;li&gt;小螢幕高密度&lt;/li&gt;
&lt;li&gt;大螢幕低密度&lt;/li&gt;
&lt;li&gt;大螢幕高密度&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;的話，我要怎樣設定 srcset 才能達到目標，因為現在已經不是用 media query 來寫 srcset 了，不能直接寫這樣四組，所以我就去找了 Firefox 和 Chromium 的原始碼來看看他們怎麼做的，Firefox 的找沒多久就&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://dxr.mozilla.org/mozilla-central/source/dom/base/ResponsiveImageSelector.cpp#274&quot;&gt;找到&lt;/a&gt;了，因為他們有 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/mozilla/dxr&quot;&gt;dxr&lt;/a&gt; 專案用來方便找程式碼，實際用過覺得真的好用，至於 Chromium 就找比較久了，後來是在 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/WebKit/webkit/blob/master/Source/WebCore/html/parser/HTMLSrcsetParser.cpp#L232&quot;&gt;WebKit 裡面&lt;/a&gt;有找到，然後發現兩個瀏覽器的原理其實都一樣，要處理同時有 width descriptor 和 density descriptor 的狀況，基本上就是都轉成 density 然後來挑最適合的，作法大致如下，細節可能有誤：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;先對圖片標籤排版，這邊可能會用到 &lt;code&gt;sizes&lt;/code&gt; 屬性，不過 CSS 還是優先，然後會得到圖片在頁面上的寬度，稱為 computed width&lt;/li&gt;
&lt;li&gt;對每張候選圖片計算 effective pixel density，算法是： &lt;code&gt;圖片寬度 / computed width&lt;/code&gt;，圖片寬度可以是 width descriptor 來的或是圖片的實際寬度，如果 descriptor 是 density descriptor 的話就不用計算，直接拿來用&lt;/li&gt;
&lt;li&gt;比對 effective pixel density 和現在 device 螢幕的 density，取最接近的&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;其中第三步驟的比較，大概是考慮效能和記憶體問題，兩個瀏覽器都沒真的做很嚴謹，都是照順序跑過一遍而已，所以在寫 srcset 的時候建議也要照圖片的大小排，至於要大的先還是小的先，就看開發者希望是 density 略大的優先還是略小的優先了，所以如果我寫：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;srcset=&quot;aaa.jpg 1x, bbb.jpg 1.4x, ccc.jpg 1.6x, ddd.jpg 2x&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然後我現在圖片需要 &lt;code&gt;1.5x&lt;/code&gt; 的話，應該就會拿到 1.4x 的 &lt;code&gt;bbb.jpg&lt;/code&gt;，而如果我偏好用 1.6x &lt;code&gt;ccc.jpg&lt;/code&gt; 的話，就要改成：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;srcset=&quot;ddd.jpg 2x, ccc.jpg 1.6x, bbb.jpg 1.4x, aaa.jpg 1x&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;後來發現這個挑選圖片的原則，其實在 WHATWG 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://html.spec.whatwg.org/multipage/embedded-content.html#embedded-content&quot;&gt;HTML Spec 裡面有寫&lt;/a&gt;，不過是 non-normative 的段落，就是說這不是一定要遵守，只是建議，而且前面也有提到 spec 內是寫說挑選的原則是瀏覽器自己處理，而會這樣設計相信是為了像 mobile device 之類的裝置，網路速度如果比較慢，或是需要節省流量時，就可以挑選比較小的檔案，而不一定是挑出顯示上最好的那張圖片。&lt;/p&gt;

&lt;p&gt;最後，其實 descriptor 除了 density 和 width 兩種之外，還有一種 height descriptor，不過目前只是保留可能性，spec 還沒定義要怎樣處理，其實還蠻能理解目前會以寬度為主的狀況，在 Matt Brubeck 的 Let's build a browser engine! 系列文章中的第六篇「&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://limpet.net/mbrubeck/2014/09/17/toy-layout-engine-6-block.html&quot;&gt;Block layout&lt;/a&gt;」這篇文章有介紹到一般瀏覽器是怎樣排版畫 layout 的，而其處理的原則就是先從左上角開始把東西往右排，所以寬度一定先決定，然後才決定高度，相信這也是垂直置中搞這麼多年的原因吧。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=w5SJRGTClv4:0M0tJgbByBU:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=w5SJRGTClv4:0M0tJgbByBU:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=w5SJRGTClv4:0M0tJgbByBU:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=w5SJRGTClv4:0M0tJgbByBU:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=w5SJRGTClv4:0M0tJgbByBU:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/w5SJRGTClv4&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/04/08/more-on-srcset/</guid>
         <pubDate>Tue, 07 Apr 2015 16:53:33 +0000</pubDate>
         <category>css-html</category>
      </item>
      <item>
         <title>Loader</title>
         <link>http://feedproxy.google.com/~r/othree/~3/6uPZzFIHQv4/</link>
         <description>&lt;p&gt;Loader 是 ECMAScript 定義要來處理 module import/export 等等事情的底層介面，ES6 的 module 我一直都很好奇，到底要怎麼去找 import 進來模組的原始碼，會好奇這點是因為如果是網頁環境，所有其它模組的原始碼一定是在遠端的 server 上，要拿到勢必是一個 request，然後還要等下載，總之就是非同步的流程，以前在 ES5 的話，要做非同步控制大概就是要做成 callback 的形式，所以會有像 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/amdjs/amdjs-api/blob/master/AMD.md&quot;&gt;AMD&lt;/a&gt; 那樣的設計出來，加上 module 名稱和檔案名稱可能又有差別，像是差個副檔名之類的，而 ES6 提供了原生的 import/export 語法來定義 module，所以我就很好奇它的底層要怎樣設計才能標準化。&lt;/p&gt;
&lt;p&gt;Addy Osmani 有建立一個 Loader 的 polyfill 給 ES5 環境使用 Loader API，就叫做 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/ModuleLoader/es6-module-loader&quot;&gt;ES6 Module Loader Polyfill&lt;/a&gt;，這個 polyfill 內部實做是照當初 ES6 draft 來寫的，其實還蠻複雜，不過把讀取一個 module 的事情拆分一下，可以分成以下幾個步驟：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Normalize：根據給的名稱取得實際的 module name&lt;/li&gt;
&lt;li&gt;Locate：根據實際的 module name 取得 module 的位置&lt;/li&gt;
&lt;li&gt;Fetch：根據 module 位置去取得檔案內容&lt;/li&gt;
&lt;li&gt;Translate：如果有需要對檔案內容作任何修改，就在這裡處理&lt;/li&gt;
&lt;li&gt;Instaniate：最後是根據檔案內容（程式碼），判斷有哪些相依模組和知道如何初始化這個模組&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以上幾個步驟是屬於 Loader 可自訂化的部分，到 instaniate 完成後，Loader 就繼續去讀其它相依的模組，相依模組都準備好之後，就可以使用模組的的程式碼，正式的把模組建立起來，ES spec 細部還定義了很多實做細節，像是非同步的操作都是用 Promise 來做流程控制，還有 Loader 也有個 module 的 registry 可以來保存已經讀好的模組，就不用一直重新建立，另外還有一些內部溝通的資料結構，像 instaniate 步驟要回傳一個物件，裡面有兩個屬性分別是 &lt;code&gt;deps&lt;/code&gt; 和 &lt;code&gt;execute&lt;/code&gt;， &lt;code&gt;deps&lt;/code&gt; 是相依模組名稱的陣列， &lt;code&gt;execute&lt;/code&gt; 則是該模組本身的初始化函數，參數的數量要剛好和相依模組數量一樣，回傳的則是 Module 物件等等。&lt;/p&gt;

&lt;p&gt;其實目前的 ES6 spec draft 已經把 Loader 拿掉了，TC39 決定把他獨立出來，目前是 WHATWG 接手&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/whatwg/loader&quot;&gt;繼續&lt;/a&gt;，最新的版本已經改很大了，看起來感覺有簡化不少，不過上面的五個步驟基本上還是存在，我一開始看到這五個步驟加上說可以自訂還沒什麼感覺，只是覺得奇怪為什麼細節沒寫，沒錯，這五個步驟在 spec draft 都只有介紹目的，不像其它的操作有詳細的寫出 method 內的流程，關鍵的地方就在於 JavaScript 已經不是單純只是在瀏覽器上跑的語言了，把這部分抽象化就是為了讓它可以同時在瀏覽器環境和單機環境下都可以實做，根據不同的 JS 環境去實做相對應的步驟細節，像是 &lt;code&gt;fetch&lt;/code&gt; 在瀏覽器下就是真的用 fetch 去拉檔案，但是在 node 下就變成讀檔案，而在 ES6 Module Loader Polyfill 下，就有實做一組瀏覽器環境下的操作，不過這組操作的實做未來也不會真的進到瀏覽器內，最大的問題在於第五個步驟的 instaniate。&lt;/p&gt;

&lt;p&gt;Instaniate 這個步驟是要實做 ES6 module 一個很關鍵的部分，關鍵之處在於要把 module 的 dependency 找出來，在 ES6 module 裡面，有一個限制是每個 module 都必須要獨立一個檔案，所以不能一個檔案定義兩個 module，然後假設瀏覽器已經支援 ES6 module 了，只要 parse 程式碼成 AST 找出裡面的 &lt;code&gt;import&lt;/code&gt; 就可以把 dependency 列出來。不過現在是 polyfill，瀏覽器也還不支援 &lt;code&gt;import&lt;/code&gt;，所以要實做 instaniate 自然需要能處理這個問題，ES6 Module Loader Polyfill 的作法是使用 transpiler，目前支援 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/google/traceur-compiler&quot;&gt;Traceur&lt;/a&gt; 和 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://babeljs.io/&quot;&gt;Babel&lt;/a&gt;，把本來用 &lt;code&gt;import&lt;/code&gt; 、 &lt;code&gt;export&lt;/code&gt; 寫的模組轉成用類似的 AMD 模組定義的型式，而這邊用的型式是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/systemjs/systemjs&quot;&gt;systemjs&lt;/a&gt; 裡面提供的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/systemjs/systemjs/blob/master/lib/extension-register.js&quot;&gt;System.register&lt;/a&gt;，這個方法本身並不是 ES spec 裡面定義的，比較像是為了處理這尷尬時間點所設計的替代方案。&lt;/p&gt;

&lt;p&gt;本來我是想看看，是不是能夠只靠 Loader 就把 ES6 的 module 機制在現在的瀏覽器上建立起來，結果發現只靠 ES6 Module Loader Polyfill 是辦不到的，Loader API 並沒有定義模組的語法，如果用 ES6 的語法來定義模組還需要 transpiler 來從程式碼中分析出 module dependency，不過我不太想要把整包 transpiler 也放到 translate 裡面用，雖然可以自己寫一個什麼事情都不做的 translate function，但是要解決 dependency 的話還是會需要像 &lt;code&gt;System.register&lt;/code&gt; 的幫助，總之到這邊，可以發現一個重點是，Loader 不管 module 定義的方法，雖然假想情境下是用 ES6 module 語法，每個檔案代表一個 module，然後用 &lt;code&gt;import&lt;/code&gt; 和 &lt;code&gt;export&lt;/code&gt; 來定義相依模組和提供的 method，不過其實 Loader 也是可以處理 AMD、&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.commonjs.org/specs/modules/1.0/&quot;&gt;CommonJS&lt;/a&gt; 甚至是 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://nodejs.org/api/modules.html&quot;&gt;NodeJS&lt;/a&gt; 型式的模組定義，只是要有人去實做這部分的 translate 和 instantiate 的部分，而 SystemJS最新版（0.16）就是這樣一個專案，它號稱是 universal module loader，支援 AMD、CommonJS、NodeJS 和 ES6 的模組定義，然後在最新的版本，改成使用 ES6 Module Loader Polyfill 的機制來做 module 的讀取、相依性的判斷和模組初始化，雖然有些地方沒有真的照之前的 spec 來實做。&lt;/p&gt;

&lt;p&gt;另外一個之前不太清楚的問題也藉此搞清楚了，ES6 module 有限制一個檔案定義一個 module，而現在的 web application 常常為了效能問題，都把多個檔案合併成一個檔案，這時就不能用 ES6 module 了，當然也可以用像現在 SystemJS 的作法來處理，不過其實再過一兩年 HTTP/2 普及後，也不需要這樣搞了，會變成只需要 minimize，這部分倒是還可以接受。&lt;/p&gt;

&lt;p&gt;ES6 裡面的 Loader 本身其實是一個 constructor，放在另外一個 ES6 提供的新東西 &lt;code&gt;Reflect&lt;/code&gt; 下面，而用 &lt;code&gt;Reflect.Loader&lt;/code&gt; 建立 Loader instance 時可以順便給他一些參數，像是前面提到的讀模組的五個步驟的實做，或是領域（realm），而 &lt;code&gt;System&lt;/code&gt; 物件則是該 JS 環境下的預設的 Loader，理論上如果是瀏覽器環境，它就會知道怎樣去 fetch 遠端的程式碼回來，如果是 NodeJS 就會改用 file system 讀檔案，而且也知道要把模組放到那個 realm（理論上不同 frame 就是不同 realm），這樣大部分的使用都可以用 &lt;code&gt;System&lt;/code&gt; 就好了，只有很少數的情形需要自己建立 Loader。其實上面說的 Loader API 不知道為什麼是移到 WHATWG 之後，幾乎是重新開始編寫，完整度欠佳，有些章節還是空的，另外也沒有定義 &lt;code&gt;System&lt;/code&gt; 或是其它的新的替代方案，所以現在想要看看到底 Loader 內部怎麼做的話，要看舊版的 spec，可以去抓 2014 年 8 月的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts#august_24_2014_draft_rev_27&quot;&gt;ES6 draft rev 27&lt;/a&gt; 然後看看 CH 26, 15，對照 ES6 Module Loader Polyfill 的程式碼可能比好懂。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=6uPZzFIHQv4:o_OjCGUFgK0:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=6uPZzFIHQv4:o_OjCGUFgK0:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=6uPZzFIHQv4:o_OjCGUFgK0:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=6uPZzFIHQv4:o_OjCGUFgK0:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=6uPZzFIHQv4:o_OjCGUFgK0:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/6uPZzFIHQv4&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/04/05/loader/</guid>
         <pubDate>Sun, 05 Apr 2015 06:50:09 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>ECMAScript 6 Final Draft Approved</title>
         <link>http://feedproxy.google.com/~r/othree/~3/NSOuWfwvVeo/</link>
         <description>&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;zh-tw&quot;&gt;&lt;p&gt;Ecma-TC39 just approved the final ES6 draft. It now goes to the Ecma General Assembly for approval in June&lt;/p&gt;- Allen Wirfs-Brock (@awbjs) &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/awbjs/status/580321916403216384&quot;&gt;2015 3月 24日&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;剛剛看到說 ECMAScript 2015(ES6) 定稿了，最後一版草稿是 RC4（還沒 release），接下來會是 ECMA 認證流程的樣子，不過繼續下一版的討論也不會中斷，順便要說一下他們最後 approve 的地方是在 H.R. Giger 博物館的酒吧，超酷的，這是畫異形那位大師的博物館。&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;zh-tw&quot;&gt;&lt;p&gt;Celebrated w/&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/rebeccawb&quot;&gt;@rebeccawb&lt;/a&gt;  TC39 approval of ES6, at H.R. Giger Museum in Gruyère &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://t.co/uEKzfozxX2&quot;&gt;pic.twitter.com/uEKzfozxX2&lt;/a&gt;&lt;/p&gt;- Allen Wirfs-Brock (@awbjs) &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://twitter.com/awbjs/status/582239060539904000&quot;&gt;2015 3月 29日&lt;/a&gt;&lt;/blockquote&gt;

&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=NSOuWfwvVeo:F0O6uYGe2AI:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=NSOuWfwvVeo:F0O6uYGe2AI:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=NSOuWfwvVeo:F0O6uYGe2AI:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=NSOuWfwvVeo:F0O6uYGe2AI:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=NSOuWfwvVeo:F0O6uYGe2AI:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/NSOuWfwvVeo&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/03/30/ecmascript-6-final-draft/</guid>
         <pubDate>Mon, 30 Mar 2015 10:34:07 +0000</pubDate>
         <category>script</category>
      </item>
      <item>
         <title>For the Entire Web</title>
         <link>http://feedproxy.google.com/~r/othree/~3/HKxMeempe5M/</link>
         <description>&lt;p&gt;這陣子有兩件事情引起我的一些注意，覺得值得寫下，兩件事情我覺得其實本質上是同一件事情，先來看一下第一件事情，就是 Daniel Yoder 寫了篇文章 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.pandastrike.com/posts/20150311-react-bad-idea&quot;&gt;React Is A Terrible Idea&lt;/a&gt;，這篇文章在 React 當紅的時間出現，自然引起很多人的不滿，隨便在 Google 上搜尋就可以找到一堆回應，我自己對於 React 其實是沒特別感覺，沒有喜歡也沒有覺得它做錯什麼，真的要說的話大概還有點覺得它方向正確，我是認為 React 和 Angular 的 directive 都在把 component 的觀念引入前端工程師的視野之中，而這對於 Web Component 的發展應該會是有正面影響的。&lt;/p&gt;

&lt;p&gt;再回到 Terriable Idea 這篇文章，作者對 React 的評論我其實不完全認同，最後面有提到用 Web Component 而不要用 React，這部分我覺得是作者誤會了 React 的角色，不過有些地方有人說 React 明明就可以和 Web Component 合作，還附上 ng-conf 的&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://www.youtube.com/watch?v=g0TD0efcwVg&quot;&gt;演講影片&lt;/a&gt;，我到覺得他們也完全沒搞清楚作者的重點在哪裡；提到 Flipboard 的 &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://github.com/flipboard/react-canvas&quot;&gt;react-canvas&lt;/a&gt; 那部分算是我認為最能表現出作者想要講什麼的，作者想說的重點是現在的網路環境有限制、有問題，但是遇到時不要用一些旁門左道的方法來處理，因為這些問題終究會被解決，而問題被解決時，你之前所花的時間和資源就等於是完全浪費掉，與其要浪費在走旁門左道，還不如把這些時間和資源用在從正確的地方解決這個問題，而最後受惠的不只是自己，還有所有網際網路的開發者、使用者，這是從一個很高等生命體的角度來看事情，就如同這篇文章的標題：「For the Entire Web」，要你犧牲自己的部分利益去成就整體網際網路的利益，當然這是有些理想化，很多商業公司可能要短時間就有產品出來，不太可能所有的開發在遇到問題時都停下來等瀏覽器或是標準齊備，但是對於不少的大型企業，我就覺得他們確實應該要好好正確的回饋網路環境來解決這些問題，像是文中提到 Facebook，還有接下來要說的 Google，不過他說 Facebook 是為了和 Google 競爭才開發 React 之類的論點我就不予評論了，太多臆測～&lt;/p&gt;

&lt;p&gt;可能有人會說，有沒有這些資源的投入應該差距也不大吧，最近就剛好有另外一件事情可以佐證，&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://news.dartlang.org/2015/03/dart-for-entire-web.html&quot;&gt;Dart for the Entire Web&lt;/a&gt; 這篇 Dart 官方的公告說到，Dart VM 將不會進入到 Chrome 裡面，也就是說要在瀏覽器上跑 Dart，將還是只有轉成 JavaScript 這個選項，這件事其實是蠻大的一件事，上一個在網頁裡面跑的另外一種語言是微軟的 VBScript，最大的問題不在於好不好寫，而是在於他被單一企業把持，不過後來結果大家也都知道，所以當 Google 推出 Dart 而且說以後 Chrome 會可以直接跑 Dart 的時候，我想大部分人都是都不看好的，甚至部分人是覺得 Google 怎麼做微軟做過的蠢事。而剛好在這個官方公告出來後幾天內，Brendan Eich 在 Hacker News 上回應一串討論&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://news.ycombinator.com/item?id=9269355&quot;&gt;回應&lt;/a&gt;的蠻激動的，這串本來是在說 ECMAScript 新版本有很多東西根本是從 Dart 來的，Brendan Eich 則是反駁說很多東西在 Dart 出來前就已經在討論有 Proposal 了，然後到後來寫了一篇幾乎都在抱怨 Dart，還提到 V8 team reset 的事情，從這邊看起來，似乎是因為新的 V8 team 不打算作 Dart VM 進去，才有了 Dart 那篇公告；而 Brendan Eich 抱怨的重點，其實就是前面那段提到的，Google 花了超多人力資源去搞 Dart，而不是來幫忙改進既有的 ECMAScript，而這確實有實際的影響，他舉了一個例子，就是大數(&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wiki.ecmascript.org/doku.php?id=strawman:bignums&quot;&gt;bignums&lt;/a&gt;)的支援，Dart 有支援，在 ES 這邊目前有一點可能性會在 ES7(2016) 中出來，但這東西其實從 2010 就已經開始有討論了，如果有人來將這些討論規格化，並實做起來，那大數應該在現在的 ES6(2015) 就有了。&lt;/p&gt;

&lt;p&gt;最後再回到 Terriable Idea 這篇文章，我雖然不完全認同他對 React 的看法，但是我認為他的重點沒錯，如果他拿 Dart 出來講可能就不會引出這麼多砲火吧（可是可能也比較沒人注意），其實 react-canvas 我覺得也是很有趣的實驗，不過做成正式產品上線就是另外一回事了，最大的問題，他為了終會被解決的次要問題（畫面不流暢）完全放棄了親和力的問題，而 Flipboard 這種內容為主的產品性質是不該放棄親和力的。&lt;/p&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=HKxMeempe5M:bmO-i5SqyIU:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=yIl2AUoC8zA&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=HKxMeempe5M:bmO-i5SqyIU:YwkR-u9nhCs&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=YwkR-u9nhCs&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=HKxMeempe5M:bmO-i5SqyIU:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?i=HKxMeempe5M:bmO-i5SqyIU:F7zBnMyn0Lo&quot; border=&quot;0&quot;&gt;&lt;/a&gt; &lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://feeds.feedburner.com/~ff/othree?a=HKxMeempe5M:bmO-i5SqyIU:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/othree?d=7Q72WNTAKBA&quot; border=&quot;0&quot;&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src=&quot;http://feeds.feedburner.com/~r/othree/~4/HKxMeempe5M&quot; height=&quot;1&quot; width=&quot;1&quot; alt=&quot;&quot;/&gt;</description>
         <guid isPermaLink="false">https://blog.othree.net/log/2015/03/28/for-the-entire-web/</guid>
         <pubDate>Sat, 28 Mar 2015 05:25:25 +0000</pubDate>
         <category>web</category>
      </item>
   </channel>
</rss>
<!-- fe4.yql.bf1.yahoo.com compressed/chunked Thu Oct  1 22:36:05 UTC 2015 -->
