摘要:前端開發(fā)如何做好本地接口模擬之前有寫過一篇本地化接口模擬前后端并行開發(fā),講到過本地接口模擬,但不太細致。有哪些途徑本地接口模擬一般分為工具層面和代碼層面。因為本地接口模擬功能主要是針對的返回值為格式的異步請求,所以這種方式主要用文件。
前端開發(fā)如何做好本地接口模擬
之前有寫過一篇 本地化接口模擬、前后端并行開發(fā),講到過本地接口模擬,但不太細致。這次細細的說說本地接口模擬。
1. 有什么好處本地接口模擬最大的好處就是能夠使前后端項目解耦,前端更專注于開發(fā),減少線上調(diào)試,以此提升開發(fā)效率。
2. 有哪些途徑本地接口模擬一般分為工具層面和代碼層面。
3. 工具層面就工具層面而言,一般是由項目的構(gòu)建工具提供的功能。比如,當(dāng)我們用 webpack-dev-server、webpack-dev-middleware + browser-sync 等工具時,就可以向工具里添加本地接口模擬功能。
</>復(fù)制代碼
注:這里不講解工具如 webpack-dev-server、webpack-dev-middleware + browser-sync 等的用法,如有需要,可以自己去了解一下
下面以 webpack-dev-server 為例進行講解,其他工具類似。
3.1 靜態(tài)文件最簡單的,我們可以用靜態(tài) json 文件做本地接口模擬功能。
</>復(fù)制代碼
|-- / # 項目根目錄
|-- mock/ # 模擬數(shù)據(jù)目錄(可以自定義)
|-- 1.json
|-- 2.json
|-- ...
|-- ... # 其他文件
然后用 webpack-dev-server 以項目根目錄為基地址來開啟本地開發(fā)調(diào)試,在頁面中就可以這樣訪問:
</>復(fù)制代碼
fetch("/mock/1.json"); // 訪問 1.json
fetch("/mock/2.json"); // 訪問 2.json
# 可以將 fetch 換成其他請求方式
這種方式可以訪問項目中所有的文件,不光是 json 文件,其他的如 html、js、css 之類的文本文件、如圖片之類的二進制文件也可以訪問。另外,只要文件有更新,刷新瀏覽器頁面就可以重新獲取新的文件,沒有緩存。
因為本地接口模擬功能主要是針對的返回值為 json 格式的異步請求,所以這種方式主要用 json 文件。
這種方式是最簡單、快捷、使用難度最低的方式。
3.2 動態(tài)注冊接口使用靜態(tài)文件做本地接口模擬功能主要存在以下的一些問題:
靜態(tài)文件只能以 get 方法訪問
輸入數(shù)據(jù)是靜態(tài)的,不能做運算、循環(huán)、判斷等,也不能根據(jù)請求參數(shù)做出不同的響應(yīng)
本地接口名與服務(wù)器上的接口名不一樣,這就比較麻煩了,每次上線到服務(wù)器的時候都得改接口名
所以,多數(shù)情況下,都會采用動態(tài)注冊接口的方式做本地接口模擬功能。
這種方式是用 js 文件編寫一系列的 路由 => 響應(yīng) 映射,然后動態(tài)的把定義好的接口注冊到工具實例中。
目錄結(jié)構(gòu):
</>復(fù)制代碼
|-- / # 項目根目錄
|-- mock/ # 模擬數(shù)據(jù)目錄(可以自定義)
|-- user.js
|-- home.js
|-- ...
|-- ... # 其他文件
示例 mock 文件的寫法(可以自定規(guī)范,下面只是演示):
</>復(fù)制代碼
# mock/user.js
module.exports = {
"GET /user/profile": { ... }, // 直接返回一個對象
"POST /user/update": (req, res) => { ... }, // 根據(jù) `req, res` 的自定義響應(yīng)
...
};
# mock/home.js
const mockjs = require("mockjs");
module.exports = {
"GET /home/list": mockjs.mock({ // 用 mockjs 輔助生成假數(shù)據(jù)
"list|1-10": [{ "id|+1": 1 }],
}),
};
注:
上面的寫法只是示例,可以自定規(guī)范、書寫格式等
可以用 mockjs 庫來幫助生成假數(shù)據(jù)
webpack-dev-server 的相關(guān)配置:
</>復(fù)制代碼
# webpack.config.js
const beforeDevServer = app => {
// 在這里讀取 mock 目錄下的所有文件,按照一定的規(guī)范和格式,載入動態(tài)接口
// 比如:
app.get("/user/profile", function(req, res) {
res.json({ ... }); // 返回文件中定義的 `GET /user/profile` 的值
});
app.post("/user/update", function(req, res) {
handle(req, res); // handle:文件中定義的 `POST /user/update` 的自定義處理函數(shù)
});
...
};
module.exports = {
//...
devServer: {
before: beforeDevServer,
}
};
然后用 webpack-dev-server 開啟本地開發(fā)調(diào)試,在頁面中就可以這樣訪問:
</>復(fù)制代碼
fetch("/user/profile"); // 訪問 /user/profile
fetch("/user/update", {method: "post", body: { ... }});
// 訪問 /user/update
fetch("/home/list"); // 訪問 /home/list
# 可以將 fetch 換成其他請求方式
一般來說,我們還會用上 chokidar 來監(jiān)聽 mock 目錄下的文件變動,來更新路由及其響應(yīng),以此能夠做到每次訪問到的都是最新的資源(因為 node 針對某個模塊只會加載一次)。
</>復(fù)制代碼
const chokidar = require("chokidar");
const watcher = chokidar.watch("./mock");
watcher.on("change", path => {
// 先清除模塊緩存,保證加載最新的資源
if (require.cache[path]) delete require.cache[path];
const mapObj = require(path);
// 接下來把映射對象 mapObj 重新映射到 app 中
...
});
這種方式比較復(fù)雜,尤其是對項目搭建者要求比較高,需要對相關(guān)工具有深入的了解,好在社區(qū)已經(jīng)有封裝好的工具:roadhog。
但這種方式對使用者是很棒的,因為能夠完全模擬服務(wù)器接口,包括接口名、HTTP 方法、參數(shù)、返回值等,所以同樣的代碼既可以在本地運行,也可以在服務(wù)器上運行。
所以,這也是比較推薦的方式。
3.3 使用代理</>復(fù)制代碼
注:上面的代碼只是演示構(gòu)建過程,并不保證可以運行
這種方式是把本地模擬文件寫在另一個多帶帶項目里,然后使用使用代理的方式,訪問模擬接口。
mock 項目(以 koa 為例):
</>復(fù)制代碼
const Koa = require("koa");
const Router = require("koa-router");
const app = new Koa();
const router = new Router();
router.get("/api/user/profile", (ctx, next) => {
ctx.body = { ... };
});
router.post("/api/user/update", (ctx, next) => {
// ...
});
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(3000);
app 應(yīng)用項目:
webpack-dev-server 的相關(guān)配置:
</>復(fù)制代碼
# webpack.config.js
module.exports = {
//...
devServer: {
proxy: {
"/api": "http://localhost:3000" // 把所有 `/api` 開頭的接口都代理到 `mock` 項目中
}
}
};
然后用 webpack-dev-server 開啟本地開發(fā)調(diào)試,在頁面中就可以這樣訪問:
</>復(fù)制代碼
fetch("/api/user/profile"); // 訪問 mock 項目的 /api/user/profile
fetch("/api/user/update", {method: "post", body: { ... }});
// 訪問 mock 項目的 /api/user/update
# 可以將 fetch 換成其他請求方式
一般來說,我們還會用上 nodemon 來監(jiān)聽 mock 項目中的文件變動,自動重啟 mock 應(yīng)用程序,以此能夠做到每次訪問到的都是最新的資源(因為 node 針對某個模塊只會加載一次)。
</>復(fù)制代碼
nodemon app.js
這種方式可以統(tǒng)一管理多個項目的數(shù)據(jù)模擬文件,多個項目可以共享一些模擬數(shù)據(jù)。
3.4 線上接口模擬有些時候,當(dāng)我們在產(chǎn)品環(huán)境的時候(在線上)也可能想用模擬數(shù)據(jù)(比如APP、微信小程序、用于演示的 web 應(yīng)用等),或者需要一個線上的地方來統(tǒng)一管理模擬數(shù)據(jù)時,就需要線上接口模擬了。
線上接口模擬擁有完備的 UI 操作界面,可以添加多個用戶、多個團隊、多個倉庫,可以生成為每一個請求參數(shù)添加類型限定、描述,為響應(yīng)數(shù)據(jù)字段添加描述等。
因為是在線上的模擬數(shù)據(jù),所以在任何地方都可用,不管是本地開發(fā),還是線上調(diào)試、演示,都是可用的。
比較有名的線上接口模擬工具有:
easy-mock:線上演示地址 https://easy-mock.com/
RAP / rap2-delos + rap2-dolores:阿里出品,線上演示地址 http://rap2.taobao.org/
3.4.1 easy-mock</>復(fù)制代碼
環(huán)境需求:Node.js (>= v8.9) & MongoDB (>= v3.4) & Redis(>= v4.0)
安裝步驟請參考官方的文檔 easy-mock#quick-start
easy-mock 主要提供了以下的一些功能:
支持接口代理
支持快捷鍵操作
支持協(xié)同編輯
支持團隊項目
支持 RESTful
支持 Swagger | OpenAPI Specification (1.2 & 2.0 & 3.0)
基于 Swagger 快速創(chuàng)建項目
支持顯示接口入?yún)⑴c返回值
支持顯示實體類
支持靈活性與擴展性更高的響應(yīng)式數(shù)據(jù)開發(fā)
支持自定義響應(yīng)配置(例:status/headers/cookies)
支持 Mock.js 語法
支持 restc 方式的接口預(yù)覽
3.4.2 RAP / rap2-delos + rap2-dolores</>復(fù)制代碼
環(huán)境需求:Node.js (>= v8.9) & MySQL (>= v5.7) & Redis(>= v4.0)
RAP 目前有兩個版本,第一個版本的 RAP 已經(jīng)被官方廢棄了,建議用第二個版本。
RAP2 分成了兩個包:
rap2-delos:后端數(shù)據(jù) API 服務(wù)器
rap2-dolores:前端靜態(tài)資源
RAP2 的安裝步驟要麻煩一些,rap2-delos 可以參考官方文檔 rap2-delos#部署、非官方rap2-delos部署文檔,rap2-dolores 可以參考官方文檔 rap2-dolores#deployment-部署。
RAP2 提供了與 easy-mock 類似的功能,但比 easy-mock 要更強大一些,當(dāng)然也要復(fù)雜一些,比如:
對請求參數(shù)支持更完備,比如 headers、query params、body params
對響應(yīng)數(shù)據(jù)支持更完備,比如可以為每個字段添加描述、限定類型等
3.4.3 兩者之間比較RAP2 比 easy-mock 要更強大一些,但也要復(fù)雜一些,所以追求功能完備的可以用 RAP2,追求簡單快捷的可以用 easy-mock。
4. 代碼層面從上面可以看出,除了第二種方式 動態(tài)注冊接口 之外,其他的方式都不能做到完全模擬服務(wù)器環(huán)境,至少服務(wù)器接口地址與本地模擬地址不一樣,這就有一個問題:每次上線前都得改成服務(wù)器地址。
另外,前端與后端對接的過程中也總是難免會遇到一些問題:
前端傳的參數(shù)與后端所需的參數(shù)難以保持一致:比如分頁,前端定的 page、從 1 開始,后端定的 pageNum、從 0 開始
前端需要的數(shù)據(jù)與后端返回的數(shù)據(jù)相差很大,需要對返回的數(shù)據(jù)做處理
后端可能更改字段名或者數(shù)據(jù)類型,導(dǎo)致前端要查找、并更新相應(yīng)的代碼
一種好的、解決這些問題的方式是對應(yīng)用進行分層、把異步請求進行隔離封裝。
我一般會用 see-fetch、see-ajax 對異步請求進行隔離封裝。
注:see-fetch 是對 window.fetch 的封裝,see-ajax 是對 XMLHttpRequest 對象的封裝。
4.1 以 see-fetch 為例進行說明:可以在代碼中設(shè)置多個內(nèi)部環(huán)境,然后針對不同的外部環(huán)境設(shè)置不同的內(nèi)部環(huán)境(如:本地環(huán)境、線上環(huán)境等),這樣就可以做到不改代碼,只改一個環(huán)境值。
如果搭配 define-plugin,連環(huán)境值都不需要改,直接由 define-plugin 在運行的過程中指定。
</>復(fù)制代碼
import seeFetch from "see-fetch";
seeFetch.setEnv(0/1/2/3);
seeFetch.setEnv(__SEE_ENV__); // __SEE_ENV__ 由 define-plugin 運行中指定
配置一個異步請求:
</>復(fù)制代碼
seeFetch.config(name, { // 定義一個名為 name 的異步請求(下面的配置可以是多環(huán)境,每個環(huán)境可以設(shè)置不同的值)
method, // 當(dāng)前請求使用什么 http 方法
stringify,
settings,
url, // 當(dāng)前請求 url 地址
req, // 請求參數(shù)鍵名的映射,比如 `page => pageNum`
pre, // 操作請求參數(shù),比如 page 從 1 開始改成從 0 開始
refactor, // 重構(gòu)響應(yīng)數(shù)據(jù),如字段重命名、類型轉(zhuǎn)換等
post, // 操作響應(yīng)數(shù)據(jù),以把數(shù)據(jù)轉(zhuǎn)換成自己所需要的數(shù)據(jù)
implement, // 自定義請求,比如后端返回一個模板字符串,而不是接口
});
發(fā)起訪問:
</>復(fù)制代碼
seeFetch(name, params).then(result => {
// 這里的 result 是經(jīng)過格式化后的最終數(shù)據(jù)
});
從上面可以看出:一個請求的不確定性都被封裝到了配置中,不管是接口地址更新、前端請求參數(shù)與后端不一致、后端響應(yīng)數(shù)據(jù)與前端所需的差異很大等,都可以在配置中進行操作,而絲毫不需要改其他地方的代碼。
這樣,如果后端接口有什么改動的,只需要找到配置文件進行更新,而不用在項目中找哪里使用了這個接口。
如此,既能很好的使用本地數(shù)據(jù)模擬,也可以從容應(yīng)對后端接口的改動,便能事半功倍。
后續(xù)更多博客,查看 https://github.com/senntyou/blogs
作者:深予之 (@senntyou)
版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/100739.html
摘要:移動端應(yīng)用一般都運行在微信瀏覽器中中手機瀏覽器中。因為微信瀏覽器是定制的瀏覽器,一般的遠程調(diào)試方式都不可用,需要配合特定的工具,如微信開發(fā)者工具。 前端如何高效的與后端協(xié)作開發(fā) 1. 前后端分離 前端與后端的分離,能使前端的開發(fā)脫離后端的開發(fā)模式,擁有更大的自由度,以此便可做前端工程化、組件化、單頁面應(yīng)用等。 可以參考:前后端分離、web與static服務(wù)器分離 2. 盡量避免后端模板...
摘要:移動端應(yīng)用一般都運行在微信瀏覽器中中手機瀏覽器中。因為微信瀏覽器是定制的瀏覽器,一般的遠程調(diào)試方式都不可用,需要配合特定的工具,如微信開發(fā)者工具。 前端如何高效的與后端協(xié)作開發(fā) 1. 前后端分離 前端與后端的分離,能使前端的開發(fā)脫離后端的開發(fā)模式,擁有更大的自由度,以此便可做前端工程化、組件化、單頁面應(yīng)用等。 可以參考:前后端分離、web與static服務(wù)器分離 2. 盡量避免后端模板...
摘要:實現(xiàn)前后端分離的心得對目前的來說,前后端分離已經(jīng)變得越來越流行了,越來越多的企業(yè)網(wǎng)站都開始往這個方向靠攏。前后端工作分配不均。 實現(xiàn)前后端分離的心得 對目前的web來說,前后端分離已經(jīng)變得越來越流行了,越來越多的企業(yè)/網(wǎng)站都開始往這個方向靠攏。那么,為什么要選擇前后端分離呢?前后端分離對實際開發(fā)有什么好處呢? 為什么選擇前后端分離 在以前傳統(tǒng)的網(wǎng)站開發(fā)中,前端一般扮演的只是切圖的工作...
摘要:本文由云社區(qū)發(fā)表絕大多數(shù)程序只考慮了接口正常工作的場景,而用戶在使用我們的產(chǎn)品時遇到的各類異常,全都丟在看似的中。在面板,還可以對請求進行暫停延遲等網(wǎng)絡(luò)異常的模擬。小程序?qū)崿F(xiàn)最后,留一道思考題。 本文由云+社區(qū)發(fā)表 絕大多數(shù)程序只考慮了接口正常工作的場景,而用戶在使用我們的產(chǎn)品時遇到的各類異常,全都丟在看似 ok 的 try catch 中。如果沒有做好異常的兼容和兜底處理,會極大的影...
摘要:如何構(gòu)建大型的前端項目搭建好項目的腳手架一般新開發(fā)一個項目時,我們會首先搭建好一個腳手架,然后才會開始寫代碼。組件化一般分為項目內(nèi)的組件化和項目外的組件化。 如何構(gòu)建大型的前端項目 1. 搭建好項目的腳手架 一般新開發(fā)一個項目時,我們會首先搭建好一個腳手架,然后才會開始寫代碼。一般腳手架都應(yīng)當(dāng)有以下的幾個功能: 自動化構(gòu)建代碼,比如打包、壓縮、上傳等功能 本地開發(fā)與調(diào)試,并有熱替換與...
閱讀 918·2021-11-22 13:53
閱讀 2543·2021-10-15 09:40
閱讀 1014·2021-10-14 09:42
閱讀 3589·2021-09-22 15:59
閱讀 903·2021-09-02 09:47
閱讀 2410·2019-08-30 15:54
閱讀 1449·2019-08-29 17:14
閱讀 412·2019-08-29 15:15