何为单点登录(SSO)?
单点登录(SSO)这玩意儿,很多人第一次接触是在公司内网:你开了 OA,再点文档系统,不用再输密码;再点工单系统,还是不用。 这时候你会产生一种错觉:好像“全公司共用一个账号密码”就完事了。 其实不是。SSO 的精髓不是“共用密码”,而是“共用一次登录的结果”,也就是:我在一个可信的地方证明过“我是谁”,其他系统就别再折腾我了。 先一句话:什么是单点登录?单点登录(Single Sign-On, SSO):用户在一个统一的认证中心登录一次之后,就能访问多个相互信任的系统/应用,而不需要在每个系统里重复登录。 它解决的主要是两件事: 用户少输几次账号密码(体验) 公司少养几套“用户体系 + 权限体系 + 登录逻辑”(治理) 先认清角色:谁负责“认人”,谁负责“用人”?SSO 场景里最常见有两个角色: IdP(Identity Provider,身份提供方):负责认证,也就是“我来确认你是谁”。常见是统一登录中心。 SP(Service Provider,服务提供方):具体业务系统,比如 OA、工单、文档、财务系统等。 你可以把它理解成: IdP =...
git pull 和 git fetch 有啥区别?
我见过很多 Git 事故,开头都差不多:“我就随手 pull 了一下……” 然后分支就开始长出一堆莫名其妙的 merge commit,或者你本地改到一半突然冲突,心态当场下线。 其实 git pull 和 git fetch 的区别很简单:一个只更新“情报”,一个更新“情报 + 现场”。 先一句话结论(TL;DR) git fetch:把远端的新提交拉到本地,但不动你当前分支(不合并、不改工作区)。 git pull:等价于 git fetch + 把远端分支的更新合到你当前分支(默认 merge,也可以 rebase)。 所以我通常这样记: fetch = “我先看看远端发生了啥” pull = “我直接把远端的变化拿过来并处理掉” 先讲清楚一个重要概念:远端跟踪分支你执行 git fetch origin 以后,Git 会更新这些东西: origin/main origin/master origin/feature-xxx 注意:origin/main 这种叫 远端跟踪分支(remote-tracking branch),它只是 G...
macOS 用虚拟机装 Windows(VirtualBox)
一、虚拟机安装虚拟机选择我装 Windows 的目的很纯粹:在 macOS 上偶尔打开 IE/Edge 或者跑一跑 Windows 环境下的页面/脚本,验证兼容性。既然不是拿来当主力系统用,性能、功耗、资源占用这些就不用纠结太多,能稳定跑起来就行。 如果你也只是做测试,VirtualBox 的优势很明显:免费、足够用、还能随手打个快照。至于 Parallels / VMware 这类商业方案体验更好,但多数时候你可能用不到那份“丝滑”。附一个对比文章:macOS 下虚拟机选哪个? 市面上常用虚拟机里,VirtualBox 是长期免费的,所以我这里直接选它。 相关链接官网:https://www.virtualbox.org/ App 下载:https://download.virtualbox.org/virtualbox/6.1.32/VirtualBox-6.1.32-149290-OSX.dmg 二、Windows 系统镜像下载镜像下载网站: https://msdn.itellyou.cn/ 建议选择 Win10 系统的镜像 镜像文件一般比...
前端如何实现页面截屏?
截图这个需求看起来很简单:点个按钮,生成一张图。但真做起来你会发现它分成两类完全不同的问题: 把某个 DOM 区域“渲染成图片”(类似 html2canvas 的思路) 直接捕获屏幕/窗口/标签页的一帧(更像“录屏里截一帧”) 这篇文章按这两条路线各给一个原生实现的 demo,顺带把坑点说清楚;最后再补两个常用开源库的用法,方便你直接落地。 使用 Canvas 绘制 DOM 元素核心原理先把话说重一点:“纯原生把 DOM 画到 canvas”本质是在复刻 html2canvas。浏览器没有提供“一键把 DOM 截成图”的官方 API,所以你只能自己遍历节点、算布局、画背景、画文字、画图片……这条路能走,但边角非常多。 这里讲一个最简版本的思路:解析 DOM 树,用 Canvas 2D API 把你关心的信息画出来,最后导出图片。 遍历 DOM 树:从目标元素开始递归遍历所有子元素。 获取计算样式:利用 window.getComputedStyle 获取每个元素的最终样式(背景、字体、边框等)。 定位绘制:根据元素的 getBoundingC...
Axios 请求可以被取消吗?解析 Axios 请求取消机制
你大概率遇到过这些 UI 问题:搜索框打字太快,结果列表一会儿跳来跳去;路由切换后,上个页面的请求回来了把状态又写了一遍;或者用户连点两次提交,后端被打了两次还把前端状态搞乱。 这些问题背后的共同点就是:旧请求不该再影响当前界面。最直接的处理方式就是取消它(或者至少忽略它的结果)。下面按 Axios 的两套方案讲清楚怎么做,再给一些更贴近业务的封装写法。 技术实现方案对比1. 传统 CancelToken 方案适用版本: Axios < 0.22实现原理: Axios 自己的一套取消令牌(CancelToken),本质是通过 token 把“取消信号”传进请求链路里。 1234567891011121314// 创建令牌源const source = axios.CancelToken.source()// 发送请求axios.get('/api', { cancelToken: source.token}).catch(err => { if (axios.isCancel(err)) { c...
Cookie 能实现不同域共享吗?
这个问题在做 SSO、做多站点业务、或者“主站 + 独立活动页”时经常冒出来:A 域登录了,B 域能不能直接读到 A 的 Cookie? 结论先放前面:不同主域(不同 eTLD+1)之间,浏览器不允许你直接共享 Cookie。能做的只有“换个思路实现同样的业务目的”,比如跳转换票据、统一登录中心、或者用后端做代理。 Cookie 与同源策略同源策略是浏览器的基本安全机制,其核心要求是:只有当请求的协议、域名和端口号完全一致时,才视为同源。 对于 Cookie 来说,同源策略意味着默认情况下,Cookie 仅能在设定该 Cookie 的域名及其子域名中访问。 例如,设置 Cookie 时指定 Domain=.example.com 后,example.com 及其所有子域(如 sub1.example.com、sub2.example.com)都可以共享该 Cookie。但对于完全不同的主域,如 example.com 与 anotherdomain.com,浏览器会严格阻止 Cookie 共享。 由于同源策略的限制,直接实现不同主域之间(例如 example.com 与 ...
浅析微前端中的隔离策略
微前端这套东西,最真实的价值是“多个团队/多个技术栈能在一个壳里各自发版”。但它的副作用也很明显:大家都跑在同一个 window 里,谁动了全局变量、谁加了个不小心的样式、谁忘了清理定时器,别的应用可能就跟着倒霉。 所以隔离几乎是微前端绕不过去的一关。这篇文章想把三个问题讲清楚: 为什么很多团队不把 iframe 当成默认方案? 不用 iframe 的话,JS 隔离一般怎么做? qiankun 的沙箱、样式隔离大概是什么思路? 为什么需要 JavaScript 隔离?在微前端架构中,各个子应用通常由不同团队开发,它们可能使用不同的技术栈、框架甚至版本。当多个子应用运行在同一个全局环境中时,会产生以下问题: 全局变量污染:子应用可能会修改全局变量或挂载全局方法,导致其他子应用发生异常。 事件和定时器难清理:全局事件监听、定时器如果不卸载,切应用几次就会叠加成“幽灵回调”。 样式冲突:这不是 JS 隔离本身,但实际项目里几乎总会一起踩(全局选择器、reset、变量名撞车)。 为了避免这些问题,你得想办法把“子应用对全局的影响”控制住:要么给它一个独立运行环境(i...
如何标准化处理线上用户反馈的问题
线上用户反馈其实就是“线上报 bug”,只不过报的人可能不是研发:信息往往不全、描述也不一定准确。处理得好,团队能快速复现并修掉问题;处理得不好,就会陷入反复追问、反复转发、最后不了了之。 下面这套流程的目标很明确:每条反馈都能落到一个工单上,有人负责、有进度可查、最后能回到用户那里完成闭环。 建立统一的反馈系统多渠道入口整合第一步不是“上一个系统”,而是先把入口收拢:官网、App 内、社群、客服、邮箱……最后最好都能汇总到同一个地方(哪怕先从飞书表单/企业微信/简单工单开始)。入口分散的后果就是:反馈容易丢、重复登记、也很难统计。 自动化采集与手动补充能自动采集的字段尽量自动采集(系统版本、浏览器、页面 URL、设备信息、用户 ID/匿名 ID、时间戳),剩下的再让人工补齐。强烈建议对“必须字段”做约束,比如: 复现步骤(最重要) 期望结果 vs 实际结果 截图/录屏(能让沟通少一半) 日志/错误码(如果有的话) 每条反馈最好都有唯一编号(工单号),后面讨论就围绕这个号说话,避免“那个用户说的那个问题”这种对不上号的沟通...
package.json 里的 sideEffects 到底是干嘛的?
你第一次在 package.json 里看到 sideEffects,大概率是在某个组件库/工具库里: 1234{ "name": "some-lib", "sideEffects": false} 然后心里冒出一个很真实的问题:这玩意儿跟“副作用”到底有什么关系?我业务代码也没写 Redux 啊。 其实它就是在跟打包工具(最典型是 webpack)打招呼:“兄弟,我这里哪些模块导入时不会做额外事情,你可以放心 Tree Shaking;哪些模块导入时会偷偷改世界观,你别把它摇没了。” 先搞清楚:这里说的副作用是什么?在 sideEffects 语境里,“副作用”指的是:模块在被 import 的那一刻,就会发生一些“跟导出值无关”的行为。 最常见的副作用长这样: import 一个 CSS 文件(它不导出啥,但会影响样式) import 一个 polyfill(它会改全局对象/原型) import 一个初始化脚本(它会注册全局事件、往 window 挂东西、打点、改运行时...
如何解决页面请求接口大规模并发问题
真实项目里,“页面并发请求太多”一般不是压测才发现的,而是用户直接告诉你:打开页面慢、偶尔转圈、还会莫名其妙报错。 常见的触发方式也很朴素:一个页面初始化要拉权限、菜单、用户信息、配置、列表、筛选项、推荐位、埋点……再加上组件各自 useEffect 一起跑,瞬间就把并发拉满。 处理这类问题别只想着“后端扛一下”。更健康的做法是前后端一起把请求治理起来:前端负责减少/合并/排队/缓存,后端负责限流/排队/缓存/抗压。 前端层面优化1. 请求去重在某些情况下,页面可能会多次触发相同的请求,如用户快速点击按钮、页面轮询等。可以通过 请求去重 来避免无意义的重复请求。 实现方式 使用 Map 或 Set 记录正在进行的请求,并在请求完成后移除。 12345678910111213const pendingRequests = new Map<string, Promise<Response>>();async function fetchData(url: string, options: Reques...
