بنقرة واحدة
chrome-devtools-mock
通过 Chrome DevTools 注入 XHR 拦截脚本来 mock 前端页面 API 数据,无需修改源码。当用户要求 mock 页面数据、前端没有后端可用、需要快速预览 UI 时触发。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
通过 Chrome DevTools 注入 XHR 拦截脚本来 mock 前端页面 API 数据,无需修改源码。当用户要求 mock 页面数据、前端没有后端可用、需要快速预览 UI 时触发。
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | chrome-devtools-mock |
| description | 通过 Chrome DevTools 注入 XHR 拦截脚本来 mock 前端页面 API 数据,无需修改源码。当用户要求 mock 页面数据、前端没有后端可用、需要快速预览 UI 时触发。 |
通过 Chrome DevTools MCP 的 navigate_page + initScript 注入 XMLHttpRequest 拦截,在浏览器层面 mock API 响应,不修改任何源码。
MOCK_ENABLED = true,会污染代码库,容易忘记删除导致提交到生产环境。window.fetch:大多数项目用 axios,axios 底层走 XMLHttpRequest 而非 fetch,拦截 fetch 无效。evaluate_script 注入后再 reload:reload 后注入的脚本会丢失。使用 chrome-devtools___navigate_page 工具的 initScript 参数。initScript 会在页面加载前、任何其他脚本执行前注入,确保 XHR 拦截在 API 请求之前生效。
用 list_pages + select_page 选中目标页面。
根据用户需求和页面代码,确定:
{code: 1, message: 'success', data: {...}})调用 navigate_page 时传入 initScript:
chrome-devtools___navigate_page({
type: "reload",
timeout: 15000,
initScript: "<XHR拦截脚本>"
})
页面加载后用 take_screenshot 确认 mock 数据已生效。
以下是完整的 XMLHttpRequest 拦截模板,必须严格按此结构:
(function() {
// === 1. 定义 mock 数据 ===
var mockRoutes = {
'/api/v1/some-endpoint': { key: 'value' },
'/api/v1/another': { items: [] }
};
// === 2. 定义响应包装函数(根据项目 API 格式调整) ===
var wrapResp = function(data) {
// 常见格式,根据实际项目调整
return JSON.stringify({ code: 1, message: 'success', data: data });
};
// === 3. 拦截 XMLHttpRequest ===
var origOpen = XMLHttpRequest.prototype.open;
var origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(m, u) {
this.__url = u;
return origOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function(b) {
var u = this.__url || '';
var d = null;
// === 4. URL 匹配(具体路径必须在泛路径之前) ===
// 先匹配带 ID 的具体路径
if (u.match(/\/api\/v1\/items\/[^/?]+/) && u.indexOf('delete') === -1) {
d = { item: { id: '1', name: 'Mock Item' } };
}
// 再匹配列表路径
else if (u.indexOf('/api/v1/items') !== -1) {
d = { items: [{ id: '1', name: 'Mock Item' }] };
}
// === 5. 返回 mock 响应 ===
if (d !== null) {
var r = wrapResp(d);
var self = this;
// 必须用 Object.defineProperty 覆盖只读属性
Object.defineProperty(self, 'readyState', { writable: true, value: 4 });
Object.defineProperty(self, 'status', { writable: true, value: 200 });
Object.defineProperty(self, 'statusText', { writable: true, value: 'OK' });
Object.defineProperty(self, 'responseText', { writable: true, value: r });
Object.defineProperty(self, 'response', { writable: true, value: r });
// 必须异步触发回调,模拟真实网络行为
setTimeout(function() {
self.dispatchEvent(new Event('readystatechange'));
self.dispatchEvent(new Event('load'));
self.dispatchEvent(new Event('loadend'));
if (self.onreadystatechange) self.onreadystatechange();
if (self.onload) self.onload();
if (self.onloadend) self.onloadend();
}, 5);
return; // 不调用原始 send
}
// 未匹配的请求走原始逻辑
return origSend.apply(this, arguments);
};
})();
/items/123)必须在泛路径(如 /items)之前匹配,否则泛路径会先命中Object.defineProperty:XMLHttpRequest 的 readyState、status、response 等属性是只读的,必须用 Object.defineProperty 覆盖setTimeout:回调必须在 setTimeout 中触发,否则 axios 的拦截器可能还未注册dispatchEvent 也要直接调用 onload 等回调,因为 axios 可能用任一方式监听initScript 每次传入:initScript 只在当次 navigate_page 调用时生效,后续刷新需要重新传入initScript 中的 JS 需要兼容各种环境,避免使用高级语法