你不再需要動態網頁——編輯-釋出-開發分離

Phodal發表於2015-11-17

​儘管沒有特別的動力去構建一個全新的CMS,但是我還是願意去撰文一篇來書寫如何去做這樣的事——編輯-釋出-開發分離模式是如何工作的。微服務是我們對於複雜應用的一種趨勢,編輯-釋出-開發分離模式則是另外一種趨勢。在上篇文章《Repractise架構篇一: CMS的重構與演進》中,我們說到編輯-釋出-開發分離模式。

系統架構

如先前提到的,Carrot使用了下面的方案來搭建他們的靜態內容的CMS。

Carrot

在這個方案裡內容是用Contentful來發布他們的內容。而在我司ThoughtWorks的官網裡則採用了Github來管理這些內容。於是如果讓我們寫一個基於Github的CMS,那麼架構變成了這樣:

Github 編輯-釋出-開發

或許你也用過Hexo / Jekyll / Octopress這樣的靜態部落格,他們的原理都是類似的。我們有一個程式碼庫用於生成靜態頁面,然後這些靜態頁面會被PUSH到Github Pages上。

從我們設計系統的角度來說,我們會在Github上有三個程式碼庫:

  1. Content。用於存放編輯器生成的JSON檔案,這樣我們就可以GET這些資源,並用Backbone / Angular / React 這些前端框架來搭建SPA。
  2. Code。開發者在這裡存放他們的程式碼,如主題、靜態檔案生成器、資原始檔等等。
  3. Builder。在這裡它是執行於Travis CI上的一些指令碼檔案,用於Clone程式碼,並執行Code中的指令碼。

以及一些額外的服務,當且僅當你有一些額外的功能需求的時候。

  1. Extend Service。當我們需要搜尋服務時,我們就需要這樣的一些服務。如我正考慮使用Python的whoosh來完成這個功能,這時候我計劃用Flask框架,但是隻是計劃中——因為沒有合適的中介軟體。
  2. Editor。相比於前面的那些知識這一步適合更重要,也就是為什麼生成的格式是JSON而不是Markdown的原理。對於非程式設計師來說,要熟練掌握Markdown不是一件容易的事。於是,一個考慮中的方案就是使用 Electron + Node.js來生成API,最後通過GitHub API V3來實現上傳。

So,這一個過程是如何進行的。

使用者場景

整個過程的Pipeline如下所示:

  1. 編輯使用他們的編輯器來編輯的內容並點選發布,然後這個內容就可以通過GitHub API上傳到Content這個Repo裡。
  2. 這時候需要有一個WebHooks監測到了Content程式碼庫的變化,便執行Builder這個程式碼庫的Travis CI。
  3. 這個Builder指令碼首先,會設定一些基本的git配置。然後clone Content和Code的程式碼,接著執行構建命令,生成新的內容。
  4. 然後Builder Commit內容,並PUSH內容。

這裡還依賴於WebHook這個東西——還沒想到一個合適的解決方案。下面,我們對裡面的內容進行一些拆解,Content裡面由於是JSON就不多解釋了。

Builder: 構建工具

Github與Travis之間,可以做一個自動部署的工具。相信已經有很多人在Github上玩過這樣的東西——先在Github上生成Token,然後用travis加密:

travis encrypt-file ssh_key --add

加密後的Key就會儲存到.travis.yml檔案裡,然後就可以在Travis CI上push你的程式碼到Github上了。

接著,你需要建立個deploy指令碼,並且在after_success執行它:

after_success: - test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" && bash deploy.sh

在這個指令碼里,你所需要做的就是clone content和code中的程式碼,並執行code中的生成指令碼,生成新的內容後,提交程式碼。

#!/bin/bash

set -o errexit -o nounset

rev=$(git rev-parse --short HEAD)

cd stage/

git init
git config user.name "Robot"
git config user.email "robot@phodal.com"

git remote add upstream "https://$GH_TOKEN@github.com/phodal-archive/echeveria-deploy.git"
git fetch upstream
git reset upstream/gh-pages

git clone https://github.com/phodal-archive/echeveria-deploy code
git clone https://github.com/phodal-archive/echeveria-content content
pwd
cp -a content/contents code/content

cd code

npm install
npm install grunt-cli -g
grunt 
mv dest/* ../
cd ../
rm -rf code
rm -rf content

touch .

if [ ! -f CNAME ]; then
    echo "deploy.baimizhou.net" > CNAME
fi

git add -A .
git commit -m "rebuild pages at ${rev}"
git push -q upstream HEAD:gh-pages

這就是這個builder做的事情——其中最主要的一個任務是grunt,它所做的就是:

grunt.registerTask('default', ['clean', 'assemble', 'copy']);

Code: 靜態頁面生成

Assemble是一個使用Node.js,Grunt.js,Gulp,Yeoman 等來實現的靜態網頁生成系統。這樣的生成器有很多,Zurb Foundation, Zurb Ink, Less.js / lesscss.org, Topcoat, Web Experience Toolkit等組織都使用這個工具來生成。這個工具似乎上個Release在一年多以前,現在正在開始0.6。雖然,這並不重要,但是還是順便一說。

我們所要做的就是在我們的Gruntfile.js中寫相應的生成程式碼。

assemble: {
  options: {
    flatten: true,
    partials: ['templates/includes/*.hbs'],
    layoutdir: 'templates/layouts',
    data: 'content/blogs.json',
    layout: 'default.hbs'
  },
  site: {
    files: {'dest/': ['templates/*.hbs']}
  },
  blogs: {
    options: {
      flatten: true,
      layoutdir: 'templates/layouts',
      data: 'content/*.json',
      partials: ['templates/includes/*.hbs'],
      pages: pages
    },
    files: [
      { dest: './dest/blog/', src: '!*' }
    ]
  }
}

配置中的site用於生成頁面相關的內容,blogs則可以根據json檔案的檔名生成對就的html檔案儲存到blog目錄中。

生成後的目錄結果如下圖所示:

 .
├── about.html
├── blog
│   ├── blog-posts.html
│   └── blogs.html
├── blog.html
├── css
│   ├── images
│   │   └── banner.jpg
│   └── style.css
├── index.html
└── js
    ├── jquery.min.js
    └── script.js

7 directories, 30 files

這裡的靜態檔案內容就是最後我們要釋出的內容。

還需要做的一件事情就是:

javascript grunt.registerTask('dev', ['default', 'connect:server', 'watch:site']);

用於開發階段這樣的程式碼就夠了,這個和你使用WebPack + React 似乎相差不了多少。

編輯-釋出-開發分離

在這種情形中,編輯能否完成工作就不依賴於網站——脫稿又少了 個藉口。這時候網站出錯的概率太小了——你不需要一個快取伺服器、HTTP伺服器,由於沒有動態生成的內容,你也不需要守護程式。這些內容都是靜態檔案,你可以將他們放在任何可以提供靜態檔案託管的地方——CloudFront、S3等等。或者你再相信自己的伺服器,Nginx可是全球第二好(第一還沒出現)的靜態檔案伺服器。

開發人員只在需要的時候去修改網站的一些內容。

So,你可能會擔心如果這時候修改的東西有問題了怎麼辦。

  1. 使用這種模式就意味著你需要有測試來覆蓋這些構建工具、生成工具。
  2. 相比於自己的程式碼,別人的CMS更可靠?

需要注意的是如果你上一次構建成功,你生成的檔案都是正常的,那麼你只需要回滾開發相關的程式碼即可。舊的程式碼仍然可以工作得很好。

其次,由於生成的是靜態檔案,查錯的成本就比較低。

最後,重新放上之前的靜態檔案。

相關文章