SlideShare a Scribd company logo
Mirage For Beginners
Mirage Version 0.1.41
Wilson Su
Agenda
Background
1
Mirage
Introduction
2
Code
Examples
3
2
Background
3
Given a web app that
accesses data in the server
through RESTful APIs
4
API Request and Response
HTTP Request
GET/POST/PUT/DELETE ...
HTTP Response
JSON Data
Client Server
Web App
API
Controller
Data
5
Front-end developers
want to implement web UIs
before the APIs are ready
6
Develop New Features
Client Server
Web App
API
Controller
Data
GET /api/products
404 Not Found
7
What’s The Next Step
Wait for the backend side to complete the API development
A
Do the API development yourself
B
Add mock data to the API request functions in the client side
C Add mock data to the API request functions in the client side
C
8
API Function Example
// The fake function
function fetchProducts() {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ id: 1, name: 'Orange' },
{ id: 2, name: 'Banana' },
]);
}, 400);
});
}
// The actual function
function fetchProducts() {
return fetch('/api/products');
}
Must be changed to look like the right
one after the API is completed
9
You can start to use Mirage
10
Mirage Introduction
11
What’s Mirage
Mirage
− is an API mocking library running in the browser
− runs alongside the rest of your frontend JavaScript code
− uses an in-memory database to maintain the data
12
How Mirage Works?
Mirage intercepts requests
by stubbing native fetch and
XMLHttpRequest
13
API Request and Response
HTTP Request
GET/POST/PUT/DELETE ...
HTTP Response
JSON Data
Client Server
Web App
API
Controller
Data
fetch
XMLHttpRequest
14
With Mirage Server In The Client
Client
Mock API Mock Data
Fake HTTP Response
GET /api/products
Web App
fetch
XMLHttpRequest
15
In-Memory DB
Override Native XMLHttpRequest
const nativeXMLHttpRequest = window.XMLHttpRequest;
const makeFakeRequest = () => {
function FakeRequest() {}
FakeRequest.prototype.send = () => { ... };
FakeRequest.prototype.abort = () => { ... };
...
return FakeRequest;
};
window.XMLHttpRequest = makeFakeRequest();
16
Code Examples
17
Create Mirage Server
import { createServer } from 'miragejs';
createServer({
routes() {
this.timing = 400; // The Server's response time in milliseconds
this.get('/api/products', () => {
return {
data: [{ id: 1, name: 'Orange' }, { id: 2, name: 'Banana' }],
};
});
},
});
18
Dynamic Handlers
import { createServer, Model } from 'miragejs';
createServer({
models: { product: Model },
routes() {
this.get('/api/products', schema => schema.products.all());
this.post('/api/products', (schema, request) => {
const body = JSON.parse(request.requestBody);
return schema.products.create(body);
});
},
});
19
Create Initial Data
20
createServer({
models: { product: Model },
seeds(server) {
server.create(
'product',
{ id: 1, name: 'Orange' },
);
},
});
createServer({
models: { product: Model },
seeds(server) {
server.db.loadData({
products: [
{ id: 1, name: 'Orange' },
],
});
},
});
Dynamic Segments
21
createServer({
models: { product: Model },
routes() {
this.get('/api/products/:id', (schema, request) => {
return schema.products.find(request.params.id);
});
this.delete('/api/products/:id', (schema, request) => {
return schema.products.find(request.params.id).destroy();
});
},
});
More Examples
22
Project Folder Structure
scripts
ㄴ app.js
mock
ㄴ routes
ㄴ product
ㄴ list.route.js
ㄴ detail.route.js
ㄴ server.js
ㄴ settings.dev.js
index.html
✓ Include configurations such as the
response time and enabled routes in
/mock/settings.dev.js
✓ Put route files under /mock/routes
✓ Add subfolders and route files for
different features
✓ No need to update /mock/server.js
when new routes added
23
/mock/settings.dev.js
export default {
delay: 400,
routes: [
'product/list', //=> /mock/routes/product/list.route.js
'product/detail', //=> /mock/routes/product/detail.route.js
],
};
24
/mock/server.js (1)
const context = require.context('./routes', true, /.route.js$/);
const routes = context
.keys()
.map(filepath => {
const name = filepath.match(/./([w/-]+).route.js/)[1];
const route = context(filepath).default;
return { name, route };
})
.filter(({ name }) => settings.routes.includes(name));
25
/mock/server.js (2)
export const makeServer = settings => {
createServer({
routes() {
this.timing = settings.delay;
routes.forEach(({ route }) => route.routes(this));
this.passthrough();
},
});
};
makeServer(settings);
26

More Related Content

Mirage For Beginners

  • 1. Mirage For Beginners Mirage Version 0.1.41 Wilson Su
  • 4. Given a web app that accesses data in the server through RESTful APIs 4
  • 5. API Request and Response HTTP Request GET/POST/PUT/DELETE ... HTTP Response JSON Data Client Server Web App API Controller Data 5
  • 6. Front-end developers want to implement web UIs before the APIs are ready 6
  • 7. Develop New Features Client Server Web App API Controller Data GET /api/products 404 Not Found 7
  • 8. What’s The Next Step Wait for the backend side to complete the API development A Do the API development yourself B Add mock data to the API request functions in the client side C Add mock data to the API request functions in the client side C 8
  • 9. API Function Example // The fake function function fetchProducts() { return new Promise((resolve) => { setTimeout(() => { resolve([ { id: 1, name: 'Orange' }, { id: 2, name: 'Banana' }, ]); }, 400); }); } // The actual function function fetchProducts() { return fetch('/api/products'); } Must be changed to look like the right one after the API is completed 9
  • 10. You can start to use Mirage 10
  • 12. What’s Mirage Mirage − is an API mocking library running in the browser − runs alongside the rest of your frontend JavaScript code − uses an in-memory database to maintain the data 12
  • 13. How Mirage Works? Mirage intercepts requests by stubbing native fetch and XMLHttpRequest 13
  • 14. API Request and Response HTTP Request GET/POST/PUT/DELETE ... HTTP Response JSON Data Client Server Web App API Controller Data fetch XMLHttpRequest 14
  • 15. With Mirage Server In The Client Client Mock API Mock Data Fake HTTP Response GET /api/products Web App fetch XMLHttpRequest 15 In-Memory DB
  • 16. Override Native XMLHttpRequest const nativeXMLHttpRequest = window.XMLHttpRequest; const makeFakeRequest = () => { function FakeRequest() {} FakeRequest.prototype.send = () => { ... }; FakeRequest.prototype.abort = () => { ... }; ... return FakeRequest; }; window.XMLHttpRequest = makeFakeRequest(); 16
  • 18. Create Mirage Server import { createServer } from 'miragejs'; createServer({ routes() { this.timing = 400; // The Server's response time in milliseconds this.get('/api/products', () => { return { data: [{ id: 1, name: 'Orange' }, { id: 2, name: 'Banana' }], }; }); }, }); 18
  • 19. Dynamic Handlers import { createServer, Model } from 'miragejs'; createServer({ models: { product: Model }, routes() { this.get('/api/products', schema => schema.products.all()); this.post('/api/products', (schema, request) => { const body = JSON.parse(request.requestBody); return schema.products.create(body); }); }, }); 19
  • 20. Create Initial Data 20 createServer({ models: { product: Model }, seeds(server) { server.create( 'product', { id: 1, name: 'Orange' }, ); }, }); createServer({ models: { product: Model }, seeds(server) { server.db.loadData({ products: [ { id: 1, name: 'Orange' }, ], }); }, });
  • 21. Dynamic Segments 21 createServer({ models: { product: Model }, routes() { this.get('/api/products/:id', (schema, request) => { return schema.products.find(request.params.id); }); this.delete('/api/products/:id', (schema, request) => { return schema.products.find(request.params.id).destroy(); }); }, });
  • 23. Project Folder Structure scripts ㄴ app.js mock ㄴ routes ㄴ product ㄴ list.route.js ㄴ detail.route.js ㄴ server.js ㄴ settings.dev.js index.html ✓ Include configurations such as the response time and enabled routes in /mock/settings.dev.js ✓ Put route files under /mock/routes ✓ Add subfolders and route files for different features ✓ No need to update /mock/server.js when new routes added 23
  • 24. /mock/settings.dev.js export default { delay: 400, routes: [ 'product/list', //=> /mock/routes/product/list.route.js 'product/detail', //=> /mock/routes/product/detail.route.js ], }; 24
  • 25. /mock/server.js (1) const context = require.context('./routes', true, /.route.js$/); const routes = context .keys() .map(filepath => { const name = filepath.match(/./([w/-]+).route.js/)[1]; const route = context(filepath).default; return { name, route }; }) .filter(({ name }) => settings.routes.includes(name)); 25
  • 26. /mock/server.js (2) export const makeServer = settings => { createServer({ routes() { this.timing = settings.delay; routes.forEach(({ route }) => route.routes(this)); this.passthrough(); }, }); }; makeServer(settings); 26