不再依赖后台,使用json-server模拟restful接口
Why json-server?
在所有的项目开发中,前端开发都需要后台提供接口和数据,才能进行下一步的开发,但是后台开发多半是滞后于前端开发的,那么我们怎么才能自己临时地来模拟数据,并行开发呢?答案就是MOCK数据,对比过多种mock工具后,最终选择了使用 json server ,因为它足够简单,且足够强大,支持CORS和JSONP跨域请求,支持GET, POST, PUT, PATCH 和 DELETE 方法,更提供了一系列的查询方法,如limit,order等。
安装使用
npm install -g json-server
然后在根目录下面新建一个文件db.json
:
{
"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}
然后开始即可:
json-server --watch db.json
在浏览器里输入http://localhost:3000/posts/1
你会看到下面的结果:
{ "id": 1, "title": "json-server", "author": "typicode" }
下面四点需要注意:
- POST, PUT, PATCH ,DELETE等请求提交时,会使用lowdb自动改变
db.json
并保存 - 所有提交的JSON数据都必须闭合在花括号里面
- ID无法修改,只能使用POST新增
- POST, PUT , PATCH等请求如果使用JSON数据提交时必需包含
Content-Type: application/json
,否则虽然会返回200但是数据不会改变
所有的使用选项如下:
json-server [options] <source>
Options:
--config, -c 配置文件路径 [default: "json-server.json"]
--port, -p 端口号 [default: 3000]
--host, -H 主机地址 [default: "localhost"]
--watch, -w 是否监听文件 [boolean]
--routes, -r 路由文件路径
--middlewares, -m 中间件文件路径 [array]
--static, -s 静态文件目录
--read-only, --ro 只允许GET请求 [boolean]
--no-cors, --nc 禁止跨域 [boolean]
--no-gzip, --ng 禁止GZIP压缩 [boolean]
--snapshots, -S 设置快照目录 [default: "."]
--delay, -d 响应延迟(ms)
--id, -i 设置数据库ID属性 (e.g. _id) [default: "id"]
--foreignKeySuffix, --fks 设置前缀, (e.g. _id as in post_id)
[default: "Id"]
--quiet, -q 不输出日志信息 [boolean]
--help, -h Show help [boolean]
--version, -v Show version number [boolean]
Examples:
json-server db.json
json-server file.js
json-server http://example.com/db.json
https://github.com/typicode/json-server
默认路由
-
复数路由,针对数组数据:
GET /posts
GET /posts/1
POST /posts
PUT /posts/1
PATCH /posts/1
DELETE /posts/1
-
单数路由,针对对象数据:
GET /profile
POST /profile
PUT /profile
PATCH /profile
-
过滤器,你可以使用
.
进行深层次的属性匹配:
GET /posts?title=json-server&author=typicode
GET /posts?id=1&id=2
GET /comments?author.name=typicode
-
分页,默认是返回10条数据
GET /posts?_page=7
GET /posts?_page=1&_limit=2
返回除了获取的数据,在头部还会有一个Link
头,包括了first
, prev
, next
,last
链接:
<http://localhost:3000/posts?_page=1&_limit=1>; rel="first", <http://localhost:3000/posts?_page=1&_limit=1>; rel="prev", <http://localhost:3000/posts?_page=3&_limit=1>; rel="next", <http://localhost:3000/posts?_page=5&_limit=1>; rel="last"
-
排序
GET /posts?_sort=views&_order=asc
GET /posts/1/comments?_sort=votes&_order=asc
GET /posts?_sort=user,views&_order=desc,asc
-
切片
GET /posts?_start=20&_end=30
GET /posts/1/comments?_start=20&_end=30
GET /posts/1/comments?_start=20&_limit=10
除了返回数据外,在返回的消息头部,还有一个X-Total-Count
字段,代表了所有的数据的总量
-
操作符
_gte: 大于等于
_lte: 小于等于
_ne : 不等于
_like : 正则匹配
GET /posts?views_gte=10&views_lte=20
GET /posts?id_ne=1
GET /posts?title_like=server
-
全文查询
使用q
:
GET /posts?q=internet
-
关系
嵌入子属性使用_embed
,嵌入父属性使用_expand
:
GET /posts?_embed=comments
GET /posts/1?_embed=comments
GET /comments?_expand=post
GET /comments/1?_expand=post
获取或者创建嵌套属性:
GET /posts/1/comments
POST /posts/1/comments
-
获取所有数据
GET /db
-
首页
GET /
其他
-
静态文件服务器
只需要在根目录创建一个public
的目录即可,或者使用--static
手动设置别的目录
-
使用远程数据
$ json-server http://example.com/file.json
$ json-server http://jsonplaceholder.typicode.com/db
-
使用动态生成的数据
// index.js
module.exports = () => {
const data = { users: [] }
// Create 1000 users
for (let i = 0; i < 1000; i++) {
data.users.push({ id: i, name: `user${i}` })
}
return data
}
$ json-server index.js
-
自定义路由(路由改写以及映射)
新建一个routes.json
文件:
{
"/api/*": "/$1",
"/:resource/:id/show": "/:resource/:id",
"/posts/:category": "/posts?category=:category",
"/articles\\?id=:id": "/posts/:id"
}
json-server db.json --routes routes.json
现在这些路由就会被映射成:
/api/posts # → /posts
/api/posts/1 # → /posts/1
/posts/1/show # → /posts/1
/posts/javascript # → /posts?category=javascript
/articles?id=1 # → /posts/1
!!!注意,重要的事情说三遍:
!!!注意,重要的事情说三遍:
!!!注意,重要的事情说三遍:
上一个被映射的URL会重新匹配下面的映射规则,因此很有可能被再次映射:例如:
/api/posts/1 # → /posts/1
会继续匹配下面的/posts/javascript
因而最终变成了/posts?category=1
,和顺序有关,只会继续往下匹配改写,不会往上匹配,而且匹配后显示的URL并不改变,因此需要非常注意谨慎。
-
使用中间件
// hello.js
module.exports = (req, res, next) => {
res.header('X-Hello', 'World')
next()
}
json-server db.json --middlewares ./hello.js
json-server db.json --middlewares ./first.js ./second.js
-
使用配置文件
新建一个json-server.json
或者使用--config, -c
来指定:
{
"port": 3000,
"host": 'http://127.0.0.1'
...
}
模块使用
-
安装使用
你也可以把json-server
当做一个模块和其他的express中间件一起使用:
$ npm install json-server --save-dev
// server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(router)
server.listen(3000, () => {
console.log('JSON Server is running')
})
$ node server.js
注意:jsonServer.router()
也可以在现成的express项目中进行使用
-
自定义json-server之外的路由
// Add custom routes before JSON Server router
server.get('/echo', (req, res) => {
res.jsonp(req.query)
})
server.use((req, res, next) => {
if (req.method === 'POST') {
req.body.createdAt = Date.now()
}
// Continue to JSON Server router
next()
})
-
访问控制
server.use((req, res, next) => {
if (isAuthorized(req)) { // add your authorization logic here
next() // continue to JSON Server router
} else {
res.sendStatus(401)
}
})
-
自定义输出
其实所有的要返回的匹配的数据都在res.locals.data
里,这样我们就可以自定义输出了:
router.render = (req, res) => {
res.jsonp({
body: res.locals.data
})
}
router.render = (req, res) => {
res.status(500).jsonp({
error: "error message here"
})
}
-
自定义路由(路由改写以及映射)
const router1 = jsonServer.router('db1.json')
const router2 = jsonServer.router('db2.json')
server.use(jsonServer.rewriter({
'/api/*': '/$1',
'/blog/:resource/:id/show': '/:resource/:id'
}))
server.use('/post', jsonServer.rewriter({
'/api/*': '/$1',
'/blog/:resource/:id/show': '/:resource/:id'
}))
server.use('/post1',router1)
server.use('/post2',router2)
注意,路由改写应该写在server.use(router)
之前,否则无效
API
jsonServer.create()
返回一个express服务器jsonServer.defaults([options])
返回使用的中间件- static path to static files
- logger enable logger middleware (default: true)
- bodyParser enable body-parser middleware (default: true)
- noCors disable CORS (default: false)
- readOnly accept only GET requests (default: false)
jsonServer.router([path|object])
返回router
配合Mockjs使用
// data
const Mock = require('mockjs')
const Random = Mock.Random
module.exports = () => {
const data = {products: []}
data.products.push({
name: Random.name()
})
return data
}
// server.js
const jsonServer = require('json-server')
const server = jsonServer.create()
const middlewares = jsonServer.defaults()
const products_db = require('./data/products.js')
const products_router = jsonServer.router(products_db())
server.use(middlewares)
server.use(jsonServer.bodyParser)
server.use(products_router)
server.listen(9000, () => {
console.log('JSON Server is running')
})