尧图精选

Rust+Tauri+Vue打造10MB级高性能API调试工具

🕒 发布时间:2026/9/13 14:37:29 📁 来源:尧图网络
1. 项目概述为什么一个“10 MB、启动不到 1 秒”的 API 工具值得认真对待你有没有过这样的体验打开 Postman等它加载完主界面、同步状态、检查更新、初始化插件、再加载工作区——整个过程动辄 3~5 秒甚至在低配笔记本或远程桌面环境下卡顿到需要点两次图标更别提它背后那个常年驻留内存、占用 400MB RAM 的 Electron 进程以及每次升级后莫名其妙丢失环境变量、Collection 权限错乱、Cookie 管理失效的“玄学时刻”。这不是个别现象而是数百万 API 开发者每天都在默默忍受的“效率税”。而标题里这个“10 MB 的 Postman 替代品”不是概念演示也不是半成品 Demo它是一个真实可下载、开箱即用、Windows/macOS/Linux 全平台原生运行的桌面客户端——安装包仅 9.8 MB实测 Windows x64 版本双击后从点击到呈现完整请求编辑界面平均耗时 872 毫秒i5-1135G7 16GB 内存SSD冷启动最快一次记录为 613 毫秒。它不依赖 Node.js 运行时不打包 Chromium 渲染引擎不走 Web 技术栈的“重载”老路它用 Rust 编写核心网络层与状态管理用 Tauri 构建轻量级原生外壳前端 UI 则由 Vue 3 Composition API 驱动所有交互逻辑在毫秒级完成响应。它解决的不是一个“能不能用”的问题而是“要不要为工具本身持续支付时间成本”的根本矛盾。这个项目最核心的价值不在于它“比 Postman 少了哪些功能”而在于它重新定义了 API 工具的性能基线当一个工具的启动延迟低于人类感知阈值约 100ms它的存在就不再构成认知中断当它的内存常驻开销压到 80MB 以内它就能和 VS Code、Terminal、Figma 同时开着而不拖慢整机响应当它的安装包小到可以微信直接传给同事它就真正具备了团队快速对齐、零配置协作的传播力。它适合三类人一是嵌入式/边缘计算开发者比如正在用 ESP32-Rust 调试本地 HTTP 接口的工程师需要极简、确定、无后台干扰的调试环境二是前端团队中负责联调的 Vue 开发者希望在本地 dev server 启动后立刻切过去发个 POST 测试数据流而不是等 Postman 缓缓醒来三是 DevOps 或 SRE经常要在跳板机、CI 临时容器里快速验证一个 endpoint没有条件装完整版 Electron 应用。它不是 Postman 的平替而是“API 调试场景下的瑞士军刀”——专为高频、轻量、确定性操作而生。2. 整体架构设计与技术选型逻辑为什么是 Rust Tauri Vue 这个组合2.1 核心目标倒推技术栈性能、体积、可控性三重约束下的必然选择我们先明确这个项目的硬性边界条件体积上限 ≤ 10 MB排除任何打包 Chromium 的方案Electron 最小化构建仍超 120MB冷启动 ≤ 1000 ms要求二进制加载快、初始化逻辑极简、无异步等待阻塞主线程内存常驻 ≤ 100 MB禁止长期持有大对象、禁止未释放的 WebSocket 连接池、禁止冗余的 UI 渲染缓冲区跨平台一致性高Windows/macOS/Linux 行为一致不因系统差异导致请求头自动添加、证书校验逻辑不同等问题。这四个条件像四把尺子直接筛掉了绝大多数主流技术路径。比如用纯 WebView2Windows或 WKWebViewmacOS做外壳可行但 iOS/macOS 上 WebView 的 JS 执行环境隔离性差调试协议不统一且无法保证 Linux 支持用 Flutter Desktop2023 年后虽有进展但 Release 模式下 Linux 构建仍不稳定且默认包体积超 45MB含 Skia 引擎用 Qt QMLC 开发门槛高Vue 生态迁移成本大且 Qt 自带的网络模块QNetworkAccessManager在 HTTP/2 和 TLS 1.3 支持上滞后于现代标准。最终选定Rust Tauri Vue不是因为“热门”而是每个环节都精准命中约束维度Rust 的作用Tauri 的作用Vue 的作用体积控制编译为静态链接二进制无运行时依赖strip后可压缩至 3MB 内核逻辑替换 Electron仅用系统 WebView省去 100MB ChromiumVue Runtime 可通过vue/devtools按需注入生产环境仅打包vue.runtime.esm-bundler.js 25KB启动速度main()函数内完成最小初始化日志、配置读取、网络栈预热无 GC 停顿启动即加载系统 WebView无需下载/解压/校验渲染进程Vue App 实例创建在 WebView 加载完成后立即执行无 bundle 解析耗时Vite 构建为 ESM浏览器原生支持内存效率所有网络请求使用tokio异步运行时连接复用率 92%JSON 解析用simd-json比serde_json快 3.2 倍进程模型为单进程Rust 主进程 WebView 子进程无 Electron 的主进程/渲染进程/插件进程三层嵌套响应式系统基于 Proxy无 Vue 2 的 Object.defineProperty 递归劫持开销组件卸载时自动清理事件监听器提示Tauri 并非“简化版 Electron”它的底层是 Rust 的tauri-runtime所有 IPC 调用最终编译为系统级 FFI 调用而非 Electron 的 JSON 序列化 Node.js 中间层转发。这意味着一个invoke(send_request)调用从 Vue 触发到 Rust 处理函数执行全程耗时稳定在 0.18~0.23ms实测 i7-10875H而同等操作在 Electron 中平均为 1.7ms。2.2 为什么不用纯 Rust GUI如 egui、druid——开发效率与生态适配的权衡有读者会问既然追求极致性能为何不直接用 Rust 写 GUI比如egui即时模式 UI或druid声明式跨平台答案很实在UI 复杂度与开发可持续性的临界点已经越过。这个工具需要支持多标签页Tab管理每个 Tab 独立保存请求历史、响应时间线、Cookies请求体支持 raw/json/form-data/x-www-form-urlencoded 四种模式切换且 form-data 需文件选择器集成响应体支持语法高亮JSON/XML/HTML/Plain、折叠/展开、搜索定位环境变量管理全局 当前 Collection 当前 Request 三级作用域导入导出 CollectionPostman v2.1.0 格式兼容基础认证Basic、Bearer Token、API Key请求历史持久化SQLite加密存储敏感字段。如果全用egui实现意味着每个输入框要手写文本光标位置管理、IME 输入处理、剪贴板交互文件选择需调用rfdcrate 并桥接到 egui 的按钮事件状态同步逻辑复杂JSON 语法高亮需集成syntect或tree-sitter而tree-sitter的 Rust binding 在 Windows 上编译失败率高达 37%2024 Q1 数据响应体滚动区域需自行实现虚拟滚动否则 10MB 响应体直接 OOM。而 Vue 生态已有成熟方案monaco-editorVS Code 同源提供开箱即用的 JSON 高亮、折叠、搜索vue-file-agent封装了跨平台文件拖拽、预览、上传进度vue-router天然支持多 Tab 的路由状态映射pinia的 store 持久化插件可一键将环境变量加密存入 SQLite。所以技术选型的本质不是“谁更快”而是“在满足性能红线的前提下谁能让功能迭代速度更快、Bug 更少、团队协作成本更低”。Rust 负责“不可妥协的底层”网络、加密、存储Tauri 负责“安全可控的桥梁”IPC、系统能力暴露Vue 负责“快速迭代的表层”UI、交互、生态复用。三者分工清晰边界明确这才是工业级项目能长期维护的关键。2.3 Vue 为何选 Composition API 而非 Options API——响应式系统的底层优化空间可能有人疑惑Vue 2 也能跑在 Tauri 里为何坚持 Vue 3关键在响应式系统的重构。Options API 的响应式依赖this.$data的属性劫持所有 data 字段在组件创建时就被Object.defineProperty递归代理。而一个 API 工具的请求编辑器典型 data 结构如下interface RequestData { method: string; // GET/POST/PUT... url: string; headers: Recordstring, string; body: { type: raw | json | form; content: string }; auth: { type: none | basic | bearer; config: any }; // ... 还有 12 个其他字段 }若用 Options API即使用户只修改method整个RequestData对象的所有字段都会被 Proxy 拦截触发不必要的依赖收集。而 Composition API 的ref()/reactive()是细粒度的const method ref(GET)—— 仅当method.value被读取/赋值时才触发依赖const headers reactive({})—— 仅当headers[Content-Type]被访问时才建立依赖链。我们在实测中对比了两种写法对大型 Collection200 Requests的 Tab 切换性能Options API平均切换耗时 42ms主线程阻塞Composition API平均切换耗时 11ms其中 8ms 为 DOM 更新3ms 为响应式追踪。更重要的是Composition API 天然支持逻辑复用 —— 我们把“请求发送”逻辑抽成useRequestSender()Hook把“环境变量解析”抽成useEnvResolver()这些 Hook 可被任意组件导入且内部状态完全隔离。当某天需要增加“请求重放队列”功能时只需新增useRequestQueue()无需改动任何现有组件的 data 结构。这种可维护性在团队协作中比“省下 5ms 启动时间”更有长期价值。3. 核心模块拆解与实操要点从二进制构建到 UI 渲染的全链路3.1 Rust 核心层如何用 3 个 crate 实现高性能网络栈整个 Rust 侧代码量约 4200 行不含测试核心逻辑集中在三个 cratecore-network1800 行封装reqwesttokio提供send_request()同步接口实际为block_on包装确保 Tauri 命令不阻塞主线程core-storage1200 行基于rusqlitesqlx用于异步备份实现加密的 SQLite 存储密钥派生使用pbkdf2100_000 轮core-utils1200 行环境变量解析器支持{{host}}:{{port}}/api/{{version}}嵌套语法、JSON Schema 校验器轻量版jsonschemafork、MIME 类型探测器基于文件头 magic bytes。这里重点讲core-network的关键设计请求生命周期管理Postman 的一个痛点是当用户快速连续点击“Send”按钮时旧请求未结束新请求已发出导致响应体错乱、时间线显示异常。我们的解法是引入Request Token 机制// 在 core-network/src/request.rs #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct RequestToken(u64); impl RequestToken { pub fn new() - Self { // 使用原子计数器避免 rand::thread_rng() 的初始化开销 static COUNTER: AtomicU64 AtomicU64::new(0); Self(COUNTER.fetch_add(1, Ordering::Relaxed)) } } // Tauri 命令入口 #[tauri::command] async fn send_request( app_handle: tauri::AppHandle, request: HttpRequest, ) - ResultHttpResponse, String { let token RequestToken::new(); // 发送前广播 tokenUI 层据此取消旧请求 app_handle.emit(request-starting, token).map_err(|e| e.to_string())?; // 实际发送tokio::spawn_blocking 避免阻塞主线程 let response tokio::task::spawn_blocking(move || { // ... reqwest 发送逻辑此处省略 HttpResponse { token, status: 200, body: ..., headers: vec![] } }).await.map_err(|e| e.to_string())?; // 发送后广播完成事件 app_handle.emit(request-finished, response.clone()).map_err(|e| e.to_string())?; Ok(response) }Vue 层监听request-starting事件一旦收到新 token立即调用abortController.abort()终止上一个请求的fetch调用注意这里不是终止 Rust 层而是终止前端展示层的 pending 状态。这样既保证了 Rust 层请求的真实执行避免资源浪费又确保 UI 层永远只显示最新一次请求的结果。TLS 证书处理绕过系统证书库的确定性方案Postman 在企业内网常因自签名证书报错用户需手动点击“Continue Anyway”而我们的方案是默认信任系统证书库但允许用户通过 UI 导入 PEM 格式根证书并动态添加到reqwest::ClientBuilder的add_root_certificate()中。关键代码// core-network/src/client.rs pub fn build_client(cert_pem: Optionstr) - ResultClient, Boxdyn std::error::Error { let mut builder reqwest::ClientBuilder::new(); if let Some(pem) cert_pem { let cert reqwest::Certificate::from_pem(pem.as_bytes())?; builder builder.add_root_certificate(cert); } // 强制启用 HTTP/2比 HTTP/1.1 节省 30% 连接建立时间 builder builder.http2_prior_knowledge(); Ok(builder.build()?) }这个设计让工具在金融、政务等强证书管控环境中也能开箱即用无需修改系统设置。3.2 Tauri 层IPC 通信的零拷贝优化实践Tauri 的默认 IPC 机制是 JSON 序列化/反序列化对于大响应体如 5MB JSON序列化耗时可达 120msserde_json::to_string。我们采用Shared Memory Message Passing方案优化Rust 侧将响应体写入内存映射文件memmap2crate生成唯一 ID通过 IPC 发送该 ID字符串 32 字节给前端Vue 侧用fetch(tauri://memmap/ id)直接读取内存映射内容Tauri 提供tauri-plugin-fs插件支持前端拿到 ArrayBuffer 后用TextDecoder解码为字符串交由 Monaco 渲染。实测对比10MB JSON 响应方案序列化耗时传输耗时前端解析耗时总耗时默认 JSON IPC280ms15ms90ms385msShared Memory0ms2ms85ms87ms注意tauri-plugin-fs的read_binary接口在 1.10 版本已支持直接返回ArrayBuffer无需额外 base64 编码这是性能飞跃的关键。我们为此专门提交了 PR 修复其在 macOS 上的 mmap 权限 bugPR #1287。3.3 Vue 层Monaco Editor 的深度定制与性能陷阱规避响应体查看器是用户停留时间最长的区域我们选用 MonacoVS Code 同源而非highlight.js因为它支持虚拟滚动10MB 文件不卡顿按需语法高亮只高亮可视区域内置 JSON Schema 校验配合后端 OpenAPI 文档键盘快捷键CtrlF 搜索、CtrlShiftP 命令面板。但 Monaco 有两大坑必须填平坑一首次加载白屏时间长 800msMonaco 的 AMD 模块加载器默认按需加载语言包首次打开 JSON 响应时会动态请求json.worker.js、editor.main.js等 7 个文件。我们的解法是构建时用monaco-editor-webpack-plugin预打包所有依赖在vite.config.ts中配置optimizeDeps.include强制预构建启动时用monaco.editor.defineTheme()注册暗色主题避免 CSS 重绘。坑二大文件下内存泄漏Chrome DevTools 显示 detached DOM 节点根源在于 Monaco 的dispose()方法未正确清理ResizeObserver。我们封装了一个SafeMonacoEditor组件script setup langts import { onBeforeUnmount, onMounted, ref } from vue import * as monaco from monaco-editor const container refHTMLElement | null(null) let editor: monaco.editor.IStandaloneCodeEditor | null null onMounted(() { if (!container.value) return editor monaco.editor.create(container.value, { value: props.content, language: json, readOnly: true, automaticLayout: true, minimap: { enabled: false }, // 关闭 minimap 节省 40MB 内存 scrollbar: { vertical: auto, horizontal: auto } }) }) onBeforeUnmount(() { if (editor) { // 强制清除 ResizeObserverMonaco 1.85 已修复但需兼容旧版 const observer (editor as any)._resizeObserver if (observer typeof observer.disconnect function) { observer.disconnect() } editor.dispose() editor null } }) /script实测表明此方案使 10MB 响应体在连续打开/关闭 50 次后内存增长 2MB未处理时达 180MB。4. 实操全流程从零构建、调试到发布一个可用版本4.1 本地开发环境搭建5 分钟完成全栈启动我们假设你已安装 Rust1.75、Node.js18.18、Python3.9用于构建 SQLite 扩展。以下是精确到命令的步骤步骤 1克隆并安装依赖# 克隆官方仓库注意非 GitHub 镜像直连 git clone https://github.com/rustfox/rustfox.git cd rustfox # 安装 Tauri CLI全局 npm install -g create-tauri-app # 安装前端依赖Vue 侧 cd src-tauri npm install # 安装 Rust 依赖核心侧 cd .. cargo build --release # 首次编译约 3 分钟启用 LTO 优化步骤 2启动开发服务器前后端热重载# 终端 1启动 Vue 开发服务器Vite cd src-tauri npm run tauri dev # 终端 2启动 Rust 核心服务可选用于调试网络层 cd .. cargo run --bin rustfox-core-dev此时访问http://localhost:1420Tauri 默认端口即可看到界面。注意tauri dev模式下前端代码由 Vite 提供 HMR热模块替换Rust 侧代码修改后需手动重启但得益于 Tauri 的 IPC 设计前端 UI 不会因此崩溃。步骤 3关键配置文件解读src-tauri/tauri.conf.json核心配置重点关注bundle: { targets: [deb, appimage, nsis] }Linux/macOS/Windows 打包目标src-tauri/Cargo.tomlRust 依赖tauri { version 1.10, features [fs-all, shell-open] }启用文件系统和 Shell 能力src-tauri/src/main.rsTauri 应用入口setup()函数中注册所有自定义命令如send_request,save_collectionsrc-tauri/src/core/mod.rsRust 核心模块入口pub mod network; pub mod storage;显式声明模块树。实操心得新手常卡在tauri dev报错 “Failed to find WebView2 runtime”。解决方案是Windows 用户安装 WebView2 Runtime 离线安装包约 12MBmacOS 用户确保系统版本 ≥ 12.0WebKit 15.4Linux 用户安装webkit2gtk-4.1Ubuntu/Debiansudo apt install libwebkit2gtk-4.1-dev。4.2 构建生产包如何把体积压到 9.8 MB生产构建不是简单执行tauri build而是需要多层精简第一层Rust 编译优化在Cargo.toml的[profile.release]下添加lto true # 启用链接时优化 codegen-units 1 # 减少并行编译单元提升优化效果 panic abort # 移除 panic unwind 表节省 1.2MB strip true # 自动 strip 符号表第二层前端资源压缩vite.config.ts中配置export default defineConfig({ build: { rollupOptions: { output: { manualChunks: { // 将 monaco-editor 单独打包避免与业务代码耦合 monaco: [monaco-editor] } } }, // 启用 brotli 压缩比 gzip 小 15% terserOptions: { compress: { drop_console: true, drop_debugger: true } } } })第三层Tauri 打包裁剪执行构建命令# 清理旧构建 tauri clean # 构建 Windows NSIS 安装包关键参数 tauri build --target x64 --ci \ --featuresproduction \ --no-dev-server \ --verbose # 构建后检查体积 ls -lh src-tauri/target/release/bundle/nsis/RustFox_*.exe # 输出RustFox_0.8.2_x64-setup.exe 9.78 MB注意--ci参数禁用交互式提示--no-dev-server跳过 Vite 开发服务器启动--featuresproduction启用 Rust 的 production feature如禁用 debug 日志。我们曾因漏掉--no-dev-server导致安装包里意外打包了 Vite 的 12MB 依赖体积飙升至 22MB。4.3 真机测试 checklist覆盖 95% 的用户场景构建完成后绝不能直接发布。我们有一份真机测试清单覆盖从低端到高端设备设备类型测试项通过标准失败案例Windows 低配i3-7100U 4GB RAM冷启动时间、连续发送 10 次请求的内存增长启动 ≤ 1200ms内存增长 15MB曾因未关闭 Monaco minimap内存增长达 42MBmacOS M18GBHTTPS 自签名证书处理、中文路径文件上传点击“信任证书”后请求成功文件名显示正常早期版本在 M1 上reqwestTLS 握手超时需升级到reqwest 0.12.4Ubuntu 22.04GNOME Wayland系统托盘图标、文件拖拽上传、HiDPI 缩放托盘图标清晰拖拽后文件名 UTF-8 正确缩放 150% 无模糊Wayland 下 GTK 文件对话框需libgtk-3-0否则崩溃企业内网 Win10无外网离线模式启动、本地 OpenAPI 文件导入无网络时仍能加载 UI导入swagger.json成功依赖unpkg.com的 Monaco CDN已改为本地node_modules/monaco-editor/min/vs每台设备测试需记录htop/Activity Monitor的实时内存曲线截图保存。这份清单让我们在 v0.8.0 版本上线前提前发现并修复了 7 个平台特异性 Bug。5. 常见问题与排查技巧实录来自 237 次用户反馈的真实战场5.1 启动失败类问题90% 源于系统环境缺失问题 1“Application failed to start: WebView2 not found”现象双击安装包弹窗报错日志显示WebView2Loader.dll not found。原因Windows 10 1803 以下版本无内置 WebView2且用户未安装运行时。解决方案方案 A推荐在安装包中捆绑 WebView2 Bootstrapper微软官方3MB方案 B引导用户手动下载 WebView2 Runtime 方案 C企业部署用 PowerShell 静默安装Invoke-WebRequest -Uri https://go.microsoft.com/fwlink/p/?LinkId2124703 -OutFile $env:TEMP\WebView2Setup.exe Start-Process $env:TEMP\WebView2Setup.exe -ArgumentList /silent /install -Wait问题 2“Failed to initialize SQLite database”现象首次启动后界面空白DevTools 控制台报SQLITE_CANTOPEN。原因应用试图在只读目录如 Program Files写入数据库Windows UAC 拦截。解决方案Rust 侧强制将数据库路径设为%APPDATA%\RustFox\database.dbWindows或~/Library/Application Support/RustFox/database.dbmacOS安装包使用 NSIS 脚本在安装时创建目录并赋予用户完全控制权限前端增加友好提示“检测到权限不足已自动切换至用户目录”。实操心得我们曾收到 32 次同类反馈最终在 v0.7.3 版本加入自动路径迁移逻辑 —— 若检测到旧路径不可写则将数据迁移到新路径并弹窗告知用户。这个改动让启动失败率从 12.7% 降至 0.3%。5.2 功能异常类问题网络与 UI 的协同故障问题 3“发送请求后响应体为空但状态码显示 200”现象请求明明成功但响应体区域显示空白Network 面板却能看到完整数据。排查路径检查是否启用了“响应体自动格式化”Settings → Response → Auto-format JSON查看 Monaco 控制台右键 → Inspect Element → Console是否有RangeError: Invalid array buffer length执行navigator.clipboard.readText()测试剪贴板权限某些企业策略禁用最终定位textDecoder.decode(arrayBuffer)在 Chrome 120 对超大 ArrayBuffer 2GB抛出 RangeError但我们的响应体最大限制为 100MB故排除。根因用户开启了“隐私模式”禁用了SharedArrayBuffer导致 Tauri 的内存映射通道降级为 JSON IPC而响应体 JSON 序列化时因特殊字符如\u2028行分隔符解析失败。修复在 Rust 侧序列化前对响应体字符串执行json_escape()转义所有 Unicode 控制字符前端JSON.parse()前先unescape()。问题 4“环境变量{{base_url}}在请求 URL 中不生效但在 Headers 中生效”现象URL 输入{{base_url}}/users发送后实际请求https://{{base_url}}/users多出https://前缀。原因URL 输入框的校验逻辑将{{base_url}}误判为不完整 URL自动补全协议。修复方案在useEnvResolver()Hook 中对 URL 字段单独处理先提取{{xxx}}占位符再拼接增加视觉提示当 URL 包含{{}}时输入框边框变为橙色并 tooltip 提示“检测到环境变量将跳过协议校验”。5.3 性能瓶颈类问题如何定位毫秒级延迟问题 5“切换 Tab 时偶发卡顿DevTools 显示 Long Task 100ms”分析工具Chrome DevTools → Performance → Record勾选Screenshots在卡顿时按CmdShiftP→ 输入Capture layer tree查看Composite Layers面板确认是否因transform: translateZ(0)强制 GPU 加速导致图层过多。根因Vue 的Transition组件在 Tab 切换时对整个响应体区域执行opacity动画触发浏览器重排Reflow。修复移除响应体区域的过渡动画改用v-show切换 display对请求历史列表启用v-memoVue 3.2缓存未变化的 DOM 节点最终将 Tab 切换 Long Task 从 112ms 降至 8ms。问题 6“连续发送 50 次请求后内存占用从 80MB 涨到 1.2GB”诊断命令# Linux/macOS监控进程内存 watch -n 1 ps aux | grep rustfox | grep -v grep # WindowsPowerShell Get-Process rustfox | Select-Object WS,PM,Id,ProcessName根因core-network中的reqwest::Client实例被重复创建每次请求新建 Client导致连接池未复用TCP 连接堆积。修复将Client提升为全局单例lazy_static!或once_cell::sync::Lazy设置ClientBuilder::pool_max_idle_per_host(100)添加连接池监控client.pool_idle_size()每 5 秒上报到 DevTools。修复后50 次请求后内存稳定在 95MB ± 3MB。5.4 用户行为类问题那些文档不会写的“人性细节”问题 7“复制响应体 JSON 后粘贴到 VS Code 里格式错乱”现象用户右键“Copy Response”在 VS Code 中CtrlV结果 JSON 缺少换行、缩进全乱。原因navigator.clipboard.writeText()只能写纯文本而 Monaco 的getSelection().getText()返回的是无格式字符串。解决方案新增“Copy Formatted”按钮调用monaco.editor.getFormattedText()内部使用prettier按CtrlShiftC快捷键触发格式化复制在设置中增加选项“默认复制格式
上一篇/下一篇内容由系统自动关联 返回资讯列表 →