Last Updated on 2023-08-03 by OneJar
自從對新版 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 (前置工作)
你需要準備以下東西:
- 申請一個 GitHub 帳號。
- 最基本的 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
重點:
- 重要!把 GitBook 內容相關的檔案全部放在
book_sources
底下。 README.md
是必要檔案,會成為 Introduction 頁面。SUMMARY.md
是必要檔案,會成為左邊的目錄。- 非必要,但建議設一個資料夾
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:
- 點右上角帳號的頭像 -> 選擇
Settings
-> 左邊列表選擇最底下的Developer settings
-> 下個頁面的左邊列表選擇Personal access tokens
。 - 點擊
Generate new token
按鈕。 - 輸入 Token 的描述,權限勾選
repo:status
和public_repo
兩個項目。 - 點最下面的
Generate token
按鈕。 - 這時候頁面上會顯示一組 Token,複製下來。注意!產生的 Token 內容只會在此時顯示一次,之後無法再查到,如果忘記 Token 就只能重新操作產生一次。
到 Repository 將剛剛的 Token 設定成 Secret:
- 到想要自動發佈的 Repository -> 選擇
Settings
-> 左邊列表選則Secrets
-> 點New secret
按鈕。 - 「Name」欄位填
GH_ACCESS_TOKEN
,「Value」欄位貼上剛剛複製的 Token。 - 點
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_NAME
和 USER_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 :
障礙排除: Oops something wrong! exit code: 128
如果執行 GitHub Actions 遇到以下錯誤:
[INFO] Push to gh-pages...
On branch gh-pages
nothing to commit, working tree clean
fatal: could not read Password for 'https://***@github.com': No such device or address
ret=[128]
Oops something wrong! exit code: 128
通常是 token 過期或沒有設定成功,請照「Step 4. 設定 GitHub Access Token」重新設定。
結語
本文介紹的作法,很容易就能達到自架 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 的小遺憾是無法改變筆記的預設權限,目前的預設權限是任何已登入的人都能編輯,變成每一篇筆記都要手動設定一次。可惜反應在留言區一年多,沒有得到產品團隊回應,也許產品團隊覺得其他功能對營運的效益更大。希望未來有機會看到這個功能實現。
2021/11/14 updated: 最近發現 HackMD 推出個人付費方案 (Prime Personal Plan),包含了自訂預設權限的功能,該說難怪留言區遲遲沒有得到正面回應嗎,原來這項功能被規劃為付費功能。雖然免費仔如我覺得有點扼腕(誤),但平心而論這樣的收費規劃算合理範圍,一來一個產品需要合理盈利,二來功能性上 HackMD 並沒有閹割免費版原本的權益,如果不想買單,還是可以靠自己手動修改每篇筆記的權限設定,如果想要更便利,就付費升級。 HackMD 個人付費方案每個月 $4 美元,約一百初頭台幣,用戶依自己的使用習慣決定需不需要付費升級囉。
既然有現成好用的免費服務,為什麼還要花時間研究怎麼自架 GitBook?
本文介紹的模式,我最喜歡的部分有兩點。
第一點是可以完全控制最後製書的成果。
在第三方平台可能要擔心哪天某個功能停止支援,或是平台改版,呈現的效果變得不如預期,控制權在平台商手上。例如我很喜歡 HackMD 的書籍模式,如果哪一天 HackMD 因為維護或產品策略上的考量決定拔掉書籍模式,或是改變書籍模式的呈現方式,我無論喜不喜歡都只能被迫接受,而且什麼時候會改變不受我控制。
不要覺得這不可能,即使大如 Google,收掉的服務也沒少過,甚至有些是深具意義的功能,例如最近 Google 旗下的 YouTube 宣布終止社群字幕功能,引來不少反彈聲浪。
另一個更現成、更血淋淋的例子 —— 曾經是開源分享的典範、擁抱開放精神的 GitBook,誰料得到變成如今這樣封閉商業化?
第二點是容易搬家。
在這個資訊爆炸、科技服務快速變革、改朝換代頻繁的時代,覺得看過太多曾經火紅、甚至曾經代表一個世代的服務宣布終止。例如無名小站(講得出這個名詞可能都暴露出年紀🤪)、Google Reader、近期的 PChome 信箱。
GitBook V2 的走鐘再次加深我對平台服務依賴的警戒。因此我現在選擇平台服務時的考量,只要是會在上面累積長期性資料的,第一個考慮的因素一定是萬一服務商不玩了,我怎麼搬家。
以書籍來說,最重要的是內容,託管空間或自動發佈工具怎麼換都無所謂,不影響內容。甚至如果書籍連結有設定 custom domain,託管空間或 CI/CD 選什麼工具一點也不重要。我的內容核心是 Markdown 原始檔,搬去哪都不用擔心。
我的選擇可以不是 GitHub Pages 或 GitHub Actions,我選擇這個組合,只因為這是現階段最容易取得、幾乎無成本、平台壽命風險低的組合方案。
版本修正
2022/01/16 updated: v1.0.2 修復 anchor-navigation-ex 套件問題
經網友回報發現,如果依照本文步驟操作,使用到 gitbook plugin anchor-navigation-ex
,最近可能會遇到部署失敗。原因是 anchor-navigation-ex 這個套件所拉的其他相依套件有出新版,與既有 anchor-navigation-ex 版本有相容性問題。
解決方法是升級到 onejar99/[email protected]
版本。
2023/08/03 updated: v1.0.3 修復 exec /entrypoint.sh: no such file or directory 問題
經網友回報最近執行會出現 exec /entrypoint.sh: no such file or directory
錯誤 ,發現是我最近對使用的 based image 做改版,沒注意到這個 GitHub Action 會去拉到新版 based image,發生不相容問題。
解決方法是升級到 onejar99/[email protected]
版本。
References
- GitHub Actions Documentation – GitHub Docs
- 用 VuePress + Github Pages 取代小氣鬼的 Gitbook 吧 – Mr. 沙先生
- 遭微軟併購消息傳出,GitHub使用者大遷徙,蜂擁轉移至GitLab | iThome
- 為何微軟要買下 GitHub? | TechOrange
- 社群字幕拜拜!YouTube 宣布九月終止社群協力功能 – INSIDE
- Google Reader 將在 7月1日關閉,推薦6個 RSS 閱讀器替代方案 | T客邦
- PChome 信箱終止服務!網友怨:購物無法改綁其他信箱 – INSIDE
照本文做到actions時,出現以下錯誤:
Date: Wed Jul 20 00:33:41 2022 +0800
first commit
[INFO] Push to gh-pages…
On branch gh-pages
nothing to commit, working tree clean
fatal: could not read Password for ‘https://***@github.com’: No such device or address
ret=[128]
Oops something wrong! exit code: 128
請問大神有解法嗎QQ?
Hi 我踩過同樣的錯誤,這種狀況應該是 token 過期或沒有設定成功,請照「Step 4. 設定 GitHub Access Token」重新設定試試
您好, 冒昧請一教一下, 先前照著此篇教學也成功建置了自己的gitbook, 目前想自行新增一些內容, 卻 出現 gitbook serve 時, 發生找不到 plugin 的錯誤如下
Live reload server started on port: 35729
Press CTRL+C to quit …
info: 8 plugins are installed
info: 12 explicitly listed
Error: Couldn’t locate plugins “anchor-navigation-ex, edit-link, copy-code-button, ga, theme-comscore”, Run ‘gitbook install’ to install plugins from registry.
又試了, gitbook install 卻又發生另一個錯誤如下
$ gitbook install
info: installing 5 plugins using [email protected]
info:
info: installing plugin “anchor-navigation-ex”
info: install plugin “anchor-navigation-ex” (*) from NPM with version 1.0.14
loadExtraneous -> resolve / |####################################################################################################################################————————————————————————————————————|
C:\Users\{MY_ACCOUT}\.gitbook\versions\3.2.3\node_modules\npm\lib\install\deps.js:607
return Object.keys(child.package.bin).some(function (bin) {
^
TypeError: Cannot convert undefined or null to object
上述情況在先前是沒發生的, 而這目前雖不影響我已放上github的內容, 但卻變成無法順利在publish前先在本機作檢視的動作
不知道您是否方便指點一下? 謝謝!
Hi 這是 gitbook plugin anchor-navigation-ex 套件發生版本衝突導致,詳情可以參考文章裡「2022/01/16 updated: v1.0.2 修復 anchor-navigation-ex 套件問題」段落。
如果想在本機測試,解決方法是 `git install` 前先執行一次 `npm i [email protected]` :
commands:
————————————————————
# rm -rf node_modules \
&& npm i [email protected] \
&& gitbook init && gitbook install && gitbook build
————————————————————
如果想 publish 到 GitHub Pages,GitHub Action 版本記得升級 `onejar99/[email protected]`
感謝說明以及提供解法, 參考您的指點已解決!
作者您好!我照著此文章操作,但Workflow的部分一直出錯, 我懷疑是 uses: onejar99/[email protected] 這行的問題, 想請問該如何修改,謝謝。
Hi 建議描述一下錯誤情況或 error log,或直接貼你的 GitHub Repository 連結,才可能知道你遇到什麼問題喔。