DevUI是一支兼具设计视角和工程视角的团队,服务于华为云 DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师。
官方网站: devui.design
Ng组件库: ng-devui(欢迎Star)
官方交流群:添加DevUI小助手(微信号:devui-official)
DevUIHelper插件: DevUIHelper-LSP(欢迎Star)
以前发过一个沸点,聊到前端为了提高业务交付效率,有必要去除对上游的依赖,此次想给你们分享下我本身在去后台依赖方面的一些实践,欢迎你们一块儿讨论!html
在整个研发链路上,后台的定位是给前端提供高效、稳定的API接口,前端经过这些API去获取须要的数据,并展现给用户。前端
因此要去除对后台的依赖,前端就须要本身模拟这些接口,并构造相应的测试数据。vue
为了在前端模拟后台接口,我给你们介绍第一件神器:JSON Server。node
如下是JSON Server官方对本身的定位:webpack
Get a full fake REST API with zero coding in less than 30 seconds (seriously)
无需写代码,在30秒内得到完整的REST API。
以我如今负责的DevCloud业务——XBoard看板项目——举栗子,有一个接口是获取某个看板下面的全部卡片信息(只保留关键字段),接口基本协议以下(接口协议提早跟后台协商好):git
GET /v1/[projectid]/[boardid]/cards { "error": null, "status": "success", "result": [ { "column_id": "7c489b6746fe4329aa8c869f4c13fab5", "card_list": [ { "id": "4634045604195569664", // 卡片ID "subject": "任务已ready,准备启动开发的任务", // 卡片主题 "sequence": "11203427", // 卡片序列号 "index": "12", // 序号(用于拖动排序) "archived": false, // 是否已归档 "blocked": false, // 是否设置阻塞 "is_parent": false, // 是否父卡片 "createdOn": "1598238210463", // 建立时间 "updatedOn": "1598238210463", // 最近更新时间 "parent": { // 父卡片 "subject": "设计完成,正在进行开发的需求", "id": "4634045604190851072" }, "board": { // 卡片所在的看板 "id": "1661625c5f72471a81979482ab148066", "name": "开发" }, "column": { // 状态列 "id": "7c489b6746fe4329aa8c869f4c13fab5", "name": "就绪", "type": "READY", "deleted": false }, "card_type": { // 卡片类型 "color": "#6CBFFF", "name": "任务", "icon": "icon-op-task", "id": "2" }, "author": { // 卡片做者 "name": "kagolzeng", "id": "05329882ba000f711ffec00c21191097", "nick_name": "kagol", "gender": "male" }, "updater": { // 最近更新者 "name": "kagolzeng", "id": "05329882ba000f711ffec00c21191097", "nick_name": "kagol", "gender": "male" } }, ... // 其余卡片 ] }, ... // 其余状态列 ] }
这个接口怎么用JSON Server模拟呢?github
只须要如下4步(假设已经有项目工程,好比:NG CLI工程):web
咱们一步一步来搭建一个Mock服务:正则表达式
在项目根目录下执行如下命令:npm
npm i -D json-server
在项目根目录下新建db.json文件,加上以前已经跟后台定好的接口数据(为避免重复,已省略部分字段):
{ "result": [ { "column_id": "7c489b6746fe4329aa8c869f4c13fab5", "card_list": [ { "id": "4634045604195569664", // 卡片ID "subject": "任务已ready,准备启动开发的任务", // 卡片主题 "board": { // 卡片所在的看板 "id": "1661625c5f72471a81979482ab148066", "name": "开发" }, "column": { // 状态列 "id": "7c489b6746fe4329aa8c869f4c13fab5", "name": "就绪", "type": "READY", "deleted": false }, "card_type": { // 卡片类型 "color": "#6CBFFF", "name": "任务", "icon": "icon-op-task", "id": "2" } } ] } ] }
只须要在package.json的scripts中编写Mock服务的启动脚本便可:
"mock": "node_modules/.bin/json-server --watch db.json --port 9090"
npm run mock
启动以后控制台显示:
在浏览器地址栏输入:http://localhost:9090/cards,便可查看该接口的返回数据
你们发现以上模拟后台接口的方式有什么问题了没?
测试数据的构造太麻烦!
若是每一个接口的返回数据都须要一个一个去构造,至少会有两个问题:
为了解决以上问题,我要给你们介绍第二件神器:Mock.js。
Mock.js对本身的定位是:
生成随机数据,拦截 Ajax 请求
Mock.js能够生成几乎任何你能想到的数据类型,好比数字、字符、布尔值、日期、颜色、图片、地址、URL、名字、标题、段落等,甚至还支持正则表达式。
将Mock.js集成进来也只须要简单的3个步骤:
为了集成Mock.js,咱们须要将以前的db.json改为db.js,并增长routes.json文件,能够将这两个文件放到根目录下的mock文件夹下。
mock/db.js var Mock = require('mockjs'); const CARDS = Mock.mock({ "error": null, "status": "success", "result|10": [{ // 生成10个状态列 "column_id": "@guid", "card_list|20": [{ // 状态列下有20张卡片 "id": "@guid", // 卡片ID "subject": '@title', // 卡片主题 "sequence": /d{8}/, // 卡片序列号 "index": "@integer(1, 100)", // 序号(用于拖动排序) "archived": "@boolean", // 是否已归档 "blocked": "@boolean", // 是否设置阻塞 "is_parent": "@boolean", // 是否父卡片 "createdOn": "@date", // 建立时间 "updatedOn": "@date", // 最近更新时间 "parent": { // 父卡片 "id": "@guid", "name": "@cword(2,10)" }, "board": { // 卡片所在的看板 "id": "@guid", "name": "@cword(2,10)" }, "column": { // 状态列 "id": "@guid", "name": "@cword(2,10)", "type": "@string('upper', 2, 20)", "deleted": "@boolean" }, "card_type": { // 卡片类型 "color": "@color", "name": "@cword(2,10)", "icon": /icon-[a-z]-{1-3}/, "id": "@integer(1, 100)" }, "author": { // 卡片做者 "name": "@name", "id": "@guid", "nick_name": "@name", "gender": "@string('lower', 4)" }, "updater": { // 最近更新者 "name": "@name", "id": "@guid", "nick_name": "@name", "gender": "@string('lower', 4)" } }] }] }); const API = () => ({ 'cards': CARDS, }); module.exports = API;
mock/routes.json { "/cards": "/cards" }
脚本命令也须要作相应的修改
"mock": "node_modules/.bin/json-server --watch mock/db.js --routes mock/routes.json --port 9090"
这时咱们从新使用:
npm run mock
命令启动Mock服务,在浏览器中输入
访问/cards接口:
能够看到Mock.js为咱们生成了很是多随机测试数据,以前构造这些数据但是要费很大的工夫。
而且为了构造这大量的测试数据,咱们只是在db.js中增长了不到50行代码,不用在担忧源文件体积太大的问题。
是否是很是便捷?
让咱们一块儿来试试业务中如何使用这些Mock接口,以及如何无缝切换成真实的后台接口吧。
假设咱们已经用NG CLI建立了一个项目,为了调用Mock接口,咱们须要引入Angular的HttpClientModule模块:
src/app/app.module.ts import { HttpClientModule } from '@angular/common/http'; imports: [ ..., HttpClientModule ]
而后注入Angular的HttpClient服务,就能够向Mock服务的/cards接口发起请求:
src/app/app.component.ts import { HttpClient } from '@angular/common/http'; constructor( private http: HttpClient ) {} ngOnInit() { this.http.get('http://localhost:9090/cards').subscribe(cards => { console.log('cards:', cards); }); }
获取到的接口数据以下:
聪明的你确定发现直接调用Mock服务的接口有问题:部署到测试环境或者现网怎么办?
由于环境上调用的确定是相应环境的后台接口,而不是Mock服务的接口,因此在本地开发时将接口代理到Mock服务,实际调用接口时不加具体的域名信息。
实际调用接口应该是如下的方式:
this.http.get('/v1/cards').subscribe(cards => { console.log('cards:', cards); });
为了作到无缝切换后台接口,即:无需修改任何代码,本地调用Mock服务接口,线上调用后台接口。
咱们须要在本地开发时将接口代理到Mock服务,可使用NG CLI提供代理配置proxyConfig:
angular.json "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "ng-demo:build", "port": 4600, "proxyConfig": "proxy.config.js" // 新增代理配置 }, ... }
代理配置文件:
proxy.config.js const PROXY_CONFIG = { '/v1': { target: 'http://localhost:9090/v1' } }; module.exports = PROXY_CONFIG;
咱们的Mock服务不须要作任何改变。
若是你使用的不是NG CLI,要怎么配置代理呢?
vue.config.js devServer: { proxy: { '/v1': { target: 'http://localhost:9090/v1' } } }
Webpack的写法和Vue CLI的差很少
webpack.config.js devServer: { proxy: { '/v1': { target: 'http://localhost:9090/v1' } } }
React稍微麻烦一点儿,须要安装http-proxy-middleware中间件。
const proxy = require("http-proxy-middleware"); module.exports = function(app) { app.use( proxy("/api/", { target: "http://localhost:9090/v1" }) ); };
若是你的项目使用TypeScript的话,通常都会给接口数据增长TS类型,我给你们介绍一个根据接口自动生成TS类型文件的神器:quicktype。
quicktype的定位是:
Generate types and converters from JSON, Schema, and GraphQL.
从JSON、Schema和GraphQL生成类型和转换器。
刚才咱们已经启动了咱们的Mock服务,在浏览器地址栏输入http://localhost:9090/cards,也能够查看/cards接口的返回数据,这时咱们可使用quicktype工具根,据接口地址生成相应的TS类型文件。
只须要2步便可:
npm i -g quicktype
quicktype http://localhost:9090/cards -o ./src/app/shared/types/card.interface.ts --runtime-typecheck
import { CardInterface } from './shared/types/card.interface'; this.http.get('/v1/cards').subscribe((cards: CardInterface) => { console.log('cards:', cards); });
使用TS类型有两个显而易见的好处:
一是类型校验和自动提示;
二是数据文档化和字段自动提醒和补齐。
类型校验和自动提示:
数据文档化和字段自动提醒和补齐:
本文主要介绍如何经过JSON Server和Mock.js两大神器,在前端搭建Mock服务,模拟后台接口,从而在开发阶段去除对后台的依赖,提高业务交付的效率。
欢迎你们评论交流!
源码地址:https://github.com/kagol/ng-mock-server
咱们是DevUI团队,欢迎来这里和咱们一块儿打造优雅高效的人机设计/研发体系。招聘邮箱:muyang2@huawei.com。
文/Kagol
往期文章推荐
XBoard项目的开发看板