用 Flask + Vue.Js 实现 SPA 显示产品发布信息

#

起因

近期一直在帮公司做和产品发布的流程和自动化相关的改进工作,主要是写了一些 Python + bash + Jenkinsfile 来实现 Jenkins Pipeline,效果还算不错,做产品发布比以前省心了不少。于是想着可以再做一个 Web 页面,用来展示和产品发布相关的信息,方便日常的维护工作。刚好看到网上这样一篇文章Full-stack single page application with Vue.js and Flask, 于是打算用类似的方式来实现一个SPA,顺便了解一下前端的Vue.js框架。

术语

SPA - Single Page Application

程序结构

程序的目录结构是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
├── backend
│   ├── README.md
│   ├── archive
│   ├── collector.py
│   ├── conf
│   │   ├── logging.cfg
│   │   └── main.cfg
│   ├── daemon.py
│   ├── errors.py
│   ├── logs
│   └── requirements.txt
└── www
├── __init__.py
├── __main__.py
├── app.py
├── conf
│   └── main.cfg
├── logging_config.py
├── logs
├── requirements.txt
├── setup.py
├── static
│   ├── css
│   │   └── main.css
│   └── imgs
│   └── zuora-logo-white-93.png
└── templates
├── index.html
└── static -> ../static/

backend 目录里是一个 Python 应用负责收集产品与发布相关的信息。
www 目录里主要是一个前端程序 Python 程序提供REST API 和一个index.html静态页面,Vue.js 相关代码都在 index.html 里。

用图说话那基本上就是这样的:
flask-vue-spa-1

技术点和总结

  1. 后台应用的 daemon 实现,直接用了开源项目 python-daemon daemon.py 的源代码。pip 里其实可以直接安装 python-daemon 库, 不过这个是另一个项目实现的,以后想用的话可以先看一下这个文档

  2. 后台collector里用到的fabric也是 Python 里非常有用的库,建立在Invoke (subprocess command execution and command-line features)Paramiko (SSH protocol implementation)之上,用起来感觉很方便,对开发 CMDB 的项目来说很有帮助。

  3. 前端的实现是 Python Flask + Vue.js, 由于 Vue.js 模板和 Flask Jinji2 在展示的时候有些预定义的分隔字符的冲突,所以在Flask app对象上需要做下面的处理:

    1
    2
    3
    @app.route('/')
    def index():
    return render_template('index.html')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class CustomFlask(Flask):
    jinja_options = Flask.jinja_options.copy()
    jinja_options.update(dict(
    block_start_string='{%',
    block_end_string='%}',
    variable_start_string='(?',
    variable_end_string='?)',
    comment_start_string='{#',
    comment_end_string='#}',
    ))


    app = CustomFlask(__name__)

其实也可以通过其它方式来解决这个问题:

  • 不使用 render_template(‘index.html’) 而是通过 nginx 或者 apache 返回 index.html 页面。
  • 在Vue 里重定义 delimiters,参考 stackoverflow 上的这个问题
  1. Vue.js 不愧是渐进式的 Javascript MVVM 框架, 容易上手。结合 bootstrap-vue 能够让你很方便地做出一个简单的前端页面。对于像我这种前端小白,以前只会撸 DOM 里那些 getElementById() 和 getElementByClassName() 方法的人来说真是福音。

  2. index.html 里调用 REST API实际上用到的是 axios 框架, 想写出一个好的SPA, 个人感觉在 REST API 的返回内容的设计上也是要有技巧的。目前觉得有两点, 一是返回的JSON在层级上不要太多,否则在客户端处理起来很麻烦, 而是一次性返回尽量多的内容,避免来回调用REST API 太多次,否则很容易导致因为这样的多次调用页面在加载和刷新的时候很慢。