1. 程式人生 > >前端有了這兩樣神器,再也不用追著後臺要介面啦

前端有了這兩樣神器,再也不用追著後臺要介面啦

![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215551343-599903765.png) > DevUI是一支兼具設計視角和工程視角的團隊,服務於華為雲[DevCloud](https://www.huaweicloud.com/devcloud/)平臺和華為內部數箇中後臺系統,服務於設計師和前端工程師。 > 官方網站:[devui.design](https://devui.design/) > Ng元件庫:[ng-devui](https://github.com/DevCloudFE/ng-devui)(歡迎Star) > 官方交流群:新增DevUI小助手(微訊號:devui-official) > DevUIHelper外掛:[DevUIHelper-LSP](https://github.com/sspku-yqLiu/DevUIHelper-LSP)(歡迎Star) 前言 -- 之前發過一個沸點,聊到前端為了提升業務交付效率,有必要去除對上游的依賴,這次想給大家分享下我自己在去後臺依賴方面的一些實踐,歡迎大家一起討論! ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215641371-977374547.png) 前端依賴後臺什麼? --------- 在整個研發鏈路上,後臺的定位是給前端提供高效、穩定的API介面,前端通過這些API去獲取需要的資料,並展示給使用者。 所以要去除對後臺的依賴,前端就需要自己模擬這些介面,並構造相應的測試資料。 怎麼模擬後臺介面? --------- 為了在前端模擬後臺介面,我給大家介紹第一件神器:[JSON Server](https://github.com/typicode/json-server)。 以下是JSON Server官方對自己的定位: > Get a full fake REST API with zero coding in less than 30 seconds (seriously) > 無需寫程式碼,在30秒內獲得完整的REST API。 以我現在負責的[DevCloud](https://www.huaweicloud.com/devcloud/)業務——[XBoard看板](https://support.huaweicloud.com/usermanual-projectman/devcloud_hlp_00021.html)專案——舉栗子,有一個介面是獲取某個看板下面的所有卡片資訊(只保留關鍵欄位),介面基本協議如下(介面協議提前跟後臺協商好): ```text 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模擬呢? 只需要以下4步(假設已經有專案工程,比如:[NG CLI](https://cli.angular.io/)工程): * 第1步:安裝JSON Server * 第2步:配置測試資料 * 第3步:編寫啟動指令碼命令 * 第4步:啟動Mock服務 我們一步一步來搭建一個Mock服務: 第1步:安裝JSON Server ----------------- 在專案根目錄下執行以下命令: ```text npm i -D json-server ``` 第2步:配置測試資料 ---------- 在專案根目錄下新建db.json檔案,加上之前已經跟後臺定好的介面資料(為避免重複,已省略部分欄位): ```text { "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" } } ] } ] } ``` 第3步:編寫啟動指令碼命令 ------------ 只需要在package.json的scripts中編寫Mock服務的啟動指令碼即可: ```text "mock": "node_modules/.bin/json-server --watch db.json --port 9090" ``` 第4步:啟動Mock服務 ------------ ```text npm run mock ``` 啟動之後控制檯顯示: ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215707672-762885155.png) 在瀏覽器位址列輸入:[http://localhost:9090/cards](http://localhost:9090/cards),即可檢視該介面的返回資料 ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215717681-517700122.png) 如何構造測試資料? --------- 大家發現以上模擬後臺介面的方式有什麼問題了沒? 測試資料的構造太麻煩! 如果每個介面的返回資料都需要一個一個去構造,至少會有兩個問題: * 一是每條記錄都自己手寫,太累,資料也太死; * 二是想要模擬大量的資料很難,且會導致專案原始檔體積變大。 為了解決以上問題,我要給大家介紹第二件神器:[Mock.js](http://mockjs.com/)。 Mock.js對自己的定位是: > 生成隨機資料,攔截 Ajax 請求 Mock.js可以生成幾乎任何你能想到的資料型別,比如數字、字元、布林值、日期、顏色、圖片、地址、URL、名字、標題、段落等,甚至還支援正則表示式。 將Mock.js整合進來也只需要簡單的3個步驟: * 第1步:修改JSON Server配置 * 第2步:修改指令碼命令 * 第3步:重啟Mock服務 第1步:修改JSON Server配置 ------------------- 為了整合Mock.js,我們需要將之前的db.json改成db.js,並增加routes.json檔案,可以將這兩個檔案放到根目錄下的mock資料夾下。 ```text 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; ``` ```text mock/routes.json { "/cards": "/cards" } ``` 第2步:修改指令碼命令 ---------- 指令碼命令也需要做相應的修改 ```text "mock": "node_modules/.bin/json-server --watch mock/db.js --routes mock/routes.json --port 9090" ``` 第3步:重啟Mock服務 ------------ 這時我們重新使用: ```text npm run mock ``` 命令啟動Mock服務,在瀏覽器中輸入 [http://localhost:9090/cards](http://localhost:9090/cards) 訪問/cards介面: ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215739657-1304380533.png) 可以看到Mock.js為我們生成了非常多隨機測試資料,之前構造這些資料可是要費很大的工夫。 並且為了構造這大量的測試資料,我們只是在db.js中增加了不到50行程式碼,不用在擔心原始檔體積太大的問題。 ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215751152-132817809.png) 是不是非常便捷? 讓我們一起來試試業務中如何使用這些Mock介面,以及如何無縫切換成真實的後臺介面吧。 一起來試試看吧 ------- 假設我們已經用NG CLI建立了一個專案,為了呼叫Mock介面,我們需要引入Angular的HttpClientModule模組: ```text src/app/app.module.ts import { HttpClientModule } from '@angular/common/http'; imports: [ ..., HttpClientModule ] ``` 直接呼叫Mock服務介面 ------------ 然後注入Angular的HttpClient服務,就可以向Mock服務的/cards介面發起請求: ```text 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); }); } ``` 獲取到的介面資料如下: ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215805696-1712293337.png) 使用代理無縫切換後臺介面 ------------ 聰明的你肯定發現直接呼叫Mock服務的介面有問題:部署到測試環境或者現網怎麼辦? 因為環境上呼叫的肯定是相應環境的後臺介面,而不是Mock服務的介面,所以在本地開發時將介面代理到Mock服務,實際呼叫介面時不加具體的域名資訊。 實際呼叫介面應該是以下的方式: ```text this.http.get('/v1/cards').subscribe(cards => { console.log('cards:', cards); }); ``` 為了做到無縫切換後臺介面,即:無需修改任何程式碼,本地呼叫Mock服務介面,線上呼叫後臺介面。 我們需要在本地開發時將介面代理到Mock服務,可以使用NG CLI提供代理配置proxyConfig: ```text angular.json "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "ng-demo:build", "port": 4600, "proxyConfig": "proxy.config.js" // 新增代理配置 }, ... } ``` 代理配置檔案: ```text proxy.config.js const PROXY_CONFIG = { '/v1': { target: 'http://localhost:9090/v1' } }; module.exports = PROXY_CONFIG; ``` 我們的Mock服務不需要做任何改變。 其他框架配置代理 -------- 如果你使用的不是NG CLI,要怎麼配置代理呢? ### Vue CLI配置代理 ```text vue.config.js devServer: { proxy: { '/v1': { target: 'http://localhost:9090/v1' } } } ``` ### Webpack配置代理 Webpack的寫法和Vue CLI的差不多 ```text webpack.config.js devServer: { proxy: { '/v1': { target: 'http://localhost:9090/v1' } } } ``` ### CreateReactApp配置代理 React稍微麻煩一點兒,需要安裝http-proxy-middleware中介軟體。 ```text const proxy = require("http-proxy-middleware"); module.exports = function(app) { app.use( proxy("/api/", { target: "http://localhost:9090/v1" }) ); }; ``` 增加TS型別 ------ 如果你的專案使用TypeScript的話,一般都會給介面資料增加TS型別,我給大家介紹一個根據介面自動生成TS型別檔案的神器:[quicktype](https://github.com/quicktype/quicktype)。 quicktype的定位是: > Generate types and converters from JSON, Schema, and GraphQL. > 從JSON、Schema和GraphQL生成型別和轉換器。 剛才我們已經啟動了我們的Mock服務,在瀏覽器位址列輸入[http://localhost:9090/cards](http://localhost:9090/cards),也可以檢視/cards介面的返回資料,這時我們可以使用quicktype工具根,據介面地址生成相應的TS型別檔案。 只需要2步即可: * 第1步:安裝quicktype * 第2步:生成TS型別檔案 第1步:安裝quicktype --------------- ```text npm i -g quicktype ``` 第2步:生成TS型別檔案 ------------ ```text quicktype http://localhost:9090/cards -o ./src/app/shared/types/card.interface.ts --runtime-typecheck ``` 使用TS型別 ------ ```text import { CardInterface } from './shared/types/card.interface'; this.http.get('/v1/cards').subscribe((cards: CardInterface) => { console.log('cards:', cards); }); ``` 使用TS型別有兩個顯而易見的好處: 一是型別校驗和自動提示; 二是資料文件化和欄位自動提醒和補齊。 型別校驗和自動提示: ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215822763-1383905656.png) 資料文件化和欄位自動提醒和補齊: ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215828281-292554243.png) 小結 -- 本文主要介紹如何通過JSON Server和Mock.js兩大神器,在前端搭建Mock服務,模擬後臺介面,從而在開發階段去除對後臺的依賴,提升業務交付的效率。 歡迎大家評論交流! 原始碼地址:[https://github.com/kagol/ng-mock-server](https://github.com/kagol/ng-mock-server) 加入我們 ---- 我們是DevUI團隊,歡迎來這裡和我們一起打造優雅高效的人機設計/研發體系。招聘郵箱:[email protected]。 文/Kagol 往期文章推薦 [《使用Git,10件你可能需要“反悔”的事》](https://www.cnblogs.com/kagol/p/14076276.html) [《手把手教你使用Vue/React/Angular三大框架開發Pagination分頁元件》](https://www.cnblogs.com/kagol/p/14071347.html) [《現代富文字編輯器Quill的內容渲染機制》](https://www.cnblogs.com/kagol/p/14063753.html) 附錄:XBoard看板專案一覽 --------------- [XBoard專案](https://support.huaweicloud.com/usermanual-projectman/devcloud_hlp_00021.html)的開發看板 ![](https://img2020.cnblogs.com/blog/296720/202012/296720-20201203215845356-977270