最近整理工作笔记的时候,翻到浏览器里存着的一堆前端热搜词,从“前端面试题2026”到“前端使用worker上传大文件”,再到“AnythingLLM在GitHub上是前端应用”和“github主页前端地球ui怎么实现的”,跨度大得惊人,但仔细看看,这些其实恰恰是当下前端开发者最关心的几件事:怎么面试、怎么做性能优化、怎么处理大文件这类硬核场景、中后台系统里那些绕不开的隐藏功能,以及AI来了之后前端到底往哪儿走。
这篇“前端知识点随记”就是我从这些热搜里挑出几个最有代表性的方向,结合自己平时写代码的实际经验,把它们串成一份可以反复翻看的笔记。不追求面面俱到,只挑那些真正值得咀嚼、能直接用到项目里的知识点展开聊。内容适合正在准备面试的前端、写中后台写到怀疑人生的同学,以及想搞明白AI时代前端该怎么进化的人。
1. 面试八股文的学与用:先弄明白这些题到底在考什么
“前端面试八股文汇总”能一直挂在热搜上,说明大家在面试这件事上确实焦虑。我刚入行那会儿也背过八股,背完之后进公司写代码,发现最大的问题不是八股没用,而是我只记住了答案,没理解答案背后的原理。后来我当面试官,面了上百个候选人,越来越确定一件事:八股文本身没有错,错在“背”而不是“懂”。
1.1 事件循环这类题,怎么从“背答案”变成“讲原理”
事件循环(Event Loop)是前端面试出现频率最高的题之一。大部分背过答案的人会说:先执行同步代码,然后执行微任务,再执行宏任务。这个回答对不对?对,但太浅了,等于没说。
真正的理解应该是:JavaScript是单线程的,为了避免阻塞,它把任务分成了同步任务和异步任务。异步任务又分微任务(Promise.then、MutationObserver等)和宏任务(setTimeout、setInterval、I/O等)。执行完一个宏任务之后,会清空当前所有的微任务,然后再取下一个宏任务,这个过程不断循环,就是事件循环。
但如果你只停在这里,还是没有完全讲透。面试官想听到的是:为什么微任务要优先于宏任务?为什么要有微任务这种东西?答案其实是因为微任务是在当前宏任务结束前、渲染之前执行的,所以它可以用来做那些必须“尽快”做的事,比如Promise回调。而宏任务之间浏览器有机会去渲染更新UI,所以setTimeout的延迟并不是精确的。
我建议准备这类题的时候,不要只背结论,而是自己画一遍完整的事件循环流程:执行栈、任务队列、微任务队列、渲染时机。能把图画出来,能把“为什么会这样设计”讲清楚,比背十遍答案都管用。
1.2 2026年面试的新风向:基础还在,但考法变了
看热搜词“2026前端面试题”出现的频率很高,和之前的面试题对比一下会发现,变化其实挺明显的:
- 不再只问“闭包是什么”,而问“闭包在实际项目里用在哪里要注意什么”
- 不再只问“怎么优化性能”,而问“你线上某个页面卡了,怎么排查定位”
- 开始问“你在项目里用过哪些AI辅助工具”“你怎么用AI生成组件代码”
- 开始问“前端怎么处理大文件上传”“怎么做权限控制”“怎么和后端配合”
这说明行业对前端的要求已经从“会写页面”变成了“能解决实际问题”。所以如果你还在背那种“闭包是什么”的标准答案,建议换种方式:把八股题当成一个小项目来做,用代码验证,用实践检验。
比如闭包,不要只背“函数返回函数”,而是真去写一个用闭包实现私有变量的例子,再想想闭包的内存泄漏问题,再想想闭包在循环里的坑。这样一道题就能覆盖三个知识点,面试的时候也比背答案强太多了。
1.3 八股文整理的正确姿势:按主题建索引,而不是按题库背
我自己整理前端知识点的习惯是:不按题库存,按主题建索引。比如“事件循环”下面挂的不是一道题,而是一堆相关的问题:微任务和宏任务的区别、setTimeout为什么不准时、requestAnimationFrame和setTimeout的区别是什么、Node.js的事件循环和浏览器的有什么区别。
这样整理的好处是,面试的时候不管问题怎么变,我都能从主题出发去思考,而不是机械地匹配题库。我甚至会在每个主题下写一段“我实际遇到过的情况”,比如某次线上页面卡顿就是因为setTimeout里做了大量计算,改成requestAnimationFrame之后流畅多了。这种真实案例在面试里说出来,比任何标准答案都有说服力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 性能优化的真正抓手:INP、长任务和渲染瓶颈一个都不能漏
前端性能优化能一直挂在热搜上,说明这是所有前端的共同痛点。特别是2024年之后,Google把INP(Interaction to Next Paint,交互到下一次绘制的延迟)正式列为Core Web Vitals的核心指标,替代了原来的FID(First Input Delay)。这个变化不是小事,意味着对交互响应速度的衡量方式完全变了。
2.1 INP和FID的本质区别:别只盯着首次交互
FID只统计用户第一次交互到页面响应的延迟,而且这个指标的数据往往偏小,因为用户第一次交互通常是点个链接或者滚动页面,浏览器没太多事要做。INP就不一样了,它统计的是整个页面生命周期内所有交互的延迟,取最差的那个近似值(p75,75分位)。也就是说,只要有一次点击卡了500ms,INP就会很难看。
这就带来一个实际的结论:你不仅要把首次加载和首次交互做好,还要保证整个使用过程中的每一次交互都足够流畅。这直接导致性能优化的重心从“加载性能”转向了“运行性能”,尤其是长任务的拆分。
2.2 长任务拆分:为什么一个100ms的任务会让页面“卡一下”
浏览器的主线程要在多个任务之间切换,还要负责渲染。如果一个任务执行时间太长,比如超过50ms,用户就会感觉页面卡顿。INP优化最核心的手段之一,就是把超过50ms的长任务拆成多个小任务,让浏览器有机会在任务之间插入渲染。
实操中最常见的做法是:把一个大循环改成用Generator函数或者async/await分批次执行,每一批只处理一部分数据,然后让出主线程。下面是一个简化的例子:
javascript复制async function processInChunks(items, chunkSize, processItem) {
for (let i = 0; i < items.length; i += chunkSize) {
const chunk = items.slice(i, i + chunkSize);
chunk.forEach(processItem);
// 主动让出主线程,给渲染留机会
await new Promise((resolve) => setTimeout(resolve, 0));
}
}
这个写法在数据量大的列表渲染、复杂计算场景里非常有用。我遇到过一个大表格组件,把1000行数据全部渲染出来要花300ms,用户体验就是点击按钮之后页面白了一瞬间。改成分批渲染之后,虽然没有一次性渲染那么快,但用户感受到的是“表格一点点出来了”,体验反而好得多。
2.3 从资源加载到渲染链路:一个表格式的排查清单
如果你不知道从哪儿开始做性能优化,可以按这张表从上到下排查一遍:
| 检查项 | 常见问题 | 优化手段 |
|---|---|---|
| 资源体积 | 没做代码分割、图片没压缩 | 路由级懒加载、WebP格式、gzip/brotli压缩 |
| HTTP请求数 | 请求没合并、没做缓存 | HTTP缓存策略、CDN、合理使用preload/prefetch |
| JS执行时间 | 长任务没拆分、大数据量计算 | 分片处理、Web Worker、避免不必要的重渲染 |
| DOM操作 | 频繁操作DOM导致重排重绘 | 批量更新、DocumentFragment、CSS contain |
| 交互响应 | 输入事件里做了重计算 | 防抖节流、输入框用requestAnimationFrame同步 |
这里特别多说一句CSS contain这个属性。它其实是个被很多人忽略的利器,作用是告诉浏览器某个元素的布局和绘制是独立的,不会影响外部。比如一个列表里的每个卡片都可以加上contain: layout style,这样浏览器更新卡片内部时就不用重新计算整个页面的布局。性能瓶颈在DOM渲染上的项目,强烈建议试试。
3. 大文件上传的Worker方案:从分片到并行,把上传时间砍半
“前端使用worker上传大文件”能上热搜,说明这不是个冷门需求。我自己在做后台系统的时候就遇到过:用户要上传1GB的压缩包,直接input[type=file]丢给后端,结果浏览器卡死、后端超时,两头都难受。后来老老实实做了分片上传,配合Web Worker计算文件指纹,才算是把这个问题彻底解决。
3.1 为什么算个文件哈希就必须用Worker
大文件上传通常要做两件事:一是把文件切成多个分片,二是算文件的哈希值用来做秒传和断点续传。第二件事特别容易被人忽略。算一个1GB文件的SHA-256或者MD5,在浏览器主线程直接跑,CPU会持续占用几百毫秒甚至几秒,页面直接“冻结”,用户在文件上传的这段时间里什么都干不了。
Web Worker的价值就在这里:它是浏览器提供的独立线程,可以把计算密集型的任务放进去执行,不占用主线程。虽然Worker不能直接访问DOM,但文件对象(Blob/ArrayBuffer)是可以传进去处理的。所以正确流程是:主线程读文件,把分片数据传给Worker,Worker计算哈希,再把结果传回主线程。
3.2 分片上传的完整流程和并发控制
分片上传的核心思路很简单:把大文件切成N个小片,一片一片传,传到一半断网了,下次只传没传完的片就行。实操步骤大致如下:
- 计算分片:
File.slice(start, end)按固定大小切片,比如每片2MB。 - 计算哈希:用Worker对整个文件做哈希,用于秒传判断。
- 询问后端:先请求一个接口,告诉后端文件名、大小、哈希,后端返回哪些片已经传过了。
- 上传分片:把没传过的分片并发传上去。
- 合并通知:所有分片传完后,调合并接口,后端把所有分片拼成完整文件。
这里面最值得说一下的是并发控制。如果一次性把100个分片全部发出去,浏览器会建立大量HTTP连接,反而拖慢速度。更稳妥的做法是用一个并发池,同时只发5到6个请求,每完成一个就从队列里取下一个。我常用的实现是一个简单的for循环配合Promise.all:
javascript复制async function uploadChunks(chunks, concurrency = 5) {
const queue = [...chunks];
const workers = new Array(concurrency).fill(null).map(async () => {
while (queue.length > 0) {
const chunk = queue.shift();
await uploadOneChunk(chunk); // 实际的上传请求
}
});
await Promise.all(workers);
}
实测下来,并发数控制在5到6个,速度和稳定性都比较理想。并发太多,后端和网络的压力大,反而容易触发超时重传。
3.3 秒传和断点续传背后的逻辑
这两个功能听起来高大上,其实实现原理并不复杂:
- 秒传:上传前用整个文件的哈希值去后端查询,如果后端已经有这个文件,直接返回“上传成功”,跳过所有分片。
- 断点续传:上传前用文件哈希查一下哪些分片已经存在,然后只传缺失的部分。
这里有个细节要提醒大家:文件哈希的计算要用全文件内容,而不是只算文件名和大小。因为同名不同内容的文件太多了,只靠文件名判断会导致数据错误。我用的是SparkMD5库,在Worker里计算大文件的增量哈希,不会一次性把整个文件读进内存。
3.4 上传进度和错误重试的经验之谈
分片上传还有一个容易被忽略的点:进度条怎么算。如果所有分片平均分布,进度条可以简单地用“已完成分片数/总分片数”来算。但实际网络状况不平均,更细致的做法是每片记录已发送的字节数,累加得到整体进度。
错误重试也要做好。分片上传中的网络抖动很常见,我会对每个分片设置一个3次重试机制,3次都失败才把该分片标记为失败,并在所有分片传完后统一重试失败项。这样即使中途断网,只要重连恢复,上传任务也能继续走完,用户体验好很多。
4. 中后台系统的隐藏知识点:字典管理、BPMN定制和OnlyOffice集成
中后台是前端岗位里需求量最大的场景,没有之一。热搜词里“hzero前端开发”“前端系统管理下的字典管理 一般有啥用”“bpmn前端 自定义流程”“前端怎么使用onlyoffice”全是从中后台场景里冒出来的。说实话,这些东西在学校和大多数教程里都学不到,只有真做过中后台项目才懂它们的价值。
4.1 字典管理到底是干嘛的,怎么配合前端做
“字典管理一般有啥用”这个问题会出现在热搜里,说明很多人第一次接触中后台时都被这个概念搞懵过。简单说,字典就是系统里各种“枚举值”的统称。比如用户的性别有“男”“女”“未知”,订单的状态有“待支付”“已支付”“已发货”“已完成”,这些值在数据库里存的往往是0、1、2这样的数字,但页面上要显示成对应的中文文本。
如果直接在代码里写死映射关系,后端改一个枚举值,前端就得跟着改一次代码重新发版,特别痛苦。字典管理的价值就是把这些枚举集中管理起来,后端维护一张字典表,前端通过接口动态加载,页面上的下拉选项、标签文本都从字典里取。这样后端更新字典值时,前端不用动代码,刷新页面就能看到新内容。
前端在这块要做的,一方面是封装一个统一的字典获取工具,另一方面是把下拉选择、标签展示封装成通用组件,比如DictSelect、DictTag,传入字典类型就能自动渲染。我在项目里还会给字典数据加一层本地缓存,避免每次进页面都重复请求。
4.2 BPMN自定义流程:前端为什么绕不开流程设计器
“bpmn前端 自定义流程”是个非常中后台的痛点。很多审批系统、OA系统都有流程设计功能,需要前端在页面上拖拽出流程图,设置审批节点、条件分支。这一块的核心库就是bpmn-js,它是BPMN 2.0流程定义在浏览器端的解析和渲染引擎。
bpmn-js自带了一个流程设计器的基础能力,但真实项目几乎不可能开箱即用,都得做很多定制。我举几个常见的定制点:
- 自定义节点类型:比如在流程里加一个“会签节点”,需要自定义渲染样式和属性面板。
- 属性面板定制:点击不同节点时,右侧弹出的配置面板要显示不同的字段,比如“审批人”是选用户还是选角色。
- 流程校验:保存流程前要校验节点是否完整、连线是否符合规范。
- 流程预览:非编辑模式下只读展示流程图,禁止拖拽改动。
做这些定制的前提是先理解BPMN的XML结构。BPMN流程图本质上是一段XML,bpmn-js就是把这个XML解析成图形元素。所以你能不能在bpmn-js里做定制,很大程度上取决于你对BPMN规范的理解程度——比如bpmn:UserTask代表人工任务,bpmn:SequenceFlow代表连线。这块没有捷径,老老实实看规范文档是唯一的办法。
4.3 OnlyOffice集成:从嵌入编辑器到权限控制
“前端怎么使用onlyoffice”的需求也很典型,很多系统需要在网页里直接预览和编辑Word、Excel、PPT,而OnlyOffice是一套可以自部署的在线文档解决方案,支持文档协同编辑,而且社区版免费,所以国内外用得非常多。
前端集成OnlyOffice其实不复杂,核心就是通过一个iframe嵌入OnlyOffice Document Server的地址,并带上配置参数。基本的集成代码大致是这样:
javascript复制const config = {
document: {
fileType: 'docx',
key: `document_${fileId}_${version}`, // 唯一标识,文档内容变化时要更新
title: 'test.docx',
url: 'https://your-server.com/download/test.docx',
},
documentType: 'word',
editorConfig: {
mode: 'edit', // edit 或 view
callbackUrl: 'https://your-server.com/callback', // 保存回调
user: { id: 'user1', name: '张三' },
},
};
const iframe = document.createElement('iframe');
iframe.src = `${ONLYOFFICE_API_URL}?${encodeURIComponent(JSON.stringify(config))}`;
document.body.appendChild(iframe);
注意这里的key字段特别重要,它是对文档唯一性的标识。文档内容更新了,key也要变,否则OnlyOffice会从缓存里读旧文档。callbackUrl是后端用来接收编辑保存结果的回调地址,前端提交之后要等这个回调成功才能真正保存。
权限控制也是集成中容易忽略的。如果你的系统里有“只读用户”和“可编辑用户”,一定要在editorConfig.mode里区分,不要只靠前端隐藏按钮来实现——因为OnlyOffice是iframe嵌入的,用户完全可以直接改URL参数拿掉只读限制。
4.4 前后端协作的隐藏话题:Gin集成Vue的dist,和token值怎么算
热搜词里还有一条很实际:“golang gin 集成 vue前端dist”。很多后端是Go语言写的项目,前端打包完之后要由Go后端一并托管,不想再单独搞一个Nginx。Gin里托管Vue的静态文件其实很简单,几乎是一行代码的事:
go复制r.StaticFS("/", http.Dir("./dist"))
r.NoRoute(func(c *gin.Context) {
c.File("./dist/index.html")
})
关键是那个NoRoute处理。Vue Router用了history模式之后,前端路由跳转是纯前端行为,但用户直接刷新/page/123这个地址时,后端收到的请求路径是/page/123,静态文件里没有这个路径,必须把这个路径重定向到index.html,由前端Router接管。这个细节不处理好,线上就会出现“部署完点刷新页面变404”的经典问题。
至于“java 后端给前端的token值是如何计算的”,这其实是在问JWT的结构。一个JWT由三部分组成:Header(算法类型)、Payload(用户信息)、Signature(签名)。Signature是后端用密钥把Header和Payload加盐生成的,前端拿到JWT之后放进Authorization头传给后端,后端验签通过就认为是合法用户。
JWT的前端存储有几种选择,核心权衡是XSS和CSRF的风险。存localStorage的缺点是JS可以访问,站点被注入脚本时就可能被偷走;存httpOnly Cookie则能防XSS,但要处理CSRF防护。没有绝对安全的方案,只有根据项目情况做的权衡。我在项目中更倾向把token放在内存或localStorage,配合https和较短的有效期,同时对主要接口做严格的内容安全策略(CSP)来减少XSS风险。
5. AI时代前端的进化路线:从工具人到会用工具的工程师
热搜词里那几条“前端ai工具”“codebuddy常用的前端skill”“AI出来后 前端工程师是不是没了”放在一起看,反映出大家心里最深的焦虑:AI会不会让前端失业。我的判断是:会淘汰一部分只会“切图写页面”的前端,但会让真正理解业务、懂架构的前端效率翻倍,甚至向全栈进化。
5.1 AI辅助编程工具的正确打开方式:Skill才是关键
现在聊AI辅助编程,已经不只是“用ChatGPT问问题”了,而是有一整套工具链,像CodeBuddy这类工具都开始支持自定义Skill。所谓Skill,就是把一组提示词、规则、工作流打包成一个特定的技能,让AI在特定场景下按固定方式工作。
前端比较常用的Skill类型包括:代码审查Skill,只检查代码里的性能问题和安全隐患;组件生成Skill,按项目的目录结构和样式规范生成符合要求的组件;重构Skill,把一段耦合严重的代码按指定模式拆开。
我自己的经验是,这些Skill要用好,关键在于把项目的规则告诉AI。比如我们项目里统一使用Vue3组合式API,组件文件命名是xxx-component.vue,样式是scoped,那这个Skill就会按这些规则生成代码,出来的东西基本能直接用。如果没有这些约束,AI生成的代码往往是另一种风格的,还得自己改,效率反而低。
5.2 前端AI应用开发:AnythingLLM这类项目为什么值得拆解
“anything-llm 在github上是一个前端应用”这条热搜很有意思。AnythingLLM是一个开源的本地知识库问答应用,支持多种大模型后端,把文档、网页等内容向量化之后,通过检索增强生成(RAG)实现自然语言问答。它本身是个很典型的AI应用前端范本。
拆解一下这个项目,你会发现一个AI应用的前端远远不只是聊天界面那么简单,它涉及:文档的上传和解析、向量化进度的可视化、多会话管理、模型参数配置界面、流式响应的展示、权限管理。每一个模块都有不少前端活儿要做。
对普通前端来说,AnythingLLM最大的价值在于:它证明了一个懂RAG原理的前端完全可以独立做出一个AI应用来。你不需要自己训练模型,只要会对接API、处理流式数据、管理本地存储,就能做一个能用的知识库问答系统。这是前端转AI应用开发最现实的路径之一。
5.3 GitHub主页那个3D地球到底是怎么实现的
“github主页前端地球ui怎么实现的”其实问的是GitHub官方个人主页上那个3D贡献图地球效果。那个效果的底层技术是Three.js,是一个WebGL 3D渲染库,用它在浏览器里渲染一个地球,把贡献数据映射成球面上的点和线。
实现思路大致是:先用Three.js创建一个球体几何体,贴上一张地球纹理贴图;然后把贡献数据里的每个仓库、每个提交按经纬度换算成三维坐标;最后在对应的坐标点上生成一些粒子或者柱状体,颜色深浅代表活跃程度。换算公式很简单,经纬度转三维坐标是这样的:
javascript复制function latLngToVector3(lat, lng, radius) {
const phi = (90 - lat) * Math.PI / 180;
const theta = (lng + 180) * Math.PI / 180;
return new THREE.Vector3(
-radius * Math.sin(phi) * Math.cos(theta),
radius * Math.cos(phi),
radius * Math.sin(phi) * Math.sin(theta)
);
}
如果想自己实现类似效果,我建议从数据映射做起,先用假数据跑通,再替换成真实的GitHub贡献数据。难度最大的部分其实不是地球,而是3D场景里的交互优化——相机控制、鼠标悬停高亮、粒子数量控制,这些才是真正考验性能优化的地方。做的时候可以把粒子数量控制在5000以内,用BufferGeometry而不是逐个创建模型,否则页面会很卡。
5.4 前端转全栈:AI拉平了后端门槛,窗口期到了
热搜里“前端转全栈”也频繁出现。过去前端想转全栈,最大的门槛是后端知识体系太庞杂:数据库设计、鉴权、部署、服务器运维,每一块都要花很长时间。但AI辅助编程工具的出现,其实把这个门槛拉低了不少。
我的感受是,AI工具最擅长的事情恰好就是后端的“模式化工作”:写CRUD接口、建表、配置鉴权中间件、写部署脚本。这些事情逻辑固定、有大量现成模式,AI做得又快又好。前端本身有很好的逻辑思维能力,把后端当成“另一个调用方”来理解,加上AI辅助,是完全可以上手的。
当然,关键不在于会用AI,而在于怎么判断AI写出来的后端代码是否正确、安全。比如AI生成的SQL查询有没有注入风险,AI写的鉴权逻辑有没有越权漏洞。这些判断能力,还是需要你理解后端的基本原理。所以我给想转全栈的前端朋友的建议是:让AI帮你写代码,但你一定要明白每一行代码在做什么,尤其是安全相关的部分。
5.5 前端AI应用的实用场景:天气预报数据接入这类小需求
除了转全栈,还有一种更轻量的进化方向:把AI能力融入日常前端项目。比如热搜里“vue前端怎么获取天气预报数据”看起来很简单,但背后有个通用思路,现在很多天气预报API都已经支持自然语言交互了,前端可以做一个小插件,用户输入“北京明天天气”,前端直接调AI模型理解意图,再转成API请求。
这类需求本质上是一个“意图识别 + 数据获取 + 结果渲染”的链路。前端的角色不再只是写几个接口、画几个页面,而是要设计一套从用户输入到AI理解到数据返回的完整交互流程。对前端来说,这个方向的上手成本比转全栈更低,也更容易在现有项目里落地。
6. 最后再分享两个我自己踩过的坑
说了这么多,最后分享两个我实际踩过的坑,算是给这篇随记收个尾。
第一个是分片上传时的并发数问题。刚开始做的时候我图快,并发数直接拉到了10,结果后端扛不住,一堆请求超时,重试逻辑又没写好,最后整个上传任务卡死在重试循环里。后来改成并发数5,加上单片重试3次的机制,问题才彻底解决。优化这种事,不是越大越好,找到系统的承受边界才叫优化。
第二个是bpmn.js的定制坑。刚开始定制属性面板时,我直接在默认的PropertiesPanel上改代码,结果和bpmn-js版本一更新,所有自定义配置全部失效。后来我把自定义面板完全独立出来,通过监听element.changed事件来同步数据,再也不受库版本升级的影响了。这给我一个很深的教训:做中后台定制时,尽量保持第三方库和自研代码的解耦,不要扒着库的内部结构写业务代码。
前端这个领域变化快是事实,但底层的东西其实没变过:基础原理、性能优化、工程化、业务理解。把这些基础打牢,不管外面怎么变,都能站得住。希望这篇随记能对你的工作或者面试准备有点帮助。
