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項目的開發看板