尽管没有特别的动力去构建一个全新的CMS,可是我仍是愿意去撰文一篇来书写如何去作这样的事——编辑-发布-开发分离模式是如何工做的。微服务是咱们对于复杂应用的一种趋势,编辑-发布-开发分离模式则是另一种趋势。在上篇文章《Repractise架构篇一: CMS的重构与演进》中,咱们说到编辑-发布-开发分离模式。javascript
如先前提到的,Carrot使用了下面的方案来搭建他们的静态内容的CMS。css
在这个方案里内容是用Contentful来发布他们的内容。而在我司ThoughtWorks的官网里则采用了Github来管理这些内容。因而若是让咱们写一个基于Github的CMS,那么架构变成了这样:html
或许你也用过Hexo / Jekyll / Octopress这样的静态博客,他们的原理都是相似的。咱们有一个代码库用于生成静态页面,而后这些静态页面会被PUSH到Github Pages上。前端
从咱们设计系统的角度来讲,咱们会在Github上有三个代码库:java
Content。用于存放编辑器生成的JSON文件,这样咱们就能够GET这些资源,并用Backbone / Angular / React 这些前端框架来搭建SPA。jquery
Code。开发者在这里存放他们的代码,如主题、静态文件生成器、资源文件等等。git
Builder。在这里它是运行于Travis CI上的一些脚本文件,用于Clone代码,并执行Code中的脚本。程序员
以及一些额外的服务,当且仅当你有一些额外的功能需求的时候。github
Extend Service。当咱们须要搜索服务时,咱们就须要这样的一些服务。如我正考虑使用Python的whoosh来完成这个功能,这时候我计划用Flask框架,可是只是计划中——由于没有合适的中间件。npm
Editor。相比于前面的那些知识这一步适合更重要,也就是为何生成的格式是JSON而不是Markdown的原理。对于非程序员来讲,要熟练掌握Markdown不是一件容易的事。因而,一个考虑中的方案就是使用 Electron + Node.js来生成API,最后经过GitHub API V3来实现上传。
So,这一个过程是如何进行的。
整个过程的Pipeline以下所示:
编辑使用他们的编辑器来编辑的内容并点击发布,而后这个内容就能够经过GitHub API上传到Content这个Repo里。
这时候须要有一个WebHooks监测到了Content代码库的变化,便运行Builder这个代码库的Travis CI。
这个Builder脚本首先,会设置一些基本的git配置。而后clone Content和Code的代码,接着运行构建命令,生成新的内容。
而后Builder Commit内容,并PUSH内容。
这里还依赖于WebHook这个东西——还没想到一个合适的解决方案。下面,咱们对里面的内容进行一些拆解,Content里面因为是JSON就很少解释了。
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']);
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
这里的静态文件内容就是最后咱们要发布的内容。
还须要作的一件事情就是:
grunt.registerTask('dev', ['default', 'connect:server', 'watch:site']);
用于开发阶段这样的代码就够了,这个和你使用WebPack + React 彷佛相差不了多少。
在这种情形中,编辑可否完成工做就不依赖于网站——脱稿又少了 个借口。这时候网站出错的几率过小了——你不须要一个缓存服务器、HTTP服务器,因为没有动态生成的内容,你也不须要守护进程。这些内容都是静态文件,你能够将他们放在任何能够提供静态文件托管的地方——CloudFront、S3等等。或者你再相信本身的服务器,Nginx但是全球第二好(第一还没出现)的静态文件服务器。
开发人员只在须要的时候去修改网站的一些内容。
So,你可能会担忧若是这时候修改的东西有问题了怎么办。
使用这种模式就意味着你须要有测试来覆盖这些构建工具、生成工具。
相比于本身的代码,别人的CMS更可靠?
须要注意的是若是你上一次构建成功,你生成的文件都是正常的,那么你只须要回滚开发相关的代码便可。旧的代码仍然能够工做得很好。
其次,因为生成的是静态文件,查错的成本就比较低。
最后,从新放上以前的静态文件。