背景
目前 Vue Devtools 已支持通过点击跳转至 VSCode 对应文件。但在 Vite 项目中,React Devtools 暂不支持此功能。
原因分析
React Devtools 的「Open in Editor」功能依赖形如 vscode://{file}/{path}:{line} 的跳转链接,该链接来源于 source map 中的 file 信息。
然而,Vite 默认生成的 source map 并不包含 file 字段,导致无法构建出正确的跳转链接,功能因此被置灰。
相关问题详见:facebook/react#28999
目标实现效果
目前有现有插件vite-plugin-vue-inspector,仿照它的效果来实现一个react的版本,效果如下:
实现原理分析
具体细节
function VitePluginInspector(): Plugin {
return {
name: "unplugin-react-inspector",
// 应用顺序
enforce: "pre",
// 含义: 转换钩子,接收每个传入请求模块的内容和文件路径
// 应用: 在这个钩子对jsx\tsx模版进行解析并注入自定义属性
transform(code, id) {
},
// 含义: 配置开发服务器钩子,可以添加自定义中间件
// 应用: 在这个钩子实现Open Editor调用服务
configureServer(server) {
},
// 含义: 转换index.html的专用钩子,接收当前HTML字符串和转换上下文
// 应用: 在这个钩子自动注入交互功能
transformIndexHtml(html) {
},
}
}
- 编译时注入
在
transform钩子进行ast解析,将resovledId和loc的信息注入
- 交互层注入
通过虚造路径,加载解析对应虚造的路径文件
async resolveId(id) {
// 处理虚拟路径
if (id.startsWith('virtual:react-inspector-path:')) {
const resolved = id.replace('virtual:react-inspector-path:', `${inspectorPath}/`)
return resolved
}
},
async load(resolveId) {
// 加载解析文件
if (resolveId.startsWith(inspectorPath)) {
if (fs.existsSync(resolveId)) {
return fs.readFileSync(resolveId, 'utf-8')
}
else {
console.error(`[unplugin-react-inspector] failed to find file: ${resolveId}`)
}
}
},
- 获取文件信息
在编译时已经为每一个元素注入了
options信息,提供了file、line、column信息。在经过元素的时候,可以拿到attribute属性,只需拿到有options属性的元素即可
const path = e.composedPath() as Element[]
// 过滤没有options属性的元素
const ignoreIndex = path.findIndex(node => node?.hasAttribute?.(KEY_IGNOE))
const targetNode = path.slice(ignoreIndex + 1).find((node: Element) => getData(node))
- 打开编辑器
vite内置已经实现了/__open_in_editor中间件,只需要发起fecth(url)
const openEditor = (baseUrl: URL, file: any, line: any, column: any) => {
const _url = baseUrl instanceof URL ? baseUrl : `/__open-in-editor?file=${encodeURIComponent(`${file}:${line}:${column}`)}`
const promise = fetch(_url, { mode: 'no-cors' })
return promise
}
vite的open in edtior也是参考react-developer-tool的utils文件实现的,它封装了一个服务中间件。因此直接使用即可。
具体可以参考:github.com/yyx990803/l…
致谢
整个实现都参考了两个项目: 1、vite-plugin-vue-inpsector 2、react-dev-inspector
总结
相关代码地址见下方,欢迎参考: github.com/Triumph-lig…
📌 如果觉得有帮助,欢迎点个 Star~
💬 如有问题,欢迎提 Issue 或指出改进建议!