免費無限建立自己的 GitBook 圖文教學 – 利用 GitHub Pages + GitHub Actions 自動發佈

自從對新版 GitBook 官方平台(GitBook V2)徹底失望,一直在留意能運作 GitBook 的替代方案,因為我很喜歡舊版 GitBook 工具的便利性、運用靈活、自訂性空間大,即使在封閉網路環境也能自架 GitBook。

GitBook 官方平台對書籍數量的限制是讓我徹底捨棄官方平台的最大因素。GitBook V1 允許免費版帳號有無限本公開書籍,V2 卻大幅限制只能有一本,付費版價格也很不親民,雖然後來開放到 10 本,但已經棄坑的心就像飛出去的全壘打回不來了。

我對新版 GitBook 官方平台的 吐槽 感想 可參考另一篇文章:淺談新版 GitBook(GitBook V2) —— 失去交流開放精神的企業導向產品

GitBook 我大部分用途是寫寫筆記,彙整成書籍形式方便查閱或分享,不希望造成額外的費用或時間成本。

簡單來說,我需要有一個平台可以免費放書、沒有書籍數量限制、設定不要太複雜、每次編輯書籍內容都能自動更新。

後來發現 GitHub 周邊服務的整合就能達到我的需要。下面這張圖是成果示範,效果對我而言已經足夠,設定簡單,基本書籍功能具備,閱讀的視覺舒適度也不差。

本篇文章會簡單介紹我的解決方案,並示範怎麼自動發佈你的書籍。

解決方案的理想條件

事實上要找替代方案並不難,雖然 GitBook V2 官方宣稱不再維護舊版 GitBook 指令工具,但 open source 的好處就是你仍然可以下載得到 gitbook 指令工具,製書方面不成問題

需要的是放書的平台,以及每次編輯後的發佈更新

以下是我心目中對書籍筆記平台的理想條件:

1. 免費無限本書

不用解釋,最關鍵的考量,也是 GitBook V2 最致命的一點。

2. 免費託管空間

希望書籍能在網路上公開任意存取,但不用自己花成本在維護主機或購買雲端空間。

3. 一旦內容有編輯更新,書籍會自動更新發佈

我認為這是很重要的一點,把力氣放在專注寫作。至於瑣碎又制式化的製書、發佈操作就讓科技代勞。

4. 支援文件原始檔用 Markdown 格式

GitBook V2 的文件原始檔已經不再是通用的 Markdown,而是官方自己定義的 JSON 文件(當然你可以選擇在 GitHub 用 Markdown 寫作再同步到 GitBook V2 平台)。

個人偏好製書的 Source 能維持 Markdown 格式,一來容易寫作,二來可攜性和移植性高(Portable)。文件 Source 不要是特定平台專用的格式,才能容易備份、搬遷、更換替代方案。

5. 自訂網域(Custom Domain)

這算是一個 Better to have 的條件,不是必要。支援自訂網域,一來書的 URL 可以更好記,二來有機會為你自己的網域累積價值。

滿足所有條件的解決方案:GitBook CLI + GitHub Pages + GitHub Actions

GitBook CLI 工具 —— 自己的書愛怎麼建就怎麼建

gitbook CLI 工具是使用 Markdown 寫作製書的老牌選擇,可以建立書籍的靜態網站,不受限網路環境,Portable 可攜性滿分,需要什麼外掛 Plugin 有都能任君自訂。

自己製書的好處是不再受限第三方平台的支援度,需要加上什麼外掛都能自己掌握,只需要一個託管空間放書,這個空間可以是任何地方,搬家逃難也方便。

免費吃到飽的 GitHub & GitHub Pages

至少目前還是啦⋯⋯

GitHub Pages 提供靜態網站的放置託管服務,早就廣泛被作為作品集、個人自介、demo 網站等運用,也支援自訂網域的設定。

而 GitHub 提供無限儲存庫(Repositories)的服務,每個儲存庫都對應到獨立的 GitHub Pages,應用起來相當於擁有無限個放書空間。

雖然很多人對於 GitHub 被微軟買下後的發展很沒信心,我個人至少看好 GitHub 對個人用戶長久免費開放這一點。在這個大開源時代,比起靠原始碼託管從個人用戶身上掏金,守好 GitHub 的龍頭地位、著眼和 Azure 與 Microsoft Visual Studio Team Service(VSTS)的雲端整合,從企業用戶和其他雲端產品獲利應該是更實際的作法。

退一步來說,就算哪天 GitHub 或 GitHub Pages 突然要收錢也不用怕,反正只是一個託管平台,換個地方就行了。這就是自己掌控製書的好處,不用擔心換個地方,書的內容或呈現效果會被影響。

持續發佈工具 GitHub Actions 讓書籍編輯後自動更新

這是最後一哩路,也是物色比較久的部分。

GitBook CLI 製書和 GitHub Pages 託管其實都是不太需要考慮的當然選項,如何用最簡便的方式做到自動發佈才是問題。

一度考慮過其他外部 CI/CD 工具,例如 Travis CI。但外部工具還得考慮和 GitHub 的整合性,雖然我相信以 GitHub 的廣泛使用,外部工具有支援整合的可能性很高,技術問題都能解決。

但既然選擇用 GitHub Pages,而且 GitHub 也推出免費 CI/CD 工具 —— GitHub Actions,就近選擇 GitHub 自家工具應該是最省力的選擇,將力氣留給寫作。研究 GitHub Actions 之後發現設定也不複雜,算是很理想的方案。

接下來就要進入正題,示範怎麼用上述的方案來建立自己的 GitBook。

範例教學:自動建立並發佈一本書

Prerequisites (前置工作)

你需要準備以下東西:

  1. 申請一個 GitHub 帳號。
  2. 最基本的 Git 操作知識,例如 git add, git commit, git push。我相信使用過 GitBook 和 GitHub 的人對這幾個指令不會陌生。

以下教學的範例檔案放在 GitHub 上 可輔助參考。

Step 1. 寫書

第一步需要最多心力,就是寫下你的著作。

這裡重點是示範怎麼建立你自己的 GitBook,所以我們用簡單的內容當範例,建出來的書會有 Introduction 和兩個章節:


建立一個名為 demo-build-and-publish-gitbook 的資料夾放置所有檔案,以下是檔案和資料夾結構的建議:

$ tree demo-build-and-publish-gitbook/
demo-build-and-publish-gitbook/
└── book_sources
    ├── README.md
    ├── SUMMARY.md
    └── articles
        ├── chapter-01.md
        └── chapter-02.md

重點:

  1. 重要!把 GitBook 內容相關的檔案全部放在 book_sources 底下。
  2. README.md 是必要檔案,會成為 Introduction 頁面。
  3. SUMMARY.md 是必要檔案,會成為左邊的目錄。
  4. 非必要,但建議設一個資料夾 articles 專門放置文章檔,可以讓檔案結構更好維護。

Step 2. 新增 book.json 檔

book.json 是 gitbook CLI 工具製書時的必要設定檔。

請新增在 book_sources 資料夾底下:

$ vi book_sources/book.json

如果你沒有概念該怎麼設定,可以直接複製貼上以下範本。這是我習慣的配置,包含幾個我覺得實用的 Plugin:

  • anchor-navigation-ex:支援 TOC 和「回到頂端」的功能。這個 Plugin 我覺得非常出色,有興趣客製化設定可以參考作者的教學文件
  • copy-code-button:每個 Code Block 右上角會多一個 Copy 按鈕方便複製。
  • edit-link:頁面頂端會多一個「EDIT THIS PAGE」的連結,點下去會開啟 GitHub 的編輯頁面。連結的字眼可以自訂。
  • ga:Google Analytics,可以填入自己的 trace code。
{
    "plugins": [  "anchor-navigation-ex", "edit-link", "copy-code-button", "theme-comscore", "ga" ],
    "pluginsConfig": {
      "fontSettings": {
        "theme": "night",
        "family": "sans"
      },
      "theme-default": {
        "showLevel": false
      },
      "anchor-navigation-ex": {
          "showLevel": false,
          "associatedWithSummary": false,
          "printLog": false,
          "multipleH1": false,
          "mode": "float",
          "showGoTop":true,
          "float": {
              "floatIcon": "fa fa-navicon",
              "showLevelIcon": false,
              "level1Icon": "fa fa-hand-o-right",
              "level2Icon": "fa fa-hand-o-right",
              "level3Icon": "fa fa-hand-o-right"
          },
          "pageTop": {
              "showLevelIcon": false,
              "level1Icon": "fa fa-hand-o-right",
              "level2Icon": "fa fa-hand-o-right",
              "level3Icon": "fa fa-hand-o-right"
          }
      },
      "edit-link": {
        "base": "https://github.com/<你的 GitHub 帳號>/demo-build-and-publish-gitbook/edit/master/",
        "label": "Edit This Page"
      },
      "ga": {
        "token": ""
      }
    }
}

Step 3. 建立 GitHub Repository 並將檔案 Push 上去

先到 GitHub 上建立同名 Repository:

回到資料夾底下,執行以下指令:

# 產生 .gitignore 和 Repository 的 README
$ echo -e "_book\nnode_modules" > .gitignore
$ echo "# demo-build-and-publish-gitbook" >> README.md

# 將檔案推上 GitHub
$ git init
$ git add .
$ git commit -m "first commit for book content"
$ git remote add origin [email protected]:onejar99/demo-build-and-publish-gitbook.git
$ git push -u origin master

Step 4. 設定 GitHub Access Token

為了讓 GitHub Actions 能自動幫我們發佈 GitBook 成果到 GitHub Pages,必須授權 GitHub 操作我們的 Repository。作法就是設定 Access Token。

這裡都是在 GitHub 網頁上操作,按照以下步驟即可:

產生一個 GitHub Personal Access Token:

  1. 點右上角帳號的頭像 -> 選擇 Settings -> 左邊列表選擇最底下的 Developer settings -> 下個頁面的左邊列表選擇Personal access tokens
  2. 點擊 Generate new token 按鈕。
  3. 輸入 Token 的描述,權限勾選 repo:statuspublic_repo 兩個項目。
  4. 點最下面的 Generate token 按鈕。
  5. 這時候頁面上會顯示一組 Token,複製下來。注意!產生的 Token 內容只會在此時顯示一次,之後無法再查到,如果忘記 Token 就只能重新操作產生一次

到 Repository 將剛剛的 Token 設定成 Secret:

  1. 到想要自動發佈的 Repository -> 選擇 Settings -> 左邊列表選則 Secrets -> 點 New secret 按鈕。
  2. 「Name」欄位填 GH_ACCESS_TOKEN,「Value」欄位貼上剛剛複製的 Token。
  3. Add secret 按鈕,設定就完成了。

Step 5. 撰寫 GitHub Actions Workflow

萬事俱備,只剩下設定 GitHub Actions,讓它能自動幫我們製書和發佈到 GitHub Pages。

回到資料夾,新增一個 .github/workflows/build.yml 檔案:

$ mkdir -p .github/workflows
$ vi .github/workflows/build.yml

如果前面有依照建議的資料夾結構去放置檔案,這裏完全照抄即可,只需要把 USER_NAMEUSER_EMAIL 設定更換成你的 Git User Name 和 Email:

name: Build my gitbook and deploy to gh-pages

on:
  workflow_dispatch:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
    name: Build and deploy
    runs-on: ubuntu-latest
    env:
      MY_SECRET   : ${{secrets.GH_ACCESS_TOKEN}}
      USER_NAME   : <your_user_name>
      USER_EMAIL  : <your_email>
      BOOK_DIR    : book_sources

    steps:
    - name: Checkout 🛎️
      uses: actions/[email protected]
    - name: Build and Deploy 🚀
      uses: onejar99/[email protected]

上面是一個 GitHub Actions 的設定檔,稱為一個「workflow」。裡面用到官方的 checkout action,這幾乎是每個 workflow 的起手式。另外用到我自己寫的一個 gitbook action,負責將 markdown 檔製成 GitBook 靜態網站,並自動將網站檔案 commit 到 gh-pages branch。

Step 6. 將 Workflow 檔推上 GitHub,觸發自動發佈到 GitHub Pages

將剛剛新增的 workflow 檔進行 commit 和 push:

$ git add .github/workflows/build.yml
$ git commit -m "add workflow file"
$ git push

回到 GitHub Repository 頁面,點「Actions」tab,會看到有一個 workflow 任務被自動觸發執行中:

等到執行完畢變成綠勾勾,會看到自動建立了 gh-pages branch 並 commit GitBook 靜態網站的檔案:

這時候就能到 GitHub Pages 檢視 GitBook。以我的帳號為例,這個 Repository 的 GitHub Pages 連結是 https://onejar99.github.io/demo-build-and-publish-gitbook (因為我有設定自訂網域,GitHub 會自動幫我轉址成 https://books.onejar99.com/demo-build-and-publish-gitbook):

測試:編輯書籍內容,GitBook 會自動發佈更新

比如修改第一章的檔案並進行 push:

$ vi book_sources/articles/chapter-01.md
$ git add -u .
$ git commit -m "modify chapter 01"
$ git push

會看到 GitHub Actions 自動觸發 workflow 任務:

等 workflow 執行完畢,稍等幾分鐘,GitHub Pages 就會呈現更新後的內容。

Appendix: 在本機端預覽 gitbook 效果

如果你希望寫作後先在本機端預覽效果,我製作了 gitbook CLI 和輕量 http server 的 docker images 可以利用,前提是必須先在你的電腦安裝 Docker。

指令:

$ cd demo-build-and-publish-gitbook/book_sources/
$ docker run --rm -p 4000:4000 -v $(pwd):/gitbook onejar99/gitbook:light "gitbook init && gitbook install && gitbook build"
$ docker run --rm -p 8080:8080 -v $(pwd)/_book:/home/app/public onejar99/nodejs-live-server:node12.16.1

打開瀏覽器輸入 http://localhost:8080

結語

本文介紹的作法,很容易就能達到自架 GitBook 的目標。

這樣的模式也可以應用在其他靜態網站產生器,例如 VuePress。其實運用 CI/CD 工具將網站部署到 GitHub Pages 並不是什麼新鮮的 idea,我只是嘗試簡化設定的門檻,就近使用 GitHub Actions 工具,並事先製作好 action。

本文範例的完整檔案放在 GitHub Repository。如果使用本文的 gitbook action 有問題,歡迎到 action repo 發 issue 或在本文底下留言。

最後來閒聊一下。

閒聊:為什麼要花時間研究怎麼自架 GitBook

雖然棄坑 GitBook V2 官方平台,還是有許多替代服務,倒不是一定要執著 GitBook。例如我滿喜歡協作筆記服務 HackMD 的書籍模式,此外他們家的編輯器使用體驗我覺得很流暢,也很常用 HackMD 來寫一些筆記草稿。HackMD 也支援閱讀權限控管和公開發表功能,已經能取代 GitBook 很多使用情境。

題外話:目前對 HackMD 的小遺憾是無法改變筆記的預設權限,目前的預設權限是任何已登入的人都能編輯,變成每一篇筆記都要手動設定一次。可惜反應在留言區一年多,沒有得到產品團隊回應,也許產品團隊覺得其他功能對營運的效益更大。希望未來有機會看到這個功能實現。

既然有現成好用的免費服務,為什麼還要花時間研究怎麼自架 GitBook?

本文介紹的模式,我最喜歡的部分有兩點。

第一點是可以完全控制最後製書的成果。

在第三方平台可能要擔心哪天某個功能停止支援,或是平台改版,呈現的效果變得不如預期,控制權在平台商手上。例如我很喜歡 HackMD 的書籍模式,如果哪一天 HackMD 因為維護或產品策略上的考量決定拔掉書籍模式,或是改變書籍模式的呈現方式,我無論喜不喜歡都只能被迫接受,而且什麼時候會改變不受我控制。

不要覺得這不可能,即使大如 Google,收掉的服務也沒少過,甚至有些是深具意義的功能,例如最近 Google 旗下的 YouTube 宣布終止社群字幕功能,引來不少反彈聲浪。

另一個更現成、更血淋淋的例子 —— 曾經是開源分享的典範、擁抱開放精神的 GitBook,誰料得到變成如今這樣封閉商業化?

第二點是容易搬家。

在這個資訊爆炸、科技服務快速變革、改朝換代頻繁的時代,覺得看過太多曾經火紅、甚至曾經代表一個世代的服務宣布終止。例如無名小站(講得出這個名詞可能都暴露出年紀🤪)、Google Reader、近期的 PChome 信箱。

GitBook V2 的走鐘再次加深我對平台服務依賴的警戒。因此我現在選擇平台服務時的考量,只要是會在上面累積長期性資料的,第一個考慮的因素一定是萬一服務商不玩了,我怎麼搬家。

以書籍來說,最重要的是內容,託管空間或自動發佈工具怎麼換都無所謂,不影響內容。甚至如果書籍連結有設定 custom domain,託管空間或 CI/CD 選什麼工具一點也不重要。我的內容核心是 Markdown 原始檔,搬去哪都不用擔心。

我的選擇可以不是 GitHub Pages 或 GitHub Actions,我選擇這個組合,只因為這是現階段最容易取得、幾乎無成本、平台壽命風險低的組合方案。

References

發表留言