mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-24 20:00:37 +00:00
docs: 内容
This commit is contained in:
@@ -1,13 +1,31 @@
|
||||
# Electron:PC 端多端融合方案
|
||||
|
||||
> 每天都要写第二天的 todoList。有一天在写的时候突然想到,为了让自己清楚知道自己需要做啥、做了多少、还剩多少没做,想写一个电脑端程序,在技术选型的时候就选了 electron。
|
||||
> 每天都要写第二天的 todoList。有一天在写的时候突然想到,为了让自己清楚知道自己需要做啥、做了多少、还剩多少没做,想写一个电脑端程序,在技术选型的时候就选了 Electron。
|
||||
>
|
||||
> 本篇文章的目的不是讲解 API 如何使用,想知道这些可以直接看[官方文档](https://www.electronjs.org/docs)。本文目的旨在讲明如何技术如何选择、如何快速上手、如何调试、Electron 底层原理、工程体系方面的总结。
|
||||
> 本篇文章的目的不是讲解 API 如何使用,想知道这些可以直接看[官方文档](https://www.Electronjs.org/docs)。本文目的旨在讲明如何技术如何选择、如何快速上手、如何调试、Electron 底层原理、工程体系方面的总结。
|
||||
|
||||
|
||||
|
||||
## 一、浅谈 GUI 系统
|
||||
|
||||
```shell
|
||||
浏览器是如何将布局数据计算为像素数据的,你能实现出原理类似的渲染器吗?
|
||||
浏览器在各个平台上的文字排版渲染结果是否一致,你能解释原因吗?
|
||||
你所负责的前端应用,其渲染性能还有多大的提升空间,你能量化地证明吗?
|
||||
你能设计实现出类似 RN 和小程序那样的 Hybrid 方案吗?
|
||||
你能自己控制 GPU 渲染管线,实现渲染的硬件加速吗?
|
||||
```
|
||||
|
||||
GUI 起源:从 1979 年乔布斯造访施乐 PARC 算起
|
||||
|
||||
GUI 架构:过程化绘制(drawLine、drawRect)-> 面向对象抽象时代 -> 界面与样式分离时代 -> MVC、MVVM 时代 -> 声明式、组件式时代(Vue、React、RN、Weex、Flutter)
|
||||
|
||||
我们可以看到不变的是:随着计算机科学技术的发展,为了实现某个效果,一流程序员或者组织不断研发各种技术框架,来提高开发效率和效果。Electron 就是这条历史长河中诞生的 PC 端技术框架之一。
|
||||
|
||||
|
||||
|
||||
|
||||
## 一、 方案选型
|
||||
## 二、 技术选型
|
||||
|
||||
3天时间写了个 PC 端应用程序。先看看结果吧
|
||||
|
||||
@@ -17,33 +35,36 @@
|
||||
|
||||

|
||||
|
||||
为什么要选 electron 作为 pc 端开发方案?
|
||||
|
||||
|
||||
**为什么要选 Electron 作为 pc 端开发方案?**
|
||||
|
||||
史前时代,以 MFC 为代表的技术栈,开发效率较低,维护成本高。
|
||||
后来使用 QT 技术,特点是使用 DirectUI + 面向对象 + XML 定义 UI,适用于小型软件、性能要求、包大小、UI 复杂度叫高的需求。
|
||||
再到后来,以 QT Quick 为代表的技术,特点是框架本身提供子控件,基于子控件组合来创建新的控件。类似于 ActionScript 的脚本化界面逻辑代码。
|
||||
新时代主要是以 [electron](https://electronjs.org) 和 [Cef](https://bitbucket.org/chromiumembedded/cef) 为 代表。特点是界面开发以 Web 技术为主,部分逻辑需要 Native 代码实现。大家都熟悉的 VS Code 就是使用 electron 开发的。适用于 UI 变化较多、体积限制不大、开发效率高的场景。
|
||||
新时代主要是以 [Electron](https://Electronjs.org) 和 [Cef](https://bitbucket.org/chromiumembedded/cef) 为 代表。特点是界面开发以 Web 技术为主,部分逻辑需要 Native 代码实现。大家都熟悉的 VS Code 就是使用 Electron 开发的。适用于 UI 变化较多、体积限制不大、开发效率高的场景。
|
||||
|
||||
拿 C 系列写应用程序的体验不好,累到奔溃。再加上有 Hybrid、React Native、iOS、Vue、React 等开发经验,electron 是不二选择。
|
||||
拿 C 系列写应用程序的体验不好,累到奔溃。再加上有 Hybrid、React Native、iOS、Vue、React 等开发经验,Electron 是不二选择。
|
||||
|
||||
|
||||
|
||||
|
||||
## 二、 Quick start
|
||||
## 三、 Quick start
|
||||
执行下面命令快速体验 Hello world,也是官方给的一个 Demo。
|
||||
```shell
|
||||
git clone https://github.com/electron/electron-quick-start
|
||||
cd electron-quick-start
|
||||
git clone https://github.com/Electron/Electron-quick-start
|
||||
cd Electron-quick-start
|
||||
npm install && npm start
|
||||
```
|
||||
|
||||
简单介绍下 Demo 工程,工程目录如下所示
|
||||

|
||||

|
||||
|
||||
在终端执行 `npm start` 执行的是 package.json 中的 `scripts` 节点下的 start 命令,也就是 `electron .`,`.` 代表执行 main.js 中的逻辑。
|
||||
在终端执行 `npm start` 执行的是 package.json 中的 `scripts` 节点下的 start 命令,也就是 `Electron .`,`.` 代表执行 main.js 中的逻辑。
|
||||
|
||||
```Javascript
|
||||
// Modules to control application life and create native browser window
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const {app, BrowserWindow} = require('Electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
@@ -84,13 +105,13 @@ app.on('activate', function () {
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
```
|
||||
写过 Vue、React、Native 的人看代码很容易,因为应用程序的生命周期钩子函数是很重要的,开发者根据需求在钩子函数里面做相应的视图创建、初始化、销毁对象等等。比如 electron 中的 activate、window-all-closed 等。
|
||||
写过 Vue、React、Native 的人看代码很容易。比如应用程序的生命周期钩子函数对开发者很重要,也是一个标准的做法,根据需求在钩子函数里面做相应的视图创建、初始化、销毁对象等等。比如 Electron 中的 `activate`、`window-all-closed` 等。
|
||||
|
||||
app 对象在 `whenReady` 的时候执行 createWindow 方法。内部创建了一个 `BrowserWindow` 对象,指定了大小和功能设置。
|
||||
app 对象在 `whenReady` 的时候执行 `createWindow` 方法。内部创建了一个 `BrowserWindow` 对象,指定了大小和功能设置。
|
||||
|
||||
1. webPreferences Object (可选) - 网页功能的设置。
|
||||
1. webPreferences:Object (可选) - 网页功能的设置。
|
||||
|
||||
2. preload String (可选) - 在页面运行其他脚本之前预先加载指定的脚本 无论页面是否集成 Node, 此脚本都可以访问所有 Node API 脚本路径为文件的绝对路径。 当 node integration 关闭时, 预加载的脚本将从全局范围重新引入 node 的全局引用标志。
|
||||
2. preload: String (可选) - 在页面运行其他脚本之前预先加载指定的脚本。无论页面是否集成 Node, 此脚本都可以访问所有 Node API 脚本路径为文件的绝对路径。 当 node `integration` 关闭时, 预加载的脚本将从全局范围重新引入 node 的全局引用标志。
|
||||
|
||||
`mainWindow.loadFile('index.html')` 加载了同级目录下的 index.html 文件。也可以加载服务器资源(部署好的网页),比如 `win.loadURL('https://github.com/FantasticLBP')`
|
||||
|
||||
@@ -108,25 +129,25 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
console.table(process)
|
||||
console.info(process.versions)
|
||||
for (const type of ['chrome', 'node', 'electron']) {
|
||||
for (const type of ['chrome', 'node', 'Electron']) {
|
||||
replaceText(`${type}-version`, process.versions[type])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
在页面运行其他脚本之前预先加载指定的脚本,无论页面是否集成 Node, 此脚本都可以访问所有 Node API 脚本路径为文件的绝对路径。Demo 中的逻辑很简单,就是读取 `process.versions` 对象中的 node、chrome、electron 的版本信息并展示出来。
|
||||
在页面运行其他脚本之前预先加载指定的脚本,无论页面是否集成 Node, 此脚本都可以访问所有 Node API 脚本路径为文件的绝对路径。Demo 中的逻辑很简单,就是读取 `process.versions` 对象中的 node、chrome、Electron 的版本信息并展示出来。
|
||||
|
||||
`index.html` 中的内容就是主页面显示的内容。一般不会直接写 html、css、js,都会根据技术背景选择前端框架,比如 Vue、React 等,或者模版引擎 ejs 等。
|
||||
`index.html` 中的内容就是主页面显示的内容。一般不会直接写 html、css、js,都会根据技术背景选择前端框架,比如 Vue、React 等,或者模版引擎 [ejs](https://ejs.co) 等。
|
||||
|
||||
|
||||
|
||||
|
||||
## 三、 实现原理
|
||||
## 四、 实现原理
|
||||
|
||||
electron 分为**渲染进程和主进程**。和 Native 中的概念不一样的是 electron 中主进程只有一个,渲染进程(也就是 UI 进程) 有多个。主进程在后台运行,每次打开一个界面,会新开一个新的渲染进程。
|
||||
Electron 分为**渲染进程和主进程**。和 Native 中的概念不一样的是 Electron 中主进程只有一个,渲染进程(也就是 UI 进程) 有多个。主进程在后台运行,每次打开一个界面,会新开一个新的渲染进程。
|
||||
|
||||
- 渲染进程: 用户看到的 web 界面就是由渲染进程绘制出来的,包括 html、css、js。
|
||||
- 主进程:electron 运行 package.json 中的 main.js 脚本的进程被称为主进程。在主进程中运行的脚本通过创建 web 页面来展示用户界面。一个 electron 应用程序总是只有一个主进程。
|
||||
- 主进程:Electron 运行 package.json 中的 main.js 脚本的进程被称为主进程。在主进程中运行的脚本通过创建 web 页面来展示用户界面。一个 Electron 应用程序总是只有一个主进程。
|
||||
|
||||
|
||||
|
||||
@@ -343,7 +364,11 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
|
||||
|
||||
|
||||
## 四、 如何调试
|
||||
|
||||
|
||||
|
||||
|
||||
## 五、 如何调试
|
||||
|
||||
调试分为主进程调试和渲染进程调试。
|
||||
|
||||
@@ -370,12 +395,12 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
```
|
||||
- 然后打开浏览器,在地址栏输入 `chrome://inspect`
|
||||
- 点击 `configure`,在弹出的面板中填写需要调试的端口信息
|
||||

|
||||

|
||||
- 重新开启服务 `npm start`,在 chrome inspect 面板的 `Target` 节点中选择需要调试的页面
|
||||
- 在面板中可以看到主进程执行的 `main.js`。可以加断点进行调试
|
||||

|
||||

|
||||
|
||||
方法二:利用 VS Code 调试 electron 主进程。
|
||||
方法二:利用 VS Code 调试 Electron 主进程。
|
||||
|
||||
- 在 VS Code 的左侧菜单栏,第四个功能模块就是调试,点击调试,弹出对话框让你添加调试配置文件 `launch.json`
|
||||
|
||||
@@ -390,9 +415,9 @@ Electron 架构和 Chromium 架构类似,也是具有1个主进程和多个渲
|
||||
"request": "launch",
|
||||
"name": "Debug main process",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/Electron",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
|
||||
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/Electron.cmd"
|
||||
},
|
||||
"args": ["."],
|
||||
"outputCapture": "std"
|
||||
@@ -417,7 +442,7 @@ Webpack 有一个 api: `watch-run`,可以针对代码文件检测,有变化
|
||||
|
||||
|
||||
|
||||
## 五、 开发 tips及其优化手段
|
||||
## 六、 开发 tips及其优化手段
|
||||
|
||||
### 1. 开发 tips
|
||||
|
||||
@@ -431,14 +456,14 @@ Webpack 有一个 api: `watch-run`,可以针对代码文件检测,有变化
|
||||
Refused to execute inline event handler because it violates the following Content Security Policy directive:
|
||||
```
|
||||
|
||||
4. 利用 electron 进行开发的时候,可以看成是 NodeJS + chromium + Web 前端开发技术。NodeJS 拥有文件访问等后端能力,chromium 提供展示功能,以及网络能力(electron 网络能力不是 NodeJS 提供的,而是 chromium 的 net 模块提供的)。web 前端开发技术方案都可以应用在 electron 中,比如 Vue、React、Bootstrap、sass 等。
|
||||
4. 利用 Electron 进行开发的时候,可以看成是 NodeJS + chromium + Web 前端开发技术。NodeJS 拥有文件访问等后端能力,chromium 提供展示功能,以及网络能力(Electron 网络能力不是 NodeJS 提供的,而是 chromium 的 net 模块提供的)。web 前端开发技术方案都可以应用在 Electron 中,比如 Vue、React、Bootstrap、sass 等。
|
||||
|
||||
5. 在工程化角度看,使用 yarn 比 npm 好一些,因为 yarn 会缓存已经安装过的依赖,其他项目只要发现存在缓存,则读取本地的包依赖,会更加快速。
|
||||
|
||||
6. 在使用 Vue、React 开发 electron 应用时,可以使用 npm 或 yarn install 包,也可以使用 electron-vue 脚手架工具。
|
||||
6. 在使用 Vue、React 开发 Electron 应用时,可以使用 npm 或 yarn install 包,也可以使用 Electron-vue 脚手架工具。
|
||||
|
||||
```shell
|
||||
vue init simulatedgreg/electron-vue my-project
|
||||
vue init simulatedgreg/Electron-vue my-project
|
||||
cd my-project
|
||||
npm install
|
||||
npm run dev
|
||||
@@ -461,9 +486,9 @@ Webpack 有一个 api: `watch-run`,可以针对代码文件检测,有变化
|
||||
```
|
||||
解决办法是在 main/index.dev.js 修改代码
|
||||
```javascript
|
||||
- require('electron-debug')({ showDevTools: true });
|
||||
- require('Electron-debug')({ showDevTools: true });
|
||||
+ // NB: Don't open dev tools with this, it is causing the error
|
||||
+ require('electron-debug')();
|
||||
+ require('Electron-debug')();
|
||||
```
|
||||
在 In main/index.js in the createWindow() function:
|
||||
```javascript
|
||||
@@ -490,7 +515,7 @@ Webpack 有一个 api: `watch-run`,可以针对代码文件检测,有变化
|
||||
|
||||
12. Electron 和 Web 开发相比,各自有侧重点
|
||||
|
||||

|
||||

|
||||
|
||||
### 2. 优化手段
|
||||
|
||||
@@ -529,7 +554,7 @@ node --cpu-prof --heap-prof -e "require('request’)”“
|
||||
|
||||
|
||||
|
||||
## 六、 技术体系搭建
|
||||
## 七、 技术体系搭建:全景
|
||||
|
||||
其实一个技术本身的难易程度并不是能否在自己企业、公司、团队内顺利使用的唯一标尺,其配套的 CI/CD、APM、埋点系统、发布更新、灰度测试等能否与现有的系统以较小成本融合才是很大的决定要素。因为某个技术并不是非常难,要是大多数开发者觉得很难,那它设计上就是失败的。
|
||||
|
||||
@@ -551,10 +576,234 @@ Electron 提供的 crash 信息进行包装。
|
||||
|
||||

|
||||
|
||||
```js
|
||||
import { BrowserWindow, app, dialog} from 'Electron';
|
||||
|
||||
|
||||
const mainWindow = BrowserWindow.fromId(global.mainId);
|
||||
mainWindow.webContents.on('crashed',
|
||||
const options = {
|
||||
type: 'error',
|
||||
title: '进程崩溃了',
|
||||
message: '这个进程已经崩溃.',
|
||||
buttons: ['重载', '退出'],
|
||||
};
|
||||
recordCrash().then(() => {
|
||||
dialog.showMessageBox(options, (index) => {
|
||||
if (index === 0) reloadWindow(mainWindow);
|
||||
else app.quit();
|
||||
});
|
||||
}).catch((e) => {
|
||||
console.log('err', e);
|
||||
});
|
||||
})
|
||||
|
||||
function recordCrash() {
|
||||
return new Promise(resolve => {
|
||||
// 崩溃日志请求成功....
|
||||
resolve();
|
||||
})
|
||||
}
|
||||
|
||||
function reloadWindow(mainWin) {
|
||||
if (mainWin.isDestroyed()) {
|
||||
app.relaunch();
|
||||
app.exit(0);
|
||||
} else {
|
||||
BrowserWindow.getAllWindows().forEach((w) => {
|
||||
if (w.id !== mainWin.id) w.destroy();
|
||||
});
|
||||
mainWin.reload();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
// index.js
|
||||
app.on('will-finish-launching', () => {
|
||||
if(!isDev) {
|
||||
require('./updater.js')
|
||||
}
|
||||
require('./crash-reporter').init()
|
||||
})
|
||||
|
||||
// crash-reporter.js
|
||||
const {crashReporter} = require('Electron')
|
||||
|
||||
function init() {
|
||||
crashReporter.start({
|
||||
productName: 'ZanPandora',
|
||||
companyName: 'youzan',
|
||||
submitURL: 'http://127.0.0.1:33855/crash',
|
||||
|
||||
})
|
||||
}
|
||||
module.exports = {init}
|
||||
|
||||
// server
|
||||
const Koa = require('koa')
|
||||
const app = new Koa()
|
||||
const Router = require('koa-router')
|
||||
const serve = require('koa-static-server')
|
||||
const router = new Router()
|
||||
const compareVersions = require('compare-versions')
|
||||
const multer = require('koa-multer')
|
||||
const uploadCrash = multer({dest: 'crash/'})
|
||||
router.post('/crash', uploadCrash.single('upload_file_minidump'), (ctx, next) => {
|
||||
console.log(ctx.req.body)
|
||||
// 存DB
|
||||
})
|
||||
```
|
||||
|
||||
### 4. 软件更新
|
||||
|
||||
```javascript
|
||||
// package.json
|
||||
"dependencies": {
|
||||
"Electron-is-dev": "^1.1.0",
|
||||
"Electron-squirrel-startup": "^1.0.0",
|
||||
// ...
|
||||
},
|
||||
|
||||
// index.js
|
||||
app.on('will-finish-launching', () => {
|
||||
if(!isDev) {
|
||||
require('./updater.js')
|
||||
}
|
||||
require('./crash-reporter').init()
|
||||
})
|
||||
|
||||
// updater.js
|
||||
const {autoUpdater, app, dialog} = require('Electron')
|
||||
if(process.platform == 'darwin') {
|
||||
autoUpdater.setFeedURL('http://127.0.0.1:33855/darwin?version=' + app.getVersion())
|
||||
} else {
|
||||
autoUpdater.setFeedURL('http://127.0.0.1:33855/win32?version=' + app.getVersion())
|
||||
}
|
||||
|
||||
autoUpdater.checkForUpdates() // 定时轮训、服务端推送
|
||||
autoUpdater.on('update-available', () => {
|
||||
console.log('update-available')
|
||||
})
|
||||
|
||||
autoUpdater.on('update-downloaded', (e, notes, version) => {
|
||||
// 提醒用户更新
|
||||
app.whenReady().then(() => {
|
||||
let clickId = dialog.showMessageBoxSync({
|
||||
type: 'info',
|
||||
title: '升级提示',
|
||||
message: '已为你升级到最新版,是否立即体验',
|
||||
buttons: ['马上升级', '手动重启'],
|
||||
cancelId: 1,
|
||||
})
|
||||
if(clickId === 0) {
|
||||
autoUpdater.quitAndInstall()
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
autoUpdater.on('error', (err) => {
|
||||
console.log('error', err)
|
||||
})
|
||||
|
||||
// server
|
||||
// index.js
|
||||
const Koa = require('koa')
|
||||
const app = new Koa()
|
||||
const Router = require('koa-router')
|
||||
const serve = require('koa-static-server')
|
||||
const router = new Router()
|
||||
const compareVersions = require('compare-versions')
|
||||
const multer = require('koa-multer')
|
||||
const uploadCrash = multer({dest: 'crash/'})
|
||||
router.post('/crash', uploadCrash.single('upload_file_minidump'), (ctx, next) => {
|
||||
console.log(ctx.req.body)
|
||||
// 存DB
|
||||
})
|
||||
function getNewVersion(version) {
|
||||
if(!version) return null
|
||||
let maxVersion = {
|
||||
name: '1.0.1',
|
||||
pub_date: '2020-02-01T12:26:53+1:00',
|
||||
notes: '新增功能AAA',
|
||||
url: `http://127.0.0.1:33855/public/ZanPandora-1.0.1-mac.zip`
|
||||
}
|
||||
if(compareVersions.compare(maxVersion.name , version, '>')) {
|
||||
return maxVersion
|
||||
}
|
||||
return null
|
||||
}
|
||||
router.get('/win32/RELEASES', (ctx, next) => {
|
||||
let newVersion = getNewVersion(ctx.query.version)
|
||||
if(newVersion) {
|
||||
ctx.body='BBC6F98A5CD32C675AAB6737A5F67176248B900C ZanPandora-1.0.1-full.nupkg 62177782'
|
||||
} else {
|
||||
ctx.status = 204
|
||||
}
|
||||
})
|
||||
router.get('/win32/*.nupkg', (ctx, next) => {
|
||||
// redirect s3 静态文件服务
|
||||
ctx.redirect(`/public/${ctx.params[0]}.nupkg`)
|
||||
})
|
||||
router.get('/darwin', (ctx, next) => {
|
||||
// 处理Mac更新, ?version=1.0.0&uid=123
|
||||
let {version} = ctx.query
|
||||
let newVersion = getNewVersion(version)
|
||||
if(newVersion) {
|
||||
ctx.body = newVersion
|
||||
} else {
|
||||
ctx.status = 204
|
||||
}
|
||||
})
|
||||
app.use(serve({rootDir: 'public', rootPath: '/public'}))
|
||||
app.use(router.routes())
|
||||
.use(router.allowedMethods())
|
||||
|
||||
app.listen(33855)
|
||||
```
|
||||
|
||||
|
||||
引申资料
|
||||
|
||||
- [electron-vue架构解析-开发环境启动流程分析](https://dushaofeng.github.io/2018/06/08/electron-vue架构解析-开发环境启动流程分析/)
|
||||
- [chromium 进程模型](https://www.chromium.org/developers/design-documents/process-models)
|
||||
|
||||
|
||||
## 八、 Electron 应用场景
|
||||
|
||||
### 1. 字节跳动
|
||||
|
||||
- Electron做了一个工具,能直接查看线上包的函数耗时,无任何侵入
|
||||
|
||||
- 调试工具的合集
|
||||
|
||||
- 研发需求管理
|
||||
|
||||
- 代码合并工具(MR)。区别于 gitlab 的特性,没有多仓合代码的能力。
|
||||
|
||||
比如同时在主工程系修改了7个 pod 、1个主工程的代码,需要分批次提交,不具备同时将8个仓库的代码原子性合入
|
||||
|
||||
pod 的 changeLog、版本号等需要设计自动发版的流程
|
||||
|
||||
- 把性能调试和效率工具都整合到一起了。
|
||||
|
||||
|
||||
|
||||
### 2. 阿里
|
||||
|
||||
- 沙盒的查看与操作,比如在 PC 端查看移动沙盒内文件内容、数据库文件的查看与 SQL 执行等
|
||||
- lint 功能、检测无用方法、在线日志解密查看、数据库文件的解密查看、jspatch 的 mock、
|
||||
- 针对网络请求和响应的操作,比如自定义请求、延迟、mock response、
|
||||
- Mock、查看
|
||||
- 性能测试:cpu、load、fps、启动耗时(机房有高速摄像机解帧,模拟点击 icon、启动页启动、App 首页出现、首页图片出现、App 可以滚动交互了。不需要 hook 去监控耗时)
|
||||
- pre-main、main、首页打点
|
||||
- 数据板:埋点体系的数据,看坑位的点击效果
|
||||
- 应用数据:沙盒、Cookie、数据
|
||||
- 开发工具:CPU、内存、OOM
|
||||
- 视觉:移动端元素的参考线
|
||||
- 网络、开关数据、卡顿、内存泄漏
|
||||
|
||||
|
||||
|
||||
一言以蔽之就是:通过 deviceID、ip 地址等与设备产生连接,将一切可以标准化的流程都抽象、自动化、比如性能调试和效率工具都整合到一起。
|
||||
|
||||
一个原则:该工具只做数据的查看、Mock 等工作,不做线上数据的干扰和生产
|
||||
|
||||
|
||||
Reference in New Issue
Block a user