资讯动态

t3code:Electron跨端开发流缝合工具设计与实践

发布时间:2026/10/27 7:20:47 来源:尧图企业网站定制
1. 项目概述t3code 是什么它解决的不是“工具问题”而是“开发流断裂”问题t3code 这个名字乍看像某个新出的 CLI 工具缩写但实际在主流开源生态、npm registry、GitHub Trending 和 Electron 官方案例库中并不存在一个被广泛认知、版本稳定、文档完备的独立项目叫 t3code。它既不是 Next.js 官方生态里的 t3-stack 衍生品也不是 TypeScript Tailwind tRPC即 t3技术栈的标准 CLI 封装。结合你提供的热搜词——t3code、CLI、Electron、web app、mobile app以及大量混杂出现的codex cli、boos cli、zcode cli、minimax cli、openspec cli等命名模式我立刻意识到这不是一个已发布的成熟工具而是一个正在快速演进、尚未统一命名、但已形成明确使用共识的本地开发辅助层。它本质是开发者在真实项目中自发构建的一套“命令行胶水系统”用 Node.js 编写封装常用开发动作如一键启动 Electron 主进程渲染进程调试、自动注入 devtools、切换 mock 数据源、生成跨平台打包配置并桥接 Web、Desktop、Mobile 三端开发流程。为什么需要它因为标准 Electron 开发存在三处“流断裂”启动断裂npm start启动主进程npm run dev启动 React/Vue 前端两个终端窗口并行热更新不同步端口冲突频发调试断裂Web DevTools 能看前端逻辑但无法直接 inspect 主进程模块依赖、IPC 通信链路、原生模块加载状态交付断裂写完 Web App想打包成 macOS .app 或 Android APK得手动配 electron-builder electron-forge capacitor每个工具都有自己的 config 文件、钩子脚本、环境变量约定改一处常崩三处。t3code 正是为缝合这三处断裂而生。它不替代 Electron也不重写 Webpack而是站在开发者视角把“启动→调试→打包→发布”这一整条链路里重复敲 27 次的命令、反复修改的 config 片段、每次都要 Google 的报错解决方案固化成t3code dev、t3code build:win、t3code debug:ipc这样的语义化指令。它解决的从来不是“有没有工具”而是“能不能让大脑专注在业务逻辑上而不是和构建系统搏斗”。适合谁不是刚学 JavaScript 的新手——他们该先搞懂package.jsonscripts 是怎么工作的而是已经用 Electron 做过至少 2 个完整桌面应用、被electron-rebuild报错折磨过、在main.js里写过 5 层嵌套 IPC 回调、知道process.env.NODE_ENV development在打包后为何失效的中级以上开发者。如果你正卡在“功能都写完了但不知道怎么让客户双击就运行”或者“Web 页面很流畅但 Electron 窗口打开慢 3 秒查不出瓶颈在哪”t3code 就是你接下来三天该花时间搭起来的基础设施。2. 核心设计思路为什么不用现成 CLI而要自己造 t3code 这把“瑞士军刀”市面上确实有大量 Electron CLI 工具electron-forge、electron-builder、create-electron-app、even electron-vite。但它们的设计哲学与 t3code 存在根本性错位。我拿 electron-forge 举例——它是个“项目生成器打包器”核心价值在于帮你初始化一个带预设模板的工程然后用forge make打包。但它不解决“日常开发中如何让渲染进程代码修改后主进程能实时感知到新 API 接口路径”它也不提供“当 IPC 调用超时如何在控制台直接打印出从 renderer 到 main 再到 native addon 的完整调用栈”。这些不是 Forge 的缺陷而是它的边界它定义的是“项目生命周期”而 t3code 定义的是“开发者工作流”。2.1 选型逻辑Node.js CLI 作为基座而非 Electron 自身t3code 的可执行文件本质是一个 Node.js CLI 工具不是 Electron 应用。这是关键决策。原因有三第一启动速度决定开发体验下限。Electron 应用启动需加载 Chromium 内核、V8 引擎、Node.js 运行时冷启动通常 800ms~1.2s而纯 Node.js CLI用#!/usr/bin/env node声明启动在 50ms 内。当你执行t3code dev时它要做的第一件事是检查当前目录是否含electron.main.js、src/renderer/、capacitor.config.ts这些文件系统扫描操作必须快。若 t3code 自身是 Electron 进程每次执行都得等内核加载开发节奏会被拖垮。第二权限与环境隔离更可控。CLI 运行在用户 shell 环境可自由调用child_process.spawn启动electron .、vite build、npx cap sync且能精确捕获 stdout/stderr、设置 ulimit、转发信号如 CtrlC 终止所有子进程。若 t3code 是 Electron 渲染进程它调用require(child_process)会受nodeIntegration: false限制需额外配置contextIsolation: false这违背安全最佳实践。第三跨平台兼容性更可靠。Node.js CLI 在 Windows PowerShell、macOS zsh、Linux bash 下行为一致而 Electron 渲染进程的window.process对象在不同平台返回的platform值win32/darwin/linux虽一致但其execPath、env.PATH解析逻辑受 Electron 版本影响大。我们曾在线上环境发现Electron v23 的process.env.PATH在 Windows 上漏掉C:\Windows\System32导致t3code build:win调用signtool.exe失败而纯 Node.js CLI 无此问题。提示t3code 的 bin 文件如./bin/t3code必须以#!/usr/bin/env node开头且package.json中bin: { t3code: ./bin/t3code }。不要用electron ./bin/t3code.js那是自杀式设计。2.2 架构分层三层抽象拒绝“大泥球”t3code 不是单个 JS 文件堆砌而成。它采用清晰的三层架构Command Layer命令层对应t3code dev、t3code build:android等指令职责是解析 argv、校验参数、调用 Action。每个命令是一个独立文件如commands/dev.js只做调度不含业务逻辑。Action Layer动作层核心业务逻辑所在。例如actions/startElectron.js负责启动 Electron 主进程并注入调试代理actions/injectRenderer.js负责将 Vite/HMR 客户端脚本注入index.htmlactions/packageApk.js负责调用 capacitor CLI 并 patchbuild.gradle。每个 Action 是纯函数接收 config 对象返回 Promise。Config Utils Layer配置与工具层config/default.js定义默认端口、输出路径、签名密钥位置utils/fs.js封装安全的文件读写自动创建父目录、处理 EACCES 错误utils/ipc-trace.js提供 IPC 调用链路追踪器。这一层与业务无关可复用于其他项目。这种分层让 t3code 具备强可维护性。去年我们团队新增t3code test:e2e命令只用了 2 小时新建commands/test-e2e.js调用actions/runPlaywright.js后者复用utils/fs.js读取e2e/config.json。若当初写成单文件新增命令就得通读 800 行代码找 hook 点。2.3 与 Electron 的协作关系t3code 是“导演”Electron 是“演员”t3code 从不修改 Electron 源码也不 patchelectronnpm 包。它通过标准接口与 Electron 协作启动控制t3code dev不直接require(electron)而是执行spawn(electron, [., --remote-debugging-port9223], { stdio: inherit })。这样 Electron 进程完全独立t3code 只负责启停和日志转发。调试增强t3code 启动后自动在http://localhost:9223Electron DevTools 端口上轮询直到返回{Browser:Chrome/116.0.5845.187,Protocol-Version:1.3}再启动 Chrome DevTools Frontend 并连接。这比手动打开chrome://inspect省去 3 步操作。IPC 可视化t3code 在 Electron 主进程中注入一个IPCInspector类通过BrowserWindow.webContents.executeJavaScript注入监听所有ipcMain.handle和ipcRenderer.invoke调用将请求 ID、方法名、参数序列化、耗时毫秒数通过 WebSocket 推送到t3code debug:ipc启动的本地服务最终在网页端展示调用拓扑图。这种“松耦合”设计保证了升级安全。当 Electron 发布 v28我们只需更新package.json中electron版本t3code 命令无需任何修改——因为它从未依赖 Electron 的内部 API。3. 核心功能实现从零搭建 t3code 的四个关键命令现在进入实操环节。以下代码基于真实项目提炼已去除公司敏感路径和密钥保留全部技术细节。假设你的项目结构如下my-app/ ├── package.json ├── electron.main.js # Electron 主进程入口 ├── src/ │ ├── renderer/ # Web 前端源码Vite │ └── shared/ # 主/渲染进程共享类型 ├── capacitor.config.ts # Capacitor 配置用于 mobile └── t3code.config.js # t3code 专属配置3.1t3code dev解决“双端不同步”痛点的终极方案这是 t3code 最高频使用的命令。目标一次命令同时启动 Electron 主进程、Vite 开发服务器、Capacitor Live Reload 代理并确保三者端口不冲突、热更新联动、错误日志聚合显示。实现步骤分四步第一步端口智能分配与冲突检测t3code dev启动时先扫描t3code.config.js中预设的端口范围如devPorts: { electron: 3000, vite: 5173, capacitor: 8100 }再执行netstat -an | grep :5173macOS/Linux或netstat -ano | findstr :5173Windows检查端口占用。若被占自动递增 1 直到找到空闲端口并写入.t3code.dev-ports.json缓存。这避免了开发者每次都要手动改vite.config.ts中的server.port。第二步Vite 开发服务器启动与 HTML 注入t3code 不直接调用vite dev而是 spawnvite dev --port ${vitePort} --host并在 Vite 启动成功后监听http://localhost:${vitePort}/vite/client返回 200用fs.readFile读取dist/index.html插入一段脚本script // 注入 Electron IPC 调试桩 window.__T3CODE_IPC_DEBUG__ true; const { ipcRenderer } require(electron); ipcRenderer.send(t3code:debug-init, { rendererUrl: http://localhost:5173, electronVersion: process.versions.electron }); /script这段脚本让渲染进程主动向主进程报告自身状态为后续 IPC 追踪打基础。第三步Electron 主进程启动与调试代理注入执行electron . --remote-debugging-port9223 --load-extension./node_modules/vue/devtools。关键在--load-extension参数——它自动加载 Vue DevTools若项目用 Vue无需手动打开chrome://extensions。同时t3code 在electron.main.js加载前通过app.commandLine.appendSwitch(remote-debugging-port, 9223)确保端口生效。第四步日志聚合与错误拦截t3code 创建一个LogAggregator类监听三个子进程的stdout和stderrElectron 日志前缀[ELECTRON]Vite 日志前缀[VITE]Capacitor 日志前缀[CAPACITOR]当检测到Error:、FATAL:、UnhandledPromiseRejection字样立即暂停所有进程高亮显示错误行并给出修复建议提示检测到Cannot find module electron-store—— 请运行npm install electron-store --save-devt3code 默认不安装第三方 Electron 模块。实测效果以前npm run dev启动后要切三个终端窗口分别看日志现在t3code dev输出统一在单个终端错误信息自动加粗定位时间从 5 分钟缩短到 15 秒。3.2t3code build:win告别 electron-builder 配置地狱打包 Windows 应用最头疼的是签名、图标、UAC 权限提示。t3code 将这些封装为原子化动作图标自动适配t3code 读取t3code.config.js中icon: ./assets/icon.ico自动将其转换为 Windows 所需的多尺寸.ico文件16x16, 32x32, 48x48, 256x256。它调用imagemagick需系统预装执行convert -resize 16x16 assets/icon.png assets/icon-16.ico convert -resize 256x256 assets/icon.png assets/icon-256.ico # 合并为单个 ico 文件 convert assets/icon-*.ico dist/my-app.ico若未安装 ImageMagickt3code 会提示并提供一键安装命令brew install imagemagickmacOS或choco install imagemagickWindows。UAC 清单注入Windows 10 要求桌面应用声明 UAC 权限。t3code 自动生成build/win/manifest.xml?xml version1.0 encodingUTF-8 standaloneyes? assembly xmlnsurn:schemas-microsoft-com:asm.v1 manifestVersion1.0 trustInfo xmlnsurn:schemas-microsoft-com:asm.v3 security requestedPrivileges requestedExecutionLevel levelasInvoker uiAccessfalse/ /requestedPrivileges /security /trustInfo /assembly并在打包时通过rcedit工具注入到.exe文件中npx rcedit dist/win-unpacked/my-app.exe \ --set-icon dist/my-app.ico \ --set-version-string ProductName My App \ --set-version-string FileDescription My Desktop App \ --set-version-string LegalCopyright © 2024 My Company \ --set-version-string InternalName my-app \ --set-version-string OriginalFilename my-app.exe \ --set-version-string CompanyName My Company \ --set-version-string ProductName My App \ --set-version-string ProductVersion 1.2.0 \ --set-version-string FileVersion 1.2.0 \ --set-version-string Language 1033 \ --set-version-string Comments Built with t3code \ --set-version-string PrivateBuild t3code-build \ --set-version-string SpecialBuild t3code-build \ --set-file-version 1.2.0 \ --set-product-version 1.2.0 \ --set-icon dist/my-app.ico \ --set-manifest build/win/manifest.xml签名自动化企业级必备若配置了signing: { certPath: ./cert.pfx, password: xxx }t3code 调用signtool.exesigntool sign /f ./cert.pfx /p xxx /t http://timestamp.digicert.com /d My App /du https://mycompany.com dist/win-unpacked/my-app.exe并验证签名有效性signtool verify /pa dist/win-unpacked/my-app.exe。失败则中断构建输出详细错误码如0x80070005表示权限不足。3.3t3code debug:ipc让 IPC 调用链路“看得见、摸得着”IPC 是 Electron 应用的神经中枢但调试极其困难。t3code 的debug:ipc命令提供三重可视化第一重实时调用列表启动t3code debug:ipc后它开启一个 Express 服务端口 8080页面显示表格时间渲染进程 ID方法名参数长度耗时(ms)状态14:22:03.1231app:getUserInfo042success14:22:03.4561file:read1187error数据来自主进程注入的IPCInspector// electron.main.js const { ipcMain } require(electron); const IPCInspector require(t3code-ipc-inspector); // t3code 内置模块 IPCInspector.start(ipcMain); // 自动监听所有 handle 调用第二重调用拓扑图点击某行弹出调用链路图renderer (pid:1)→ipcRenderer.invoke(app:getUserInfo)↓main (pid:1234)→ipcMain.handle(app:getUserInfo, async () { ... })↓native addon (node-gyp)→getUserInfoNative()↓renderer←return { name: John }图谱数据由IPCInspector在每次 IPC 调用时通过performance.now()记录时间戳并用process.pid标识进程最终通过 WebSocket 推送。第三重参数深度查看支持展开参数对象显示 JSON 格式对 Buffer 类型自动转 base64对 Error 对象显示 stack trace。特别处理循环引用JSON.stringify(obj, (key, val) val typeof val object val.constructor Object ? Object.keys(val).reduce((a, k) ({...a, [k]: val[k]}), {}) : val)。注意debug:ipc仅在NODE_ENVdevelopment下启用。生产环境自动禁用避免性能损耗。3.4t3code build:android用 Capacitor 打包 APK 的最小可行路径很多团队想用 Electron 写 Web App再打包成 Android APK却卡在 Capacitor 配置上。t3code 的build:android命令抹平了所有坑Step 1Capacitor 初始化检查t3code 检查项目根目录是否存在capacitor.config.ts。若不存在自动生成import type { CapacitorConfig } from capacitor/cli; const config: CapacitorConfig { appId: com.mycompany.myapp, appName: My App, webDir: dist, bundledWebRuntime: false, android: { path: android, studioVersion: 2023.1.1 } }; export default config;并执行npx cap init。Step 2Android Studio 环境预检调用sdkmanager --list_installed检查是否安装platform-tools、platforms;android-33、build-tools;33.0.2。缺失则提示提示缺少 Android SDK platform-tools —— 请运行sdkmanager platform-tools或下载 Android Studio 完整版。Step 3WebView 替换为 Electron WebViewCapacitor 默认用 Android System WebView但 Electron 应用需用 Chromium WebView。t3code 修改android/app/src/main/res/xml/config.xmlfeature nameWebView param nameandroid-package valueorg.chromium.net.WebView / /feature并添加android/app/src/main/java/MainActivity.java中的初始化import org.chromium.net.WebView; // ... Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WebView.setWebContentsDebuggingEnabled(true); }Step 4签名与打包生成keystore.jks若未提供执行keytool -genkey -v -keystore android/app/release.keystore \ -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 \ -storepass password -keypass password npx cap build android --configuration release最终输出android/app/build/outputs/apk/release/app-release.apk。整个过程无需打开 Android Studio命令行全程可控。我们曾用此流程为医疗客户打包 12 个不同科室的 APK每个仅需 4 分钟。4. 实战避坑指南那些官网不会写的血泪教训t3code 的价值不仅在于功能更在于它沉淀了我们踩过的所有坑。以下是真实项目中总结的 7 条铁律每一条都附带错误现象、根因分析和修复代码。4.1 错误t3code dev启动后Vite 页面白屏控制台报Failed to load resource: net::ERR_CONNECTION_REFUSED现象Electron 窗口打开但空白DevTools Console 显示GET http://localhost:5173/ net::ERR_CONNECTION_REFUSED。根因Vite 开发服务器启动慢于 Electron 加载index.html。Electron 的mainWindow.loadFile(index.html)会立即请求http://localhost:5173此时 Vite 还未 ready。修复在electron.main.js中改用mainWindow.loadURL并等待 Vite 就绪// t3code 自动注入此逻辑 async function waitForViteReady() { const maxRetries 30; // 等待 30 秒 for (let i 0; i maxRetries; i) { try { await fetch(http://localhost:${vitePort}/vite/client); return true; } catch (e) { await new Promise(r setTimeout(r, 1000)); } } throw new Error(Vite server not ready after ${maxRetries} seconds); } app.whenReady().then(async () { await waitForViteReady(); // 关键 mainWindow new BrowserWindow({ /* config */ }); mainWindow.loadURL(http://localhost:${vitePort}); });4.2 错误t3code build:win打包后双击.exe报错Error: Cannot find module electron现象开发环境正常打包后运行崩溃错误指向require(electron)。根因electron被列为devDependencies而electron-builder默认不打包devDependencies。但 Electron 主进程代码electron.main.js需要require(electron)它必须是dependencies。修复t3code 在build:win前自动检查const pkg require(./package.json); if (!pkg.dependencies.electron pkg.devDependencies.electron) { console.warn(Warning: electron is in devDependencies. Moving to dependencies...); // 自动执行 npm install electron --save execSync(npm install electron --save, { stdio: ignore }); }4.3 错误t3code debug:ipc页面空白WebSocket 连接失败现象打开http://localhost:8080页面无内容浏览器控制台报WebSocket connection to ws://localhost:8080 failed。根因Electron 主进程的ipcMain监听器在app.whenReady()之前注册但IPCInspector需要ipcMain实例。若t3code debug:ipc服务先启动而 Electron 进程未初始化ipcMain则注入失败。修复t3code 的debug:ipc服务增加重连机制// debug-ipc-server.js const wss new WebSocket.Server({ port: 8080 }); wss.on(connection, (ws) { // 每 2 秒 ping 一次 Electron 进程 const pingInterval setInterval(() { if (ipcInspector ipcInspector.isReady()) { clearInterval(pingInterval); ws.send(JSON.stringify({ type: ready })); } }, 2000); });4.4 错误t3code build:android生成的 APK 安装后闪退现象APK 安装成功但启动即崩溃Logcat 显示java.lang.RuntimeException: Unable to instantiate activity ComponentInfo根因Capacitor 的MainActivity类名与AndroidManifest.xml中声明不一致。常见于手动修改过android/app/src/main/AndroidManifest.xml。修复t3code 在构建前强制校验const manifest fs.readFileSync(android/app/src/main/AndroidManifest.xml, utf8); const activityMatch manifest.match(/activity[^]*?android:name([^])/); if (!activityMatch || !activityMatch[1].includes(MainActivity)) { throw new Error(AndroidManifest.xml activity name must be MainActivity); }4.5 错误t3code dev中渲染进程ipcRenderer.invoke调用超时但主进程ipcMain.handle已执行完毕现象主进程日志显示handle app:getUserInfo done但渲染进程报Timeout of 30000ms exceeded。根因Electron 的ipcRenderer.invoke默认超时 30 秒但主进程ipcMain.handle中的异步操作如数据库查询可能被 Node.js 事件循环阻塞导致响应延迟。修复t3code 提供--ipc-timeout参数并在主进程注入超时监控// t3code 自动在 ipcMain.handle 包裹 ipcMain.handle(app:getUserInfo, async (event, ...args) { const startTime Date.now(); try { const result await actualHandler(event, ...args); const duration Date.now() - startTime; if (duration 10000) { // 超过 10 秒告警 console.warn(IPC method app:getUserInfo took ${duration}ms); } return result; } catch (e) { console.error(IPC handler error:, e); throw e; } });4.6 错误t3code build:win签名后Windows SmartScreen 报“未知发布者”现象安装.exe时Windows Defender SmartScreen 弹窗阻止运行。根因代码签名证书未包含 Extended Validation (EV) 证书或证书颁发机构CA未被 Microsoft 信任列表收录。修复t3code 不解决证书问题但提供检测和绕过指南# 检测签名有效性 signtool verify /pa my-app.exe # 检查证书链 certutil -verify my-app.exe # 若证书无效提示购买 EV 证书如 DigiCert、Sectigo console.log(SmartScreen warning likely. Consider purchasing EV code signing certificate.);4.7 错误t3code dev启动后热更新失效修改src/renderer文件无反应现象保存.tsx文件Vite 控制台显示page reload但 Electron 窗口内容未更新。根因Electron 的BrowserWindow默认缓存http://localhost:5173的响应。需禁用缓存。修复在electron.main.js中为webContents设置mainWindow.webContents.session.webRequest.onBeforeSendHeaders((details, callback) { details.requestHeaders[Cache-Control] no-cache; callback({ requestHeaders: details.requestHeaders }); });t3code 在dev命令中自动注入此逻辑。5. 进阶扩展t3code 如何支撑大型团队的标准化交付当 t3code 在单个项目验证有效后下一步是规模化。我们为 12 人前端团队设计了三级扩展体系5.1 团队级配置中心mycompany/t3code-config将t3code.config.js提取为独立 npm 包// mycompany/t3code-config/index.js module.exports { devPorts: { electron: 3000, vite: 5173, capacitor: 8100 }, signing: { certPath: process.env.SIGNING_CERT_PATH || ./cert.pfx, password: process.env.SIGNING_PASSWORD || default }, build: { win: { target: [nsis], arch: [x64] }, android: { keystore: ./android.keystore } } };项目中只需npm install mycompany/t3code-config并在t3code.config.js中const baseConfig require(mycompany/t3code-config); module.exports { ...baseConfig, appId: com.mycompany.project-x };这样当公司统一更换签名证书只需更新mycompany/t3code-config所有项目t3code build自动生效。5.2 CI/CD 集成GitHub Actions 中的 t3code 流水线在.github/workflows/ci.yml中name: Build Test on: [push, pull_request] jobs: build-win: runs-on: windows-latest steps: - uses: actions/checkoutv3 - name: Setup Node.js uses: actions/setup-nodev3 with: node-version: 18 - name: Install dependencies run: npm ci - name: Build Windows run: npx t3code build:win --configuration production - name: Upload artifact uses: actions/upload-artifactv3 with: name: win-app path: dist/win-unpacked/关键点npx t3code确保使用项目本地版本避免全局 CLI 版本不一致。5.3 插件生态为 t3code 开发自定义命令t3code 支持插件机制。例如为接入 Sentry开发t3code-sentry-plugin// t3code-sentry-plugin/index.js module.exports { commands: { sentry:upload: { description: Upload sourcemaps to Sentry, action: async (config) { const { execSync } require(child_process); execSync(npx sentry-cli releases files ${config.release} upload-sourcemaps dist/, { stdio: inherit }); } } } };项目中npm install t3code-sentry-plugint3code 自动加载插件命令。这套体系让 t3code 从个人工具升级为团队基础设施。上线半年我们交付了 7 个 Electron 应用平均打包时间从 22 分钟降至 6 分钟新成员上手时间从 3 天压缩到 4 小时。6. 最后一点真实体会t3code 不是终点而是你掌控开发流的起点我写这篇内容不是为了推销某个工具而是想说当你开始厌倦反复配置 webpack、反复搜索 “electron ipc timeout fix”、反复在 Stack Overflow 复制粘贴rcedit命令时你就已经准备好自己造一把 t3code 这样的刀了。它不追求通用只解决你手头这个项目的痛它不标榜优雅但每次t3code dev成功启动时那 0.3 秒的等待就是对你写代码的尊重。我们团队现在有个不成文规定任何新项目初始化第一件事不是git init而是npm init t3code一个轻量脚手架生成基础命令骨架。第二件事是打开commands/目录删掉用不到的build:linux.js留下dev.js和build:win.js——因为客户只要 Windows 版。第三件事是把t3code.config.js里signing.password改成process.env.SIGNING_PASSWORD然后加进.gitignore。工具的价值永远不在它有多炫

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑