Skip to main content

109 posts tagged with "全栈开发"

View All Tags
· 7 min read

CorepackpackageManager 字段真正生效。

  1. enable:Node bin 下生成 pnpm/yarn shim
  2. prepare pnpm@x.y.z:下载指定版本到本地缓存
  3. use pnpm@x.y.z:写 package.json + 触发 prepare
  4. 核心目的:消灭全局安装,团队/CI 锁版本
  5. 权限来源:enable 要在 Node bin 写 shim
  6. 需要 sudo:apt/brew 装 Node,shim 在 /usr/local/bin
  7. 不需要 sudo:nvm/fnm 装 Node,shim 在用户目录
  8. 免 sudo 解法:--install-directory $HOME/.local/bin
· 5 min read

git restore 和 revert 都能"撤销",但操作对象和历史影响完全不同。

  1. restore:操作文件(工作区/暂存区),不产生 commit
  2. revert:操作某次 commit必须新 commit
  3. 核心差异:restore 改文件,revert 反做 diff
  4. 进阶用法restore --source=<sha> + commit,文件 = 目标版
  5. 不能用 revert 退旧版:revert 只反补丁,无法对齐到任意 commit
  6. preserve history:替代 reset --hard免 force-push
· 9 min read

Electron 目录没有官方推荐,但 三层物理隔离 + main 内按职责拆分 是经得起长期维护的姿势。

  1. 三层分离src/main(Node 全权限)、src/preload(白名单桥)、src/renderer(沙箱 UI),别混
  2. 入口最小化main/index.ts 只做生命周期组装,业务全部下沉到 windows / ipc / services
  3. IPC 按域拆:每个域(fs / dialog / store)一个 handler 文件,channel 名集中在 channels.ts 常量
  4. Service 层下沉:数据库、文件、网络都封成 service,handler 只做参数转发
  5. 窗口工厂:每种窗口一个工厂函数,统一管创建、状态恢复、生命周期
  6. 共享类型:main / preload / renderer 之间的 interface 抽到 src/shared,杜绝重复定义
· 11 min read

contextBridge 解决的不是"怎么把 API 传给页面",而是"怎么让页面用 Node 能力但看不到 Node 环境"。

  1. 本质:在 isolated world 创建一道有边界的桥,preload 能跑 Node,页面只能摸到白名单 API
  2. 机制:preload 跑在 isolated world,主世界(页面)拿不到 preload 的闭包变量,只能拿到白名单出口
  3. 能力exposeInMainWorld 暴露受限 API,序列化约束守住边界(Function、Symbol、Error 不能裸传)
  4. 类型系统:preload 内 typeof api + 全局 Window['electronAPI'] 声明,编译期对齐
  5. 反模式:暴露整个 ipcRenderer、暴露 process、关掉 contextIsolation
· 7 min read

Electron 渲染层的真正主角不是 BrowserWindow,是 webContents

  1. 定位:每个渲染页面背后都有一个 webContents 实例
  2. 三种获取方式:BrowserWindow.webContentswebContents.getAllWebContents()<webview> 标签
  3. 核心 API:loadURLloadFile、导航事件、executeJavaScriptopenDevTools
  4. 关键推送webContents.send 是 main 主动通知 renderer 的唯一通道
  5. 与 IPC 的关系:send 单向 main → renderer,invoke 反向,组合用才能双向
  6. 踩坑:webContents 销毁后再 send 直接抛错
  7. 与视图的关系:webContents 是内容,BrowserWindow / webContentsView 是宿主
· 6 min read

Git submodule 是 Git 原生的多仓库嵌套机制,父仓库只记 commit hash,不存文件内容。

  1. 是什么:主仓库子目录里嵌入独立 Git 仓库,各自有 commit 历史
  2. 三个核心命令submodule add / init + update / update --remote
  3. 典型场景:第三方库源码嵌入、独立发布周期的子项目
  4. 致命坑 1新 clone 是空目录,必须 init + update 才有内容
  5. 致命坑 2:子模块默认 detached HEAD,commit 容易推不上去
  6. 致命坑 3:主仓库切分支后忘了 update --remote,代码对不上
  7. 替代方案:monorepo 处理强耦合,subtree 处理简单嵌入
· 9 min read

Electron 的渲染层不是"一个浏览器",是 Chromium + 多层抽象。

  1. Chromium 是底座:每个 Electron 版本绑定一个 Chromium 稳定版
  2. webContents 是核心抽象:每个渲染页面背后都有一个 webContents 实例
  3. <webview> 标签:在 renderer 里嵌入另一个 webContents
  4. webContentsView 是新版抽象:替代已废弃的 BrowserView
  5. webPreferences 是渲染配置:preload / contextIsolation / sandbox 等开关
  6. 系统 WebView 完全不同:WKWebView / WebView2 是 OS 提供的
· 6 min read

Electron 的本质是两个不同类型的进程,IPC 是它们之间唯一合法沟通的桥。

  1. 进程模型:一个 main 进程(Node.js 全权限)+ N 个 renderer 进程(Chromium 受限沙箱)
  2. IPC 核心:main 用 ipcMain 监听,renderer 用 ipcRenderer 发起,contextBridge 是安全转交
  3. 三种调用模式send/on(单向)、invoke/handle(异步返回值)、MessagePort(双向长连接)
  4. 安全铁律:默认开 contextIsolation + nodeIntegration: false,主进程做权限守门人
  5. 反模式:在 renderer 里直接 require('fs')、把 token 放 IPC payload、不校验 sender
· 5 min read

Electron 日志的个核心决策点:存哪、怎么切、怎么查。

  1. 存哪:主进程写 app.getPath('userData')/logs,渲染进程通过 IPC 转交,不要直接写文件系统
  2. 怎么切:按大小滚动 + 按天滚动,绝对不要单文件无上限写入
  3. 怎么查:开发环境直接 tail,生产环境用 electron-log 的文件路径 + 崩溃堆栈上报
  4. 级别分级error/warn/info 写文件,debug/trace 仅本地 console
  5. 崩溃捕获:JS 异常走 uncaughtExceptionnative 崩溃crashReporter,两条路不能混
  6. 敏感信息token / cookie / 密码进日志前必须 redact() 脱敏
· 6 min read

React ref 和 forwardRef 不是一个层级的概念。

ref 是 React 故意不放入 props 的"逃生通道",forwardRef 是把这个通道从 class 实例延伸到函数组件的桥梁。

  • ref 是 React 特殊处理的 prop:class 组件默认挂到实例,函数组件默认拿不到
  • forwardRef 把 ref 这个逃生通道"打通"到函数组件内部的 DOM 或组件实例
  • 经典组合:forwardRef + useImperativeHandle,自定义暴露给父组件的方法集合
  • displayName 给 DevTools 留个可读名字,避免看到一堆 "ForwardRef" / "Anonymous"
  • React 19 起 ref 已经是普通 prop,forwardRef 即将退役——但理解它仍是排查老代码的基础