余玮杰,2018年3月加入去哪儿网技术团队。目前在大住宿事业部/大前端/RN,参与开发大住宿RN和callcenter等相关业务。本人对前端相关领域的知识充满了兴趣,并且不断学习中。
如何有效的、快捷的调试代码都是一个比较难的学问,调试 RN 代码更是如此。在编写 RN 代码时,开发者一般能常用到调试方法: (1)官方提供的调试工具:通过 console 大法或 debugger 来进行调试; (2)react devtools:react 官方提供调试工具,但是不支持调试 RN; (3)redux devtools:redux 调试工具,能监听 redux 中任何时候的 state; (4)xcode 或 Android stdiuo: 不支持 debug js code。本文就向大家介绍一个调试 RN 代码的利器——ReactNative Debugger(简称:RN Debugger)。
RN Debugger 是一个独立的 app,用于 Debug RN 程序,通过 electron 框架编写的。 基于官方的本地调试器,并且具有更多的功能,结合 react devtools 可以监听 react,同时结合了redux devtools 用于监听 redux。
上图所示就是 RN Debugger 的界面,其中: (1)redux devtools 部分就是可以监听 RN 中的 redux 的 state,与 redux devtools extension 使用方法一样。 (2)react devtools 部分监听 react 的元素,可以查看 RN 中各个元素的样式及在代码中所处的位置。 (3)console 部分就是官方提供的本地调试器。
对于 macOS,可以使用 homebrew cask 进行安装:
$ brew update && brew cask install react-native-debugger
安装后,会发现这是个独立的 app,所以可以在启动台直接启动 RN Debugger。
打开之前,首先需要确保其余的 RN 调试工具都是关闭,如 http://localhost:/debugger-ui。一般默认下,RN Debugger 是默认监听8081端口,而且 RN 程序默认也是8081端口启动。 同时,需要在 RN 程序中此开关(此图对应的是 qrn 程序,如果是原生的 RN 程序,需要打开 debug js remotely)。
当开启后,进入 RN 界面后,会发现此事时 react native debugger 开始启动,这样就可以通过 RN Debugger 来调试 RN 的程序了。
有时启动 RN 程序时,会采用不同的端口,而这里 RN Debugger 也有针对此操作进行设计。打开菜单栏的 debugger 选项后,选择 new window(快捷键command+T)会打开新的 RN debugger 界面,此时在输入框中输入要监听的端口号,就可以调试从非8081端口启动的 RN 程序。
此工具会启用 webSocket 服务来等待 RN 的连接。对于 QRN 的程序(原生的 RN 程序,无须做任何操作),此时我们只需要打开 js debug mode 功能(此开关打开后会导致 RN 启动较慢)。
当打开 RN 的菜单时,选择检查元素(对应原生的为 show inspector),当点击 RN 项目中的某个元素时,RN Debugger 中的 react devtools,会连接到 RN 程序,并且显示其元素的具体信息。
这部分显示的是组件的层次结构,可以很清楚的了解你所点选的组件在哪个层次结构中。
这部分显示的为组件的 props、state、context 及组件属性的信息,这里可以修改其中的任何值。
其中上部分,代表的为元素的样式信息,当你点击样式的某个属性时,可以修改其值。这里修改后,会实时的渲染 RN 程序,无须重新加载,所以在调试样式或组件属性时,特别方便。
上图显示的为此元素对应于 RN 项目中代码所处的位置,点击后,会跳转到编辑器(仅限 macos 下的 sublime、vscode、atom)中相应的位置(这功能首先需要设置系统 PATH 中安装启动编辑器命令,如 vscode 可以在编辑器直接设置 code 命令,则在命令行中输入 code 打开编辑器)。当开启 js 调试功能后,RN Debugger 会自动将作用域切换到 RN DebuggerWorker 下,这样就会获得 RN 的全局变量。 (1)$r: 你在react-devtools中所选择的元素。 (2)showAsyncStorageContentInDev():显示AsyncStorage内容。 (3)require(...) (RN < 0.56)/$reactNative.*(RN >= 0.56):获取 RN 的模块。
当打开 debug in chrome 后,RN Debugger 会暴露 redux-devtools-extension 下方的三个 api 会存在于全局中。 (1)window.REDUXDEVTOOLSEXTENSION (2)window.REDUXDEVTOOLSEXTENSIONCOMPOSE (3)window.REDUXDEVTOOLS_EXTENSION.connect 打开 RN 程序后,会发现 redux devtools 功能还是没有 state 信息,那是因为还需要将 redux-devtools-extension 的作为中间件用于 store 中。
import { compose, createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import reducers from '../reducers';
const middleware = [thunk];
// eslint-disable-next-line no-underscore-dangle
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default createStore(reducers, composeEnhancers(applyMiddleware(...middleware)));
这样,RN Debugger 可以监听 redux 中的各个时刻的 state,并且可以使用提供的 redux 工具的各种功能。
在调试时,当需要重新刷新或者监听元素时,总是需要去 RN 程序中点击或者 command+z,而有了 RN Debugger 之后,只需要在界面右键点击后,就可以通过上下文菜单来对 RN 进行控制,这样再也不需要在 RN 中长按刷新后来进行检查元素或点击刷新后重新加载。
RN Debugger 也可以监听网络请求。 首先在菜单中开启 network 监听功能, 其次需要在代码中添加以下代码,才能监听到 RN 中的 fetch 和 XMLHttpRequest。
// 我是将本部分代码加入到index.ios.js中
global.XMLHttpRequest = global.originalXMLHttpRequest
? global.originalXMLHttpRequest
: global.XMLHttpRequest
global.FormData = global.originalFormData
? global.originalFormData
: global.FormData
fetch // Ensure to get the lazy property
if (window.__FETCH_SUPPORT__) {
// it's RNDebugger only to have
window.__FETCH_SUPPORT__.blob = false
} else {
/*
* Set __FETCH_SUPPORT__ to false is just work for `fetch`.
* If you're using another way you can just use the native Blob and remove the `else` statement
*/
global.Blob = global.originalBlob ? global.originalBlob : global.Blob
global.FileReader = global.originalFileReader
? global.originalFileReader
: global.FileReader
}
监听网络请求也可以在官方的本地调试中实现,然而在独立 RN Debugger 中具有以下优点: (1)因为是 electron 框架,所以不存在 CORS 问题; (2)同时允许禁止的头部名,比如 origin 和 user-agent。 下方则是在代码采用了 fetch 方法请求了一个接口,然后请求后,可以发现在 network 中可以监听到网络请求信息。
RN Debugger 监听网络请求仍有不足之处,比如无法监听图片加载信息,所以如果想监听更深层次的网络,则最好使用 charles。
在菜单栏中打开此项功能,就可以点击 console 界面中源码链接后直接跳转到默认编辑器中。
RN Debugger 提供了配置文件,可以方便开发者修改配置项,省却了每次都需要修改的麻烦。
{
// 修改字体
fontFamily: 'monaco, Consolas, Lucida Console, monospace',
...
// 修改宽高
windowBounds: {
// Size of the debugger window, it will override persisted size
width: 1024,
height: 750,
},
// 是否自动更新
autoUpdate: true,
// 默认监听端口号
defaultRNPackagerPorts: [8081],
// 打开react devtools 源码文件链接或点击console中信息后跳转的编辑器
editor: '',
// 设置主题
// see https://github.com/facebook/react-devtools/blob/master/frontend/Themes/Themes.js to get more
defaultReactDevToolsTheme: 'RNDebugger',
// 默认是否打开网络监听
// See https://github.com/jhen0409/react-native-debugger/blob/master/docs/network-inspect-of-chrome-devtools.md
defaultNetworkInspect: false,
}
在使用 RN Debugger 中,会因为使用时间较长,会导致高额的内存被占用,这主要是因为采用了官方的本地调试,所以比较简便的方法时,使用快捷键重新 chrome devtools (macOS: CMD+OPTION+I,Linux/ Windows: CTRL+ALT+I)。
回顾本文,可以发现RNDebugger调试器为开发者以后调试RN代码提供了不错的功能: (1)通过点击元素跳转到对应代码; (2)直接在调试面板上修改样式代码; (3)通过 redux-devtools 获取到对应的 redux 的 state; (4)能开启多个 debugger 监听多个端口; (5)能监听网络请求。 虽然仍有不足之处,但是还是不断地再完善,所以 RN 开发者可以尝试使用此调试工具,最终你会爱上它的。