窮人Stack: github page + WordPress.com

前陣子因著自己的需要,做了這個『寶咖咖搜尋器』:

demo-bao.gif

如果你跟我一樣看房看了數年仍是無殼蝸牛,大概一眼就看懂這在做什麼了;如果看不懂,恭喜!你的人生還粉粉嫩嫩、閃閃動人。不過請放心,本篇跟這些黑漆抹烏的完全無關,只著墨在tech stack上。有興趣了解背後悶到出汗的故事者,可以參閱這篇ptt發布文

這個專案不大,但考量到平日龐大的工作量加上顧小孩,我能用的時間既零碎又少,能承受的維護成本非常低,所以最好不用自己host,也不需要我花太多力氣在null exception之類的蠢bug。最後的結論就是:

  • Backend: WordPress.com
  • Frontend host: Github page
  • Frontend development: elm

用WordPress.com當作資料後端?

自從REST API整入core之後,把WordPress當作泛用CMS並不是什麼新鮮事。在這次的小專案裡,我沒有用core REST API,而是使用WordPress.com API,主要是因為個人比較熟悉,沒什麼理由不能使用core REST API。主要用到的是GET /sites/$site/posts這個API,詳細說明請見官方文件。這個API讓我們可以指定一些條件取出想要的文章列表,例如:

  • search: 關鍵字搜尋
  • tag / category: 針對某個標籤或某個分類進行搜尋
  • exclude: 排除某些文章

其實這樣就很像一個關聯式資料庫了吧?想像把所有資料點都用一篇WordPress文章( post )來描述,資料點間的關聯性則用tag或category來描述;加上文章本身就有內文可以放更複雜的東西,還可以加上meta、自訂類別,表述資料的能力其實非常強。

以這個專案來說,用來查詢資料的程式碼相當簡單:

-- exclude the post ID 92 since it is the announcement post.
postApi : String -> String
postApi query = "https://public-api.wordpress.com/rest/v1.1/sites/isthisbaokaka.wordpress.com/posts?fields=title&exclude=92&search=" ++ query

decodePostQueryResponse : Json.Decoder ( List String )
decodePostQueryResponse =
    Json.at [ "posts" ] ( Json.list ( Json.field "title" Json.string ) )

requestQuery : String -> ( Result Http.Error ( List String ) -> msg -> Cmd msg
requestQuery queryString callback = Http.send callback ( Http.get ( postApi queryString ) decodePostQueryResponse )

除了不用自己寫API外,WordPress.com非常穩定,又不用我自己host,還可以用習慣的calypso或wp-admin介面來直接編輯資料,省掉我不少功夫。

咦?這只有GET,如果需要POST / PUT / PATCH / DELETE呢?WordPress.com API是有authentication API啦 … 但要怎麼放token是個問題,端看app的使用情境而定。

Github page + CircleCI

前端host的選擇很多,個人因為習慣的原因選用Github page;除了不想自己host外,另一個重要理由是有免費的CircleCI可以用。有CircleCI我就可以在每次更新master branch時,讓CircleCI幫我用elm-make編譯並更新Github page,也就是持續發佈( continuous deployment )。

這部分可以google到很多教學,例如這篇Using CircleCI with Github Page就寫得不錯;但像這種只有一個人在弄不用考慮多人同時push的小專案不用這麼複雜。大致上是:

  1. 設定一個branch為Github page所用,此例為gh-pages
  2. 決定一個build artifact資料夾,此例為./build
  3. 在master branch將./build加入.gitignore,在gh-pages中則不要加入.gitignore。這麼一來,開發的時候可避免build artifacts的騷擾,Github page branch又仍可從該資料夾發佈。不過這也可以用git add -f來達到一樣的效果,就看自己覺得怎樣比較潮。
  4. 設定CircleCI追蹤master branch。每當有更新,就切到gh-pages branch去編譯、上傳,省去自己發佈的麻煩。

詳細設定請看circle.yml,相當簡單。這個做法的缺點是不適合多人同時開發的情境,如果一群人同時push到master,gh-pages究竟最後是發佈哪個版本很難保證。一個折衷方法是用master / staging兩個branch,以staging為主branch,在需要發佈新版時再發一個pull request將staging merge至master;但這樣就沒有自動的持續發布了,潮感銳減。

錦上添花:Elm

elm是一套為前端開發所設計的static-typed functional language,最終會編譯成JavaScript來發佈。會選用它是因為它有類似Haskell的型別系統,透過型別安全達到極高的程式運行正確性;這麼一來,『It compiles. Ship it.』這個笑話是真的成立的。

我自己以前半途毀棄過無數side projects,回想起來通常都是在碰到很花時間的bug時宣告入土。但透過elm,不但很難寫錯,就算我過個幾個星期才回來寫也沒辦法把程式弄壞,大幅降低維護成本。有興趣可以參考這個talk: Making Impossible States Impossible

另外還有一個好處是不用花時間搞boilerplate,只需要elm package就行了。這年頭要寫個ES6的專案,光是把所有套件帶齊設定好就要花好一陣子了,npm、babel、webpack等等;這也是為什麼github上有好幾卡車的boilerplate專案,而且還在持續增加中。

有趣但小有缺憾

這個小專案有趣,而且也實際用過很多次;透過WordPress.com + Github page + Elm的組合,讓我後續維護成本極低。唯一缺憾是想做的功能沒有做全,為了避免一拖再拖造成精神上的負擔,我設定了一個死線,一旦到了這個日期就要收尾,也就是上面ptt發布文。

沒做的部分是建案反查建商。這功能主要有兩個部分:

  1. 資料來源
  2. 如何在WordPress中描述上述資料?

資料來源的部分,國內比較完整又方便取得的大概是住展房屋網;它本來就有從建商搜尋建案的功能,我又已經有建商列表了,只要寫一支爬蟲去自動巡覽列表,把查到的建案一一爬下來即可。WordPress中描述資料的部分,可以用tag來對每一個建案標註建商。這麼一來查找到建案後,帶出其tag就可以知道是哪個建商,而且還可以進一步用此tag帶出所有該建商的建案。

雖然做法已經想好,但短時間內恐怕都無暇實作吧。反正都open source了,真希望哪天起床就發現有小精靈幫我做好了啊啊 👻👻👻

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s