五年前,第一次製作 Gap撈Tech v1 嘅時候選擇咗用 Self Host 嘅 Ghost v0.10 左右,起嘅時候只係用咗三日

  1. 喺 Digital Ocean 起咗部 $5 機(Managed Ghost 好似要 $19)
  2. 買咗一個 Paid Theme,入面用緊 Bootstrap(.less)、jQuery
  3. 著起咗隻 Ghost
  4. 執個 Logo、改番啲 Social Platform 設定、執咗少少 Bootstrap Layout
  5. 大功告成!

但今次 Gap撈Tech v2 卻用咗三個月時間,今天想描述一下筆者五年來的心路歷程!

2015:選擇 Blogging 平台的典故

2015 年筆者只係抱住一個好簡單想法

想有一個自己嘅地方寫自己一啲嘅想法,冇任何技術限制想寫咩就寫咩以及想點擺就點擺,隨時一鍵比條 Link 就可以比朋友或發佈上網,而且所有寫嘅 Content 係屬於自己。

未做任何 Research 之前,以筆者有限嘅認知有兩個大平台好易入門

  1. blogger.com
  2. WordPress

但筆者認為 blogger.com 未必能夠符合以上想法;WordPress 則在工作上曾經使過,用後感只有一個 — 不了!

於是做下 Research 仲有咩選擇,幾番 Google 後就搵到 Ghost,第一眼見到佢可以用 Markdown 寫又係 NodeJs 底(v0.10 年代)已經非常吸引,技術新穎之餘又可以 Self Host,基本上一見到就已經 git clone 落黎試下用!

玩咗一陣覺得簡潔易用,喺正式上馬之前再做咗少少起底工作,原來 Ghost 當年係靠 Crowd Funding Platform 起個頭,目標就係「Just a Blogging Platform」,相信大部份與我有同樣問題嘅朋友都得以獲救,並更加確信自己嘅選擇唔會後悔。

可惜好景不常,筆者不知不覺地對一個 Blogging 平台要求愈來愈高,尤其在 Medium 走紅的時候

所謂:沒有比較 就沒有傷害

但殘酷嘅比較擺在眼前,Medium 嘅設計真心不錯,的確有比下去嘅感覺,更有一刻會問自己是否應該跳船到 Medium。

2017 年筆者嘗試在 Medium 發佈《Picking Kotlin for Android》一系列三篇的文章作為試點,了解一下發佈流程及使用體驗。

2017:缺少了一塊的 Medium

三篇主要是技術分析為主,Part 2 更涉及大量 Kotlin / Java Coding 分析。

Part 1 : Picking Kotlin for Android — The Reason Behind
Kotlin is a relatively new and statically typed programming language for the JVM, Android and the browser. It is backed by JetBrains — The biggest IDE manufacturer in the world.
Part 2 : Picking Kotlin for Android — Killing Features
Welcome to Part 2, this part is composed by a lot of gist (Java vs Kotlin sample codes) as a show case. Many useful comments/arguments are written in the gist. In order to have better reading…
Part 3 : Picking Kotlin for Android — Swift in Android?
I have seen a lot of iOS developers who has tried Kotlin with their first glaze and most of them would very likely to use the following statement to describe Kotlin: But, from my personal experience…

整個系列總共寫了一個星期多,體驗一般而且感覺上更加做多咗額外工序去令改善文章的觀感。

識筆者嘅朋友都知道筆者非常著重 Syntax Highlight,甚至做咗一個 IntelliJ IDEA Color Scheme — GapStyle,但偏偏 Medium 的 Code Block 沒有提供 Syntax Highlight,唯一 Work Around 嘅方法只可以使用 Embedd Widget 去處理,最常見就係 GitHub Gist。但問題在於當時 Gist 在 Medium Mobile/Web App 上處理 Gist 時放大得太多,感覺有 200% View Port 咁大,用 Medium Mobile/Web App 真係好難睇!

medium-app-gist.png
Medium App Screen Capture @ 23 Feb 2020

但因為當初寫 Medium 的時候只用了 Desktop Preview,整理及發佈後才認知有這個問題...

冇錯,張圖係啱啱 Cap 嘅,三年後的 2020 年依然有呢個問題(Feature Not Bug?)

除了 Gist 在手機閱讀上出問題,在文章數目增多時,筆者亦預見到有兩個大問題要花時間去管理:

  1. 在修改 Gist 後,由於 Commit Hash 會更改, URL 亦會更改,所以要更新 Gist 的內容就必須更新 Medium 的文章
  2. Content (Gist 內的 Code) 分開了兩個地方儲存,一邊儲存在 Gist,另一邊儲存在 Medium,要核對是否正在使用正確版本非常浪費心力

或許是筆者自身的執著才會衍生這個問題,所以當時預見自己會不斷分享 Coding-Oriented 的技術文章,綜合在 Medium 發佈技術文章的體驗來說:

生產力太低喇!寧願花時間做一個自己滿意的版本

自 2017 年開始,Gap撈Tech v2 的待辦事項亦愈加愈長,偏偏遇上一個好麻煩嘅病。

一個病就收皮

大約由 2017 年尾到 2019 年中,做咗 2 次大手術 1 次小手術,有 1/3 時間喺係張病床上面過。病床以外的 2/3 康復期,日常處理完公務後都盡量唔可以比自己太操勞,所以基本上接近停哂所有 Gap撈Tech 嘅更新,將啲時間撥落去休息之上,不過耐唔時有啲靈光一閃嘅想法都有加喺待寫事項中。

(話雖如此,但身邊嘅同事朋友都係覺得自我收歛咗嘅阿 Gap 好 Chur 🙈)

呢段空白期,多咗啲時間靜落黎去沉澱、思考及自我定位;雖然冇花時間去寫作,但依然會了解下最新技術,有趣嘅係撞正 2017 - 2019 呢段時期,有大量 Web 技術急速進入穩定期。

2018:大量新興 Web JS Framework 開始進入穩定期

以做 Website 黎講,揀技術起手嘅時候必須要將 SEO 排第一位,而曾經有一項必須要達到嘅指標就係 Crawler Bot Friendly,因為某啲 Search Engine 嘅 Crawler Bot 未必會執行 Client Side Javascript,所以比著係筆者都會閉上眼睛揀支援 Server-side Render 嘅技術。

而 2018 年走得最火熱嘅一定係 Universal Application,具代表嘅作品就係 Next.js(React) / Nuxt.js(Vue)。Universal Application 簡單嚟講就係第一下入去係 Server-side render,其後若 Client Browser 支援運行 Javascript 就會轉行 Client-side Rendering,可以話一下子寫解決了早兩年(2016 年)的做 Single Page Application 的煩惱;另外值得一提莫過於 Next.js/Nuxt.js 支援 Code Splitting,有效地分拆每頁所需的 Javascript Bundle size,大大提升頁面載入速度!

所以有一刻諗過用 Nuxt.js + Ghost(Headless CMS) 去打造 Gap撈Tech v2。不過,筆者知道要投資好多時間落去,點都係要等病好先可以開始。

雖然 Universal Application 解決到好多問題,但始終要有一台伺服器 (或者 AWS Lambda / Google Cloud Function)去執行 Server-side Render

不過總有啲人會將「做 Dynamic Content Website 就必須要有台伺服器」呢種習以為常嘅做法視為一個問題,十多年前有人創造 Static Site Generator 解決過一次,十多年後再用全新技術,突破界限去解決同一個問題,筆者所說的就是 JAM Stack(在 Internet Archive 翻查 https://jamstack.org/2016 年 5 月首次出現)。

只不過係區區一個 Static Site Generator,何必咁大驚小怪?

"Dynamic" Static Site

Static Site Generator 絕對不是什麼新鮮的事,老早在十年前的 PHP Framework 也有提供,大量政府資訊性網頁都靠呢個方法做,有 Content 要更新,通常靠人手重新 Generate 一次再 Deploy,再者 Implementation 上通常不是 Ajax Friendly,每版轉頁都要重新 Load 一次。

但試想下十年後有人將 Static Site Generator + Single Page Application + GraphQL + CI + CDN 撈埋一齊做瀨尿牛丸就確係可以震驚十三億人!就係 GatsbyJs!

不得不佩服設計者諗到用 GraphQL 做條龍骨,將最難靈活改變嘅 Data Source Decouple,事關大部份 Developer 當接駁自稱 RESTful API (實質 Http RPC)Fetch Data 嘅時候,好多時都會卡唔夠彈性而放棄做 Abstraction,直接 Hard Code,變相每次構建新網頁嘅時候都接近重寫一次。

gatsby-animated.gif

筆者首次見到呢幅圖已經幻想到佢嘅強大, git clone Starter Template Project 駁 Travis CI 駁 Netlify / GitHub Pages 成件事都好流暢,基本上可以話係 Developer Centric Blogging Website 恩物,流程如下:

  1. 寫 Markdown
  2. git commit; git push
  3. Trigger CI Server 運行 GatsbyJs,將所有 Markdown Parse 一次
  4. 運行每個 Page 嘅 Graph Query,將所需嘅 Data 打包成為 page.json 備用(Client Side Rendering 時才會 Ajax 提取),兼且為每個 Page 出一個 Static HTML。
  5. 最後成為一個 Pre-rendered Static Single Page Application (React)

到 2018 年尾 GatsbyJs 推出 v2,基本上當刻已經決定 Gap撈Tech v2 待康復後一定用 GatsbyJs 開發!

2019 年 4 月終於開波!

gatsby-gaplotech-v2-commit.png

1 個月時間大概只係做咗 5 成想要嘅功能(Typescript、Material UI、Custom HTML AST Renderer、MDX Experiment),然後就要去做一次小手術,小休咗 1 個月左右,最後一次七月中再做大手術再大休 3 個月到九月。

九月復工後,基本上大部份時間都關注社會運動,完全無心機搞任可嘢工餘嘅野。但喺呢一個動盪時代,收到一封見到有少少興奮又有 Click Bait 味道嘅電郵!

Ghost 3.0 👉 New business models for publishing & much more!

2019 末:Ghost 推出 Membership 功能

2019 年 10 月,Ghost 推出 v3 並支援 Membership 功能,再撰寫了一篇令筆者覺得非常受落嘅解說 —《Ghost Membership Software: Sustainable revenue for publishers》

十年前有人話

喺十萬隨機受眾當中平均獲取 $0.1 咁你就有 $10k 收入 (免費內容+隨機的插入式廣告)

但今時今日 Content 真的太氾濫,部份原因歸咎於 Content Farm、Click Baits 及假新聞搞爛咗成個市,令整個生態惡化嘅係大量「零經驗新網民」湧入令整體網民質素下降。

今時今日 Content Farm 透過社交媒體分享震驚十三億人嘅標題去呃 Impression,大部份人「被騙後」都唔識或唔會封鎖及隱藏 Content Farm 去減低再出現嘅機會,更嚴重嘅係有人仲會在社交媒體分享。於雙重打擊下,可能一個高質素嘅獨立創作者都唔夠 Content Farm 嘅收入多。

此外,這個收入模型下創作者的謀生方向只能局限地做大眾化題材。

大眾化題材離不開娛樂、飲食或搞笑,有廣闊受眾的前設下喺香港實行「每個人身上賺少少」或許尚有生存空間,但喺香港做專業少眾的題材例如資訊科技內其中一門的軟件開發,用上述講法運行的話,依賴隨機受眾帶來的收入可能連每日買碗粥水食下都做唔到。

既然免費內容豎立了此路不通的警告標語,創作者就自然要向另一個方向找出路。

喺一千個目標受眾當中平均獲取 $10 咁你都有 $10k 收入 (收費內容 / 免費內容+不干預的贊助模式)

但要做到這個程度,必須先証明自己能創造價值而且能獲得別人青睞,到有了一定的目標受眾才有機會開始量化自己創造出來的價值,可是要實踐這一點是非常非常困難。

但筆者相信,正因為困難才有挑戰性及有價值,亦相信自己能夠樂此不疲去做呢件事。

I am in

2020: 重返 Ghost

重返 Ghost 第一件事就係閉上眼睛用 Ghost Pro 去課金支持 Ghost 發展,兼且開始寫 Gap撈Tech v2 Theme 之旅。

ghost-payment-screenshot.png

起手用 Ghost Default Casper Theme,但發現 Ghost 在 Casper 開發上只配搭了 Gulp 及 PostCSS,筆者明白開發者的用義,事關愈少 Dependencies 代表 Learning Curve 愈淺,可以輕易小修小改做個性化。但這個配搭卻會窒礙一些撐握最新技術的 Developers ,因為 Developers 無辦法使用最新技術去加速開發。故此,筆者決定自行打造 Webpack + Babel + Scss + VueJs + Handlebar SSR Architecture,並活用大部份 Casper 的 Styling 做出一個自己滿意的 Gap撈Tech v2。

ghost-theme-gaplotech-v2-commit.png

一個月多的工餘開發時間,最後將這 Ghost Theme 命名為 JustDev ,並打造了

MIT License,有興趣自己搞 Blog 嘅或想脫離 Medium Paywall 嘅朋友可以隨便改隨便用。

展望

筆者未來會專注創作,分享更多所見所聞及 IT 經䌞創造價值。至於 2019 年初用 GatsbyJs 寫最後爛尾的 Gap撈Tech v2 所花的時間亦不會白費,筆者會利用過程中得到嘅經驗打造另一個 Open Source Software 。

2020 年過去 3 個月,玩了 4 個 Open Source Project

gaplo917/Ligatured-Hack
Automatically patch latest Hack Font with latest JetBrains Mono / FiraCode Ligatures - gaplo917/Ligatured-Hack
gaplo917/load-balancer-benchmark
Apache Httpd vs Nginx vs Traefik vs HAProxy. Contribute to gaplo917/load-balancer-benchmark development by creating an account on GitHub.
gaplo917/S3WebUploader
A minimalistic Web UI to conveniently upload and download files from AWS S3 compatible services - gaplo917/S3WebUploader
gaplotech/just-dev-ghost-theme
A default developer blog theme for Ghost 3.0+. Contribute to gaplotech/just-dev-ghost-theme development by creating an account on GitHub.

但係一篇 Blog 都未寫到

上一個年代,有時會問自己:「究竟我鐘意寫 Software 定鐘意寫 Blog 多啲?」

走了半個年代後獲得的答案

我只是單純享受創作過程,寫 Software 和寫 Blog 㫮是創作的一部份。

能享受一步一步走近當天草率立下的里程碑,是一種幸福,也是一種福氣。

一個 IQ 沒有 160 的普通人

一個只做忠於做自己內容的創作者

一個自小我的志願寫做程式設計員的軟件工程師

Gap