前端优化方式
css3特性, [html5的特性](https://blog.csdn.net/qq_53472371/article/details/121881111)
flex, 移动端开发, 各种居中
反爬虫,加密,前端攻击,跨域
cookie session jwt相关
前端优化方式
Turbopack
WebComponentes6的新特性
BigInt
微前端
cdn
esbuild
ES6、ES7、ES8、ES9、ES10、ES11、ES12新特性
cdn技术
vite
构建工具 Vite、Webpack、Rollup对比
js的作用域
js执行环境
JS的堆栈内存分配
js垃圾回收机制
v8的垃圾回收机制
v8引擎为啥快
前端路由hash和history的区别
反爬虫
加密
前端攻击
预防攻击
cookie session jwt相关
Js 闭包实际的用途
原型链
防抖 与 节流的区别
PWA
大数据量的解决方案
get方法和post方法的区别
RPC与HTTP的区别与联系
fetch与axios的区别
js 设计模式
前端监控
报错捕获
BFF给前端提供的能力
CommonJS AMD CMD UMD ES6 Module 比较
代码工程化问题
npm yarn pnpm
monorepo
WeakMap与Map
html5 webwork的使用方式
Tree-Shaking原理
可以跨浏览器标签的通信方法
0.1+0.2 等于 0.3 吗?(数字相加结果有无限小数的原因及解决方式)
js方法构造器和不构造器的时候,返回不同的结果
JavaScript浅拷贝与深拷贝的几种方法。
Next.js
js和原生通信的一般方法
前端图片懒加载和预加载
angular
隐式类型转换和显示类型转换
------------css3
css3
border-radius
media
box-shadow
::
text-overflow
text-shadow
backgroud: linear-gradient,radial-gradient
resize
outline
box-sizing
background-clip
transform
------------html5
>一、语义标签header,footer,nav,article,aside,section,dd dt dl
二、增强型表单datalist,progress,meter,keygen,output
placehoder,required,pattern,multiple
三、视频和音频
四、Canvas绘图
五、SVG绘图
六、拖拉API
七、WebWorker,提供主线程和新线程之间数据交换的接口:postMessage、onmessage
八、WebStorage,localStorage
九、WebSocket
十、地理定位
前端优化方式
----------------文件加载方面:压缩文件大小+ 图片+加载 + 缓存
—压缩文件大小:
压缩文件,去掉无用的代码,合理的压缩算法gzip,合理的切割文件和合并文件
—图片相关的:
雪碧图,字体图标,图片延迟加载,响应式图片,降低图片质量,尽可能利用 CSS3 效果代替图片,使用 webp 格式的图片
—加载相关的:
减少http请求,减少重定向,多域名(同一个域名最多处理6个TCP链接问题),http2, dns缓存dns-prefetch,CDN缓存,懒加载,预加载,合并http请求,减少cookie, 分页加载,服务端渲染,加载优先级preload prefetch defer async,同一个域名最多处理6个TCP链接问题
—缓存相关的:
304浏览器对比缓存,强制缓存,内存缓存和磁盘缓存,接口缓存(servicework+apiCache),合理的使用localStorage和indexDB
-----------------写代码方面:
html层面:
1 语义化HTML:代码简洁清晰,利于搜索引擎,便于团队开发维护
2 提前声明字符编码,让浏览器快速确定如何渲染网页内容
3 减少HTML嵌套关系,减少DOM节点数量
4 删除多余空格,空行、注释、及无用的属性等
5 避免table布局, table会影响页面呈现的速度,只有table里的内容全部加载完才会显示。
6 使用 flexbox 而不是较早的布局模型.
7 将 CSS 放在文件头部,JavaScript 文件放在底部。
8 少用iframe。
javascript优化
1 少操作dom,缓存DOM节点查找的结果,
2 少用全局变量。
3 避免页面卡顿 ,对于一些长时间运行的 JavaScript,我们可以使用定时器进行切分,延迟执行。
4 属性冻结。
5 requestAnimationFrame代替setTimeout,requestIdleCallback。
6 h5 的webwork用来计算。
7 switch代替if else.
8 虚拟滚动 vertual-scroll-list. 虚拟滚动 vertual-scroll-list
解决加载大量列表DOM导致浏览器性能瓶颈的虚拟滚动技术
9 IntersectionObserver 代替onscroll。监控滚动图片,图片到达可视区域才去赋值src属性,才会去真正请求,延迟加载
css 优化
1 降低 CSS 选择器的复杂性, 减少伪类选择器,减少样式层数,减少使用通配符.
2 减少重绘重排
3 多用GPU等面的代码写动画,transform 和 opacity 属性更改来实现动画,利用 CSS3 效果代替图片。
4 使用外链css,可以对css进行缓存。
5 添加媒体字段,只加载有效的css 文件。 <link href=“index.css” rel=“stylesheet” media=“screen and(min-width:1024px)”
6 减少@import使用,由于import采用的串行加载。
7 css will-change和contain。
8 使用事件委托,减少事件绑定个数
9 尽量使用canvas动画、css动画
代码性能优化
HTML优化
1、避免 HTML 中书写 CSS 代码,因为这样难以维护。
2、使用 Viewport 加速页面的渲染。
3、使用语义化标签,减少 CSS 代码,增加可读性和 SEO。
4、减少标签的使用,DOM 解析是一个大量遍历的过程,减少不必要的标签,能降低遍历的次数。
5、避免 src、href 等的值为空,因为即时它们为空,浏览器也会发起 HTTP 请求。
6、减少 DNS 查询的次数CSS优化
1、优化选择器路径:使用 .c {} 而不是 .a .b .c {}。
2、选择器合并:共同的属性内容提起出来,压缩空间和资源开销。
3、精准样式:使用 padding-left: 10px 而不是 padding: 0 0 0 10px。
4、雪碧图:将小的图标合并到一张图中,这样所有的图片只需要请求一次。
5、避免通配符:.a .b * {} 这样的选择器,根据从右到左的解析顺序在解析过程中遇到通配符 * {}
6、会遍历整个 DOM,性能大大损耗。
7、少用 float:float 在渲染时计算量比较大,可以使用 flex 布局。
8、为 0 值去单位:增加兼容性。
9、压缩文件大小,减少资源下载负担。JavaScript优化
1、尽可能把 <script> 标签放在 body 之后,避免 JS 的执行卡住 DOM 的渲染,最大程度保证页面尽快地展示出来
2、尽可能合并 JS 代码:提取公共方法,进行面向对象设计等……
3、CSS 能做的事情,尽量不用 JS 来做,毕竟 JS 的解析执行比较粗暴,而 CSS 效率更高。
4、尽可能逐条操作 DOM,并预定好 CSs 样式,从而减少 reflow 或者 repaint 的次数。
5、尽可能少地创建 DOM,而是在 HTML 和 CSS 中使用 display: none 来隐藏,按需显示。
6、压缩文件大小,减少资源下载负担。
Turbopack
快700倍
Turbopack - Webpack 的继承者,Webpack 开发人员 Tobias Koppers 加入 Vercel,组建了一支世界一流的工程师团队,以创建下一代打包工具 - Turbopack
Turbopack 比 Vite 快 10 倍,比 Webpack 快 700 倍,更大的应用程序将使差异更大。
函数级缓存
页级编译
请求级编译
es6的新特性
JS语法 ES6、ES7、ES8、ES9、ES10、ES11、ES12新特性
ES6、ES7、ES8、ES9、ES10、ES11、ES12知识点总结
BigInt
BigInt
BigInt
json-bigint处理js中数据大数字问题
微前端
微前端架构
2021 非常火的 11 个微前端框架
— 样式隔离 5 种
css modules、shadow dom、css-in-js
样式优先级
手动加样式前缀,qiankun就是这样子做的
— js隔离
参考链接1
参考链接2
快照沙箱 SnapshotSandbox: 记录 window 对象,每次 unmount 都要和微应用的环境进行 Diff
LegacySandbox:在微应用修改 window.xxx 时直接记录 Diff,将其用于环境恢复。
代理沙箱 (VM虚拟机+proxy 又称 ProxySandbox):为每个微应用分配一个 fakeWindow,当微应用操作 window 时,其实是在 fakeWindow 上操作。
— 父子通信
公用emit类
微前端 - qiankun 应用间通信
—garfish
样式隔离通过优先级garfish_app_id_xxx .title,参考链接
js隔离通过代理模式 vm代理沙箱
Garfish 源码解析 —— 一个微应用是如何被挂载的
字节是如何落地微前端的
garfish完成了一次远程获取目标代码 => 解析成ast => 然后再从ast转换成dom树的过程。
将一段远程的页面/js加载到当前页面的固定位置
计算机网络 CDN技术介绍
动态CDN和静态CDN有什么区别,普通cdn和高防cdn
php 静态 动态 cdn 加速,CDN静态加速跟动态加速的区别,动态加速好还是静态加速好?…
CDN的优点:提高了用户访问网站的响应速度,为了实现跨运营商、跨地域的全网覆盖为了保障你的网站安全为了异地备援为了节约成本为了让你更专注业务本身
CDN的流程:
1.寻找CDN专用的DNS解析服务器:当用户点击网站页面上的内容URL,经过本地DNS系统解析或者本地没有缓存通过网路上的DNS解析系统指向CDN专用的DNS解析服务器。
2.寻找CDN的全局负载均衡设备IP:通过DNS解析服务器将CDN的全局负载均衡设备IP地址返回用户。
3.寻找户所属区域的区域负载均衡设备IP:通过ip找到DNS的全局负载均衡设备,CDN全局负载均衡设备根据用户IP地址,以及用户请求的内容URL,选择一台用户所属区域的区域负载均衡设备。
4.寻找户所属区域的服务器:区域负载均衡设备会为用户选择一台合适的缓存服务器提供服务。全局负载均衡设备把服务器的IP地址返回给用户
5.寻找服务器上的资源:用户向缓存服务器发起请求,缓存服务器响应用户请求,将用户所需内容传送到用户终端。
动态cdn的原理
简单来说,就是类似于用镜像服务器给访客做一个高速代理服务器。用过代理服务器的朋友应该知道,如果XX用户通过代理访问A站点的一个动态页面,那么代理服务器会先自己访问A站点的这个动态页面,然后把A站点返回的内容转发给XX用户,这样无论A站点的数据如何更新,XX用户每次访问那个动态页面,都会从代理服务器获得最新的内容。
动态cdn主要有两个好处:
1.首页加载速度更快。
2.更可靠的连接(他只负责连接边缘服务器,如果直接回源码线,线会很长,不可靠)
WebComponent
三种技术组成:
Custom Elements
Shadow DOM
templates and slots
优点:
浏览器原生支持,不需要引入额外的第三方库
语义化
复用性,移植性高
不同团队不同项目可以共用组件
缺点:
需要操作DOM
目前浏览器兼容性、性能方面不够友好
和外部css交互比较难
执行上下文(Execution Context )和范围(Scope) Variable object(变量对象) GO(全局对象) AO(激活对象)总结
前端系统化学习【JS篇】:(九)EC、STACK、VO、AO、GO浏览器底层运行机制
JS执行上下文
作用域与作用域链,GO/VO/AO/EC及作用域和执行上下文
JS作用域链详解
js的作用域
全局,函数作用域,块级作用域
const obj = {aaa: 123,bbb: function(){console.log('====>>>', this) // obj}
};
obj.bbb();const fun = function () {console.log(this); // window
}
fun();const funa = function () {return function (){console.log(this); // window}
}
funa()();const func = function () {console.log(this);
}
new func(); // func
js执行环境
---Js代码在浏览器运行时的底层机制
我们编写的JS代码机器是不认识的,是需要一个环境来编译成机器码来执行的,对于JavaScript来说,这个环境可以是
浏览器(引擎)
node(基于v8引擎来渲染js)
webview(v8引擎)
---
ECS(Execution Context Stack)执行环境栈
在首次运行js代码时创建
实质:栈内存
---
EC(Execution Context)执行上下文(词法作用域)
在JS代码执行中,为了区分全局和函数执行所处的不同的作用域(目的是为了区分每个执行上下文中代码的独立性).
分为了:global全局执行上下文,xx函数私有执行上下文。
---
VO(Variable Object)变量对象
GO 全局对象类似window, global
AO(Active Object)私有变量对象(函数运行时产生的局部变量)
VO(G)全局变量对象 类似var a = 1, 自动给window.a = 1;
深入理解JS预编译——AO对象及GO对象
JS的堆栈内存分配
堆和栈的区别
内存中的栈区处于相对较高的地址以地址的增长方向为上的话,栈地址是向下增长的。
基本类型放在栈中
指针类型放在堆栈: 是一种连续储存的数据结构,具有先进后出后进先出的性质。
通常的操作有入栈(压栈),出栈和栈顶元素。想要读取栈中的某个元素,就是将其之间的所有元素出栈才能完成。
堆: 是一种非连续的树形储存数据结构,具有队列优先,先进先出; 每个节点有一个值,整棵树是经过排序的。特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。常用来实现优先队列,存取随意。数据类型存储以及堆栈内存是什么
基本数据类型:直接存储在栈内存中,占据空间小,大小固定,属于被频繁使用的数据。指的是保存在栈内存中的简单数据段;number string 布尔引用数据类型:同时存储在栈内存与堆内存中,占据空间大,大小不固定。
引用数据:类型将指针存在栈中,将值存在堆中。 当我们把对象值赋值给另外一个变量时,复制的是对象的指针,指向同一块内存地址,意思是,变量中保存的实际上只是一个指针,这个指针指向内存堆中实际的值,数组 对象
js垃圾回收机制
垃圾回收的方式:
① 标记清除:
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了,因为环境中的变量已经无法访问到这些变量了,然后垃圾回收器相会这些带有标记的变量机器所占空间。至于怎么标记有很多种方式,比如特殊位的反转、维护一个列表等,这些并不重要。
②引用计数:
在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。为什么很少有浏览器采用,还会带来内存泄露问题呢?主要是因为这种方式没办法解决循环引用问题。
Js 内存
Js 内存管理机制 垃圾回收 内存泄露的4个点
1.全局变量
2.被遗忘的定时器或回调函数
3.闭包
4.DOM的引用
var elements = document.getElementById('button')
function doStuff() {elements.innerHTML = '听风是风';
};
// 清除引用
elements = null;
document.body.removeChild(document.getElementById('button'));
v8垃圾回收机制
一般说新生代算法和老生代算法,但是里边又夹杂着很多细小的算法
新生代算法 Scavenge算法
空间复制 新生代最常用的就是空间复制
老生代算法:标记清除算法(标记或者,清楚死了的对象) 搭配 标记整理算法(将活着的对象移动到内存的一边)
增量标记:标记所有的任务是一个非常耗时的行为,会分成很多阶段,完成一个小阶段然后先去看看别的事情,然后在继续,直到标记完成,才会去做清除,整理等事情。
空闲时间回收 (延迟清除、增量式整理)
----------v8中常用GC算法
分代回收
空间复制
标记清除
标记整理
标记增量
博客1
博客2
博客3
v8引擎为啥快
聊聊V8引擎
认识V8引擎
1. 其它的JavaScript的引擎将js转换成字节码或解释执, V8将js生成了媲美二进制的原生机器码。
>> C++先全部编译才可以执行,java先变为class的字节码,边解释边执行。V8直接转化为机器码。
2. 虽然JavaScript需要在用户使用时完成编译和执行。在V8做了近一步编译优化中,JavaScript相关代码并非一下完成编译的,而是在某些代码需要执行时,才会进行编译,这就提高了响应时间,减少了时间开销。
3. a.尽可能最大的内联,b.优化就隐藏类c.内联缓存
4. 出色的垃圾回收机制。
5. 跨平台
v8引擎的高级地方 博客1 博客2 博客3
v8的工作过程
首先通过解析器「Parser」将 JavaScript 解析成 AST。
然后解释器「lgnition」会将AST翻译成字节码。
优化编译器「TurboFan」会对标记的代码段进行优化,最终生成优化后的字节码。这样当该段代码需要再次执行时,就会直接使用优化后的机器码执行,不用再进行解释编译。从而大大提高代码运行效率。
js内存 添加链接描述
【面试】前端路由hash和history的区别
hash模式
1 hash值的变化不会导致浏览器向服务器发送请求,不会引起页面刷新
2 hash值变化会触发hashchange事件
3 url带有#符号,略丑
4 兼容性好,支持低版本和IE浏览器
5 实现前端路由无需服务端支持
---
history模式
1 pushState,replaceState
2 对比hash的hashchange方法,history的变化不会触发任何事件,我们可以通过罗列可能触发history变化的情况,对这些情况进行拦截,以此监听history的变化。
3 点击浏览器的前进/后退按钮,onpopstate可以监听到。---
两种模式的区别
1 外观:hash的url有个#符号,history没有,history外观更好看。
2 服务端支持:hash(#及后面的内容)的变化不会导致浏览器向服务器发起请求;history刷新会重新向服务器发起请求,需要在服务端做处理:如果没有匹配到资源,就返回同一个html页面。
3 兼容性:hash能兼容到IE8,history只能兼容到IE10。
4 原理:hash通过监听浏览器的onhashchange()事件,查找对应的路由规则;history利用H5新增的pushState()和replaceState()方法改变url。
5 记录:hash模式只有#后面的内容被修改才会添加新的记录栈;history通过pushState()设置的url于当前url一模一样也会被记录到历史记录栈。对于单页面的history模式而言,url的改变只能由以下情况引起:
1.点击浏览器的前进/后退按钮,onpopstate可以监听到
2.点击a标签
3.在JS代码中触发history.pushState()或history.replaceState()
反爬虫
----限制访问频率,针对IP、UA、设备指纹,帆布指纹(canvas)识别和FingerPrint
----登录限制
----Heaher 封杀
-----JavaScript脚本动态获取网站数据, 携程
-----验证码
-----ip限制
-----网站数字内容反爬猫眼字体处理,美团的图片处理,去哪里的元素background,字符集替换式汽车之家伪元素隐藏字符串分隔debugger
有关于反爬策略的整理
网络爬虫
加密
RSA加密、非对称加密 jsencrypt.js
AES加密、对称加密 CryptoJS.AES
MD5加密、SHA256加密 这样用来防止用户篡改传递大文件信息
base64之类的
国密SM1RSA 双向加密解密
如果一定要aes,那么应该使用非对称加密手段保护对称密钥,或者用DH算法即时协商,并附加数字签名校验。如果不放心CryptoJS,那可以更进一步把加解密代码做成WebAssembly。
加密方式
加密前端处理方式
使用CryptoJS AES加密,秘钥暴露在js中,这种安全怎么保障 ! 有什么解决办法吗?
rsa具体代码
RSA加密web前端用户名密码加密传输至后台并解
前端攻击
1、xss攻击防御:过滤特殊字符,HttpOnly 浏览器禁止页面的JS访问带有HttpOnly属性的Cookie。防御2: 转义:通过使用htmlspecialchars等函数,将提交内容中的字符"<"(小于)和">"(大于)转换为HTML实体。
2、CSRF攻击: 在自己的网站放入银行转账链接,用户一点击,自动访问了银行的接口并且发生了转账。
3、网络劫持攻击防御:最好是采用https进行加密,这种通过请求网络地址攻击的我们可以通过对http进行加密,来防范,这样不法分子即使或得到,也无法解密。防御2:referer防范:通过判断请求头中的referer头确定请求的来源,从而避免CSRF攻击。防御3:token防范:通过在表单请求中添加token,标识表单的合法性,来避免CSRF攻击。
4、控制台注入代码
5、钓鱼
6、DDoS攻击防御:最直接的方法增加带宽。但是攻击者用各地的电脑进行攻击,他的带宽不会耗费很多钱,但对于服务器来说,带宽非常昂贵。
云服务提供商有自己的一套完整DDoS解决方案,并且能提供丰富的带宽资源。------如果是阿里云推荐使用高防。
7、SQL注入攻击防御:md5加密
8、点击劫持。
9、文件上传漏洞防御:权限防御:文件上传的目录设置为不可执行;防御2:文件名防御:使用随机数改写文件名和文件路径。
预防攻击:
1. https post方法
2. referer
3. token
4. xss检测
5. header,IP访问限制,登录,反爬虫
6. 文件下载速度限制
7. 加密,签名
安全方式 防范攻击
前端常见的攻击方式
csrf攻击的方式
cookie session jwt相关
cookie session token jwt
项目中使用jwt
sessionid 就是特殊的cookie,需要后端存储sessionid到用户的一个映射关系,但后端要处理分布式问题。
token 把信息存储到客户端中,服务端不管理,简单 token 的组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)分为Acesss Token 和 Refresh Token.用户登录,服务器验证用户信息,返回用户一个token值。token必须要在每次请求时传递给服务端,都保存在header中.内存级别重启全部失效集群部署,多台服务器无法共享,在负载会导致用户状态不同步
JWT 直接把用户json信息放到jwt中。JWT是特殊的token。而除了用户信息,还有签名,签名只有后端可以判断是否正确。
SSO 登录。secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。JWT生成的token是无状态的,服务端不存储,即一旦生成在有效期之前一直可用,无法销毁JWT无状态=>不需要通过存储验证是否正确,本身可以验证
前端关于单点登录各种协议
面试必问的4种单点登录的实现方式,你知道几个?
token与jwt的区别
Js 闭包实际的用途
把函数内部的变量扩展出来,供函数外边使用,就形成了闭包行为。
方式可以是,1.方法内部在返回一个新的方法。2.方法返回可以操作这个内部变量的obj。
闭包
1.保护变量,只有自己这个方法可以操作变量,自己知道这个编程的存在和使用情况
var warnUser = function (msg) {var calledCount = 0;return function() {calledCount++;alert(msg + '\nYou have been warned ' + calledCount + ' times.');};
};
var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
2. 模拟面向对象编程
function counter() {var a = 0;return {inc: function() { ++a; },dec: function() { --a; },get: function() { return a; },reset: function() { a = 0; }}
}
3.解决this问题
4. 高阶函数
原型链
原型是什么?
js 每一个对象__proto__属性,都有constructor属性。
而obj.__proto__ === parentClass.prototype;
obj.constructor = parentClass.prototype.constuctor;
而parentClass的prototype又有__proto__和constructor属性,就形成了一个无限的上下链。
又因为js当时10天太仓促设计出来,偶然间又成了非常流行的语言,但是不具备class这些特征,所以圆链条无形中用来模拟类和类的继承等面向对象的语言特征。
原型链也是有终点的,方法的__proto__指向了Function类的.prototype,但是方法类的prototype.__proto__又指向了Object.prototype, 而Object.prototype.__proto__指向了null。
Function.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;
Object.__proto__ === Function.prototype;
Object.prototype.__proto__ === null;
js原型链
防抖 与 节流的区别 例子一 例子二
用一句话总结防抖和节流的区别:防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行
防抖的应用场景
1. 表单验证
2. 按钮提交事件。
3. 浏览器窗口缩放,resize事件(如窗口停止改变大小之后重新计算布局)等
4. 搜索框输入查询节流函数的作用
1. 按钮点击事件
2. 拖拽事件
3. onScoll
4. 计算鼠标移动的距离(mousemove)
大数据量的解决方案
「前端进阶」高性能渲染十万条数据(时间分片)
requestIdleCallback和requestAnimationFrame详解
requestIdleCallback笔记
什么是时间分片(Time Slicing)
时间切片(Time Slicing)
「前端进阶」高性能渲染十万条数据(时间分片)
虚拟列表
虚拟列表
时间切片,requestIdleCallback,requestAnimationFrame
documentFragment,
接口缓存,前端缓存
属性冻结
尽量用js处理计算尽量减少dom操作
get方法和post方法的区别及常用的请求方式
get方法和post方法的区别和联系
前端Get请求能在body上传参吗
get 可以在body传参,但是浏览器不允许
delete和get一样,参数也在url中?id=123
put参数通过body传输
RPC与HTTP的区别与联系
http是协议,rpc是方法,rpc的实现可能也会用到http。
http在应用层,rpc在传输层(长连接,少了三次握手,不过http2.0也可以链接复用了)。
成熟的rpc库相对http容器,更多的是封装了“服务发现”,"负载均衡",“熔断降级”一类面向服务的高级特性。
因为良好的rpc调用是面向服务的封装,针对服务的可用性和效率等都做了优化。单纯使用http调用则缺少了这些特性。
分布式系统以及在一个大系统内服务较多的情况下,服务间的调用当然是越简单越好,而rpc的调用仅涉及到传输协议+序列化协议,而不用考虑一些类似接口可读性等。可以更方便的调用。
fetch与axios的区别
fetch优点:
1.w3e标准, 原生。
2.基于promise,支持async, await
3.语法简洁,更加语义化.
fetch缺点:
1.fetch只对网络请求报错,对400,500都当做成功的请求,服务器返回400,500错误码时并不会reject,只有网络错误导致这些请求不能完成时,fetch才会被reject。
2.fetch默认不会带cookie,需要添加配置项:fetch(url,{credentials:‘include’})
3. fetch不支持abort,
4. 不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止过程继续在后台运行,造成了流量的浪费
5. fetch没有办法原生检测请求的进度,而XHR可以(进度条)。axios的优点
axios是一个基于Promise用于浏览器和nodejs的http客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,它本身具有以下特征:从浏览器中创建XMLHttpRequest
支持Promise API
客户端支持防止CSRF: 就是让我们的每个请求都带一个从 cookie 中拿到的 key,根据浏览器同源策略,假冒的网站是拿不到你 cookie 中的 key 的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。
提供了一些并发请求的接口(!方便了很多操作)
从node.js创建http请求
拦截请求和响应
转换请求和响应数据(请求A服务器可以转换到B服务器)
中断请求
自动转换JSON数据(fetch API需要手动处理返回的数据)
ajax的优点和缺点
// ajax的优点
1、无刷新更新数据(在不刷新整个页面的情况下维持与服务器通信)
2、异步与服务器通信(使用异步的方式与服务器通信,不打断用户的操作)
3、前端和后端负载均衡(将一些后端的工作交给前端,减少服务器与宽度的负担)
4、界面和应用相分离(ajax将界面和应用分离也就是数据与呈现相分离)
// ajax的缺点
1、ajax不支持浏览器back按钮
2、安全问题 Aajax暴露了与服务器交互的细节
3、对搜索引擎的支持比较弱
4、破坏了Back与History后退按钮的正常行为等浏览器机制
js 设计模式
六大原则
开闭原则(一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭)
单一职责原则
里氏替换原则(子类对父类的方法尽量不要重写和重载)
接口隔离原则(减少依赖)
最少知道原则(一个类对自己依赖的类知道的越少越好。无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。)
合成复用原则(尽量使用对象组合/聚合,而不是继承关系达到软件复用的目的)
// 单例模式
// 工厂模式
// 订阅者模式
// 观察者模式
桥接模式
前端监控三个方面的信息: 性能,错误,辅助信息(用户信息,用户行为信息,设备信息)
前端监控SDK开发分享
Performance前端性能监控利器
Node.js在携程的落地和最佳实践
前端监控体系搭建(错误、异常、白屏、性能监控、卡顿、pv等,接入日志、告警系统)
报错捕获
前端异常监控和容灾
promise报错的捕获 reject, catch,unhandledrejection
javascript报错 error | unhandledrejection | rejectionhandled | console.error
Vue 异常 errorHandle,warnHandle,renderError,errorCaptured
React 异常 getDerivedStateFromError,componentDidCatch
---收集js报错、静态资源加载错误、ajax接口加载错误,这些常规错误收集都很好理解。下面主要说明一下"业务接口错误(bussiness)":
---辅助信息(性为,用户,设备)
----性能
收集页面加载、静态资源、ajax接口等性能信息,指标有加载时间、http协议版本、响应体大小等,这是为业务整体质量提升提供数据支撑,解决慢查询问题等。
new PerformanceObserver监听器,我们可以监听所有资源(css,script,img,ajax等)加载的性能数据:加载时间,响应大小,http协议版本
const observer = new PerformanceObserver((list) => {for (const entry of list.getEntries()) {console.groupCollapsed(entry.name);console.log(entry.entryType);console.log(entry.startTime);console.log(entry.duration);console.groupEnd(entry.name);}
})
observer.observe({ entryTypes: ['longtask', 'navigation', 'resource', 'mark', 'measure', 'paint'] });// js异常上报方式
动态创建 img 标签的形式
或者ajax(考虑跨域)
前端异常监控
JS原生错误 除了try catch中捕获住的错误,我们还需要上报没有被捕获住的错误——通过error事件和unhandledrejection事件去监听。
unhandledrejection 只能捕获未显式处理的Promise异常
// 能触发 unhandledrejection ,因为未显式处理
Promise.reject('test').then()
// 能触发 unhandledrejection ,因为未显式处理
Promise.reject('test').then(console.log)
// 不能触发 unhandledrejection ,因为已处理
Promise.reject('test').then(console.log, console.log)
// 不能触发 unhandledrejection ,因为没处理,直接抛出异常
Promise.reject('test')
BFF给前端提供的能力
api
插件:node 提供了多种内置插件,包括logger,http client,rpc client等,也可以通过配置加载第三方插件.
中间件:Gatway实现方式之一,我们通过中间件实现了sso,限流,熔断等.
路由: 通过路由,给不同Appcation提供了不同形式的API,不管是H5,PC,小程序还是Open Api
渲染: 这层可以直接渲染Client端构建生成的index.html,也可以实现SSR
----BFF优势
1、可以降低沟通成本,前端边界提升,更加独立。
2、UI多端适配,展示不同数据,灵活配置同一个接口,对接口做额外处理,PC端与移动端可以自由调节字段,同时也能聚会API来减少HTTP请求。
3、提供给第三方api。
4、性能优化,高并发与负载均衡:常见的情况下,高并发的性能制约包括了大量的I/O操作时CPU利用率较低,而Node在处理I/O密集型操作时有自己的优势。
5、访问控制,可以把服务中的权限集中控制在BFF层,使下层服务更加纯粹和独立
6、应用缓存,可以增加一些缓存临时数据,更快的响应数据。
-----BFF的痛点
1、重复开发:每个设备开发一个 BFF 应用,也会面临一些重复开发的问题展示,增加开发成本
2、维护问题:需要维护各种 BFF 应用、以往前端也不需要关心并发,现在并发压力却集中到了 BFF上
3、链路复杂:流程变得繁琐、BFF引入后,要同时走前端、服务端的研发流程,多端发布、互相依赖,导致流程繁琐浪费
4、浪费资源: BFF层多了,资源占用就成了问题,会浪费资源,除非有弹性伸缩扩容
5、分布式事务(微服务的通病)
为啥node来做BFF层
模块化
ES Module使用详解
Js模块化——CommonJS AMD CMD UMD ES6 Module 比较 博客一
为什么CommonJS和ES6可以混合使用?
commonjs es6怎么解决循环引用问题
commonjs 和 esmodule方式的区别
commonjs 和 esModule模块 AMD
commonjs
1. 值的拷贝,普通类型是拷贝,而引用类型是浅拷贝(类似赋值=,并不是Object.assign)
2. require 同步引入,动态导入,引入的时候模块会执行。但是有缓存机制,第二次引入,就是拷贝过程。
3. node真正导入的是module.exports,exports和module.exports本来是一回事,一般不要手动去改。所以当我们手动更改exports = {},这样就会报错,我们只能改属性。
esModule的优势
1 es6提出的一种打包和导入的机制。
2-静态导入,可以更好的Treeshaking去掉无用代码。引用导入,模块不会执行,更不会做缓存之类的事情。
3-只读导入,不可以修改。
4- import可以当方法使用,可以做一些动态加载。
5-异步加载。
amd
1-requirejs时代了,define定义,require引用。
2-规范加载模块是异步的,并允许函数回调,不必等到所有模块都加载完成,后续操作可以正常执行。
3-依赖前置。
cmd
1-seajs时代。define定义,seajs.use()
2-依赖就近。UMD
1. UMD 是AMD 和 CommonJS的糅合。UMD 先判断是否支持 Node.js 的模块(exports)是否存在,存在则使用 Node.js 模块模式。再判断是否支持 AMD(define 是否存在),存在则使用 AMD 方式加载模块。
2.
为什么说ESModule是异步的?
这里说的esmodule,指的是<script type="module" src="a.js"></script>
你对前端模块化的理解
什么是模块化? 模块化就是为了减少系统耦合度,提高高内聚,减少资源循环依赖,增强系统框架设计。
模块的历程:
namespace
sass,less
AMD&CMD
html模版
grunt,gulp,webpack
FIS,YUI,KISSY
代码工程化问题
hushy+Lint-staged+Commitlint
npm:包管理先锋,npm 在早期采用的是嵌套的 node_modules 结构,
早期依赖地狱 Dependency Hell,后期扁平化
幽灵依赖
不确定性
依赖分身
yarn
提升安装速度,解决不确定性
并发安装,缓存机制 离线策略 yarn-lock等
pnpm
Store + linux 硬链接和软链接的区别和联系
pnpm=>解决问题:
依赖结构的不确定性。
扁平化算法本身的复杂性很高,耗时较长。
幽灵依赖
依赖分身
本身问题
pnpm=>弊端
1.在不支持软链接的环境中,无法使用pnpm,比如 Electron 应用。
2.为依赖源文件是安装在 store 中,调试依赖或 patch-package 给依赖打补丁也不太方便,可能会影响其他项目。
3.因为使用 PnP 不会再有 node_modules 了,但是 Webpack,Babel 等各种前端工具都依赖 node_modules。虽然很多工具比如 pnp-webpack-plugin 已经在解决了,但难免会有兼容性风险。
深入浅出 npm & yarn & pnpm 包管理机制
重学前端——npm yarn pnpm
monorepo
1. monorepo 是管理项目代码的一种方式,指在一个仓库项目(repo)中管理多个模块/包(package)
2. monorepo 最主要的好处是统一的工作流和代码共享
3. Lerna 是一个管理多个 npm 模块的工具,优化维护多包的工作流,解决多个包相互依赖,且发布需要手动维护多个包的问题
lerna
WeakMap与Map
1.WeakMap的key只能是obj,map可以是字符串简单类型。
2.当WeakMap的key引用为null时,WeakMap中设置的值也会销毁,而map会保留,内存中也会保留。
---测试方法
class MyFn { }
let mf=newMyFn();
let map = new WeakMap();
map.set(mf, 'ok');
mf = null; // 对于map来说这里写不写mf都会保留在map中,在内存中搜索变量newMyFn可是可以搜索到的
console.log(map);
内存中搜索变量
html5 webwork的使用方式
---检测浏览器是否支持 Web Worker
<script type="text/javascript">//WEB页主线程var worker =new Worker("worker.js"); //创建一个Worker对象并向它传递将在新线程中执行的脚本的URLworker.postMessage("hello world"); //向worker发送数据worker.onmessage =function(evt){ //接收worker传过来的数据函数console.log(evt.data); //输出worker发送来的数据}</script>//worker.js
onmessage =function (evt){var d = evt.data;//通过evt.data获得发送来的数据postMessage( d );//将获取到的数据发送会主线程
}
通过这个例子我们可以看出使用web worker主要分为以下几部分
WEB主线程:
1.通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker,同时返回一个worker实例。
2.通过worker.postMessage( data ) 方法来向worker发送数据。
3.绑定worker.onmessage方法来接收worker发送过来的数据。
4.可以使用 worker.terminate() 来终止一个worker的执行。
worker新线程:
1.通过postMessage( data ) 方法来向主线程发送数据。
2.绑定onmessage方法来接收主线程发送过来的数据。
Tree-Shaking原理
Webpack 原理系列九:Tree-Shaking 实现原理
DCE (Dead code elimination)
代码不会被执⾏,不可到达
代码执⾏的结果不会被⽤到
代码只会影响死变量(只写不读)
Tree-Shaking是DCE的一种方式。
基于esmodule
uglify对帮忙删除同一模块的没有使用的方法模块,和没有使用的变量或者语句,uglify目前不会跨文件去做DCE------------------------------------------------------------------
#### 可以跨浏览器标签的通信方法
[浏览器-跨页面通信](https://blog.csdn.net/baidu_38242832/article/details/116672114)postMessage
```javascript
同源页面通信:广播模式:Broadcast Channe / Service Worker / LocalStorage + StorageEvent共享存储模式:Shared Worker / IndexedDB / cookie口口相传模式:window.open + window.opener基于服务端:Websocket / Comet / SSE 等
非同源页面通信:通过嵌入同源 iframe 作为“桥”,将非同源页面通信转换为同源页面通信。
worker.onmessage= function (event) { // 把子线程返回的结果添加到 div 上document.getElementById("result").innerHTML += event.data+"<br/>"; }; }
----
postMessage("Before computing,"+new Date());
0.1+0.2 等于 0.3 吗?(数字相加结果有无限小数的原因及解决方式)
0.1+0.2 不等于 0.3 ,因为在 0.1+0.2 的计算过程中发生了两次精度丢失。第一次是在 0.1 和 0.2 转成双精度二进制浮点数时,由于二进制浮点数的小数位只能存储52位,导致小数点后第53位的数要进行为1则进1为0则舍去的操作,从而造成一次精度丢失。第二次在 0.1 和 0.2 转成二进制浮点数后,二进制浮点数相加的过程中,小数位相加导致小数位多出了一位,又要让第53位的数进行为1则进1为0则舍去的操作,又造成一次精度丢失。最终导致 0.1+0.2 不等于0.3 。
---拓展
若你回答出来,面试官还可能继续问你:“ 0.1+0.2 不等于 0.3 会引起那些BUG?”
可以这样回答:“ 会引起统计页面展示错乱的BUG,还有 300.01 优惠300 元后,支付金额不足0.01 元等类似的BUG。”
---解决方式1
(0.1+0.2).toFixed(6) === 0.3.toFixed(6)
---解决方案2
Math.round(Math.pow(10, 6) * (0.1+0.2)) / Math.pow(10, 6)
---解决方案3 (toFixed返回的是字符串)
parseFloat((0.1 + 0.2).toFixed(10))
Next.js—一个轻量级的 React SSR应用框架
Next.js 是一个轻量级的 React 服务端渲染应用框架。
优点:
完善的React项目架构,搭建轻松。比如:Webpack配置,服务器启动,路由配置,缓存能力,这些在它内部已经完善的为我们搭建完成了。
丰富的插件帮开发人员增加各种功能。
自带数据同步策略,解决服务端渲染最大难点。把服务端渲染好的数据,拿到客户端重用,这个在没有框架的时候,是非常复杂和困难的。有了Next.js,它为我们提供了非常好的解决方法,让我们轻松的就可以实现这些步骤。
js和原生通信的一般方法大纲
JSBridge的原理及使用
JSBridge 的通信原理:
js调用native,1.1 注入API, 拦截 URL SCHEME.
Native 调用 JavaScript 的方式, 直接执行拼接好的 JavaScript 代码即可.
隐式类型转换和显示类型转换
JS的隐式类型转换
JS的数据类型转换(显式转换和隐式转换)
------+
+和Number的效果一样
+true 为 1
+NaN NaN
+'asdf’ NaN
+null 0
+undefined NaN
-----
Number(undefined) =NaN;
Number(null)=0;
Number(true)=1;
Number(false)=0;
Number('')=0;
Number(' ')=0;
Number(NaN)=NaN;
undefined==时,右边只有是null和undefined才是true,其余都是false
null==时,右边只有是null和undefined才是true,其余都是false
NaN==时,无论右边是什么,都是false
------
有以下6个虚值,在转为boolean时为false
分别是undefined,null,0,NaN,false,‘’
-----
使用!时,会将表达式隐式转换为Boolean类型
-----
4)将引用值转换为原始值时:使用Number(obj)时,会调用obj的valueOf的返回值,如果是基本数据类型则直接使用,如果是引用数据类型,就会找到obj的toString()方法,如果是基本数据类型,就会返回,如果也是引用数据类型,就会报错。如果自身没有toString方法,就会顺着原型链查找,调用的原型的toString方法。这里举几个例子:Number([])//0
Number({}) //NaN
----
首先我们要记住一点,所有的==比较,最终都是将左右两边转换成Number类型进行比较
[]==![]
{}==!{}
Ps: null==undefined 并且,+null 0,+undefined NaN
ES6 一共有 5 种方法可以遍历对象的属性。
(1)for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
首先遍历所有数值键,按照数值升序排列。
其次遍历所有字符串键,按照加入时间升序排列。
最后遍历所有 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
// ['2', '10', 'b', 'a', Symbol()]
上面代码中,Reflect.ownKeys方法返回一个数组,包含了参数对象的所有属性。这个数组的属性次序是这样的,首先是数值属性2和10,其次是字符串属性b和a,最后是 Symbol 属性。
wasm
什么是WebAssembly(Wasm)?
WebAssembly运行时库(WASM runtime:wasmer 或 wasmtime)\将rust官方demo猜数字编译为WASI目标并使用Wasmer运行
再次认识 WebAssembly
gis webassembly
WebAssembly优势:
快速高效:WebAssembly被设计为针对Size和Load Time进行优化的格式,可以在各个硬件平台上以native speed运行;
安全性:WebAssembly是运行在沙盒内的,甚至可以和当前的Java虚拟机共享一套环境,并且也遵守浏览器各种跨域不跨域的规章制度;
开放性:WebAssembly开放标准,不受任何一家厂商控制,并且被设计为可以和Java API和Context交互。wasm只是一个字节码标准,人们可以基于这个标准开发高级语言。类似jvm一样,很多语言可以编译成jvm字节码,从而使用jvm平台。wasm出现的意义是使用其他语言开发web app成为可能。WebAssembly 目前还不具备 IO 以及 DOM 访问能力。**跟外接的交互只有实现函数并导出,以及在函数实现中调用导入的函数。如果在浏览器或者 Node.js 中运行一定需要借助 JavaScript 才行。
1. 我看到运行时,wasmer介绍的挺好的哈,为啥我们不用呢?解释器,速度不够快,系统接口支持不太好
2. wasm edge我们当时放弃了?支持不太全面,wasi支持不太好。
3. wasmtime
4. 多种语言编译为wasm有什么问题么?比如c, pythonc, py, go => wasm编译器,rust,c,c++,go (java相对不成熟)运行时,虚拟机
5. 浏览器使用wasm。wasm gpu, cpu计算快wasm 比 js 更快,基于web work + 多线程可视化的计算库放到wasmrath https://github.com/Kanaries/Rath
6. 我们现在用的 运行时 wamr
目前应该工业界实际应用也非常多,是intel出品的,编译完二进制只要几百 kb,对比wasmtime,是 50mb
「 不懂就问 」esbuild 为什么这么快?
ESbuild 介绍
前端打包工具Esbuild–模块化、ESM、esbuild-loader
【JavaScript】ESModule(esm)
esbuild 是新一代的 JavaScript 打包工具。
他的作者是 Figma 的 CTO
esbuild以速度快而著称,耗时只有 webpack 的 2% ~3%。
---快的原因
1. 它是用 Go 语言编写的,并可以编译为本地代码。
--go
Go 是为并行性而设计的,而 JavaScript 不是。Go在线程之间共享内存,而JavaScript必须在线程之间序列化数据。Go 和 JavaScript都有并行的垃圾收集器,但是Go的堆在所有线程之间共享,而对于JavaScript, 每个JavaScript线程中都有一个单独的堆。
3. 大量使用了并行操作。
4. 代码都是自己写的, 没有使用第三方依赖。
5. 内存的高效利用。
---缺点
对JS语法支持度不足对不支持的语法会‘原样输出’到构建产物Top-level awaitasync awaitBigIntHashbang 语法
不支持 AST 过程的能力扩展会导致依赖AST处理的babel-plugin无法正常工作例如: babel-plugin-import,或者自定义的babel-plugin
不兼容低版本浏览器esbuild 仅将代码编译成 es6
不支持TS类型检查作者明确表示未来也不会支持TS 类型检查能力需要额外引入其他类型检查插件
构建工具 Vite、Webpack、Rollup对比
vite快的原因
1. 原理角度:vite使用浏览器支持的esmodule,esbuild是采用go语言编写,因为go语言的操作是纳秒级别,而js是以毫秒计数,所以vite比用js编写的打包器快10-100倍。
2. 启动阶段:vite因为它在启动的时候不需要打包,所以不用分析模块与模块之间的依赖关系,不用进行编译。
3. 热更新阶段:vite在浏览器访问devServer的时候,直接返回对应的渲染文件,而webpack是把所有都整合成bundle,返回结果。
vite
多框架支持,vue,react
全新插件机制和 API(很多 Rollup 插件可以跟 Vite 直接兼容)
基于 esbuild 的依赖预打包
更好的 CSS 支持(CSS 代码分割,自动 URL 改写)
服务端渲染 (SSR) 支持
批量引入(通配引入)(glob import)
支持Web Assembly引入
引入Web Workers
npm init vite(然后选择命令的名字,选择vue还是react)
---vite3特点
全新的 VitePress 文档
---cli端口更新
---websocket的连接策略生效
---服务冷启动性能提升
---ssr产物默认使用esm格式
---relative base支持
webpack是目前整个前端使用最多的构建工具,但是除了webpack之后也存在其他一些构建工具。比如说rollup,parcel,gulp,vite等等。vite的官方定位是下一代前端开发和构建工具。
我们知道在实际开发中,我们在编写的代码往往是不能被浏览器直接识别的,比如ES6,TypeScript,Vue文件等。所以此时我们必须通过构建工具来对代码进行转换,编译,类似的工具有webpack,rollup,parcel.但是随着项目越来越大,需要处理的javascript呈指数级增长,模块越来越多。构建工具需要很长时间才能开启服务器,HMR也需要几秒钟才能在浏览器反应过来。所以出现了vite。
分析vite
浅谈vite与webpack的区别及Vite为什么那么快
Vue 2 中,使用Vite作为前端构建开发工具,替代webpack(二)常见问题——和webpack 入口文件同名冲突 & 将commonjs转化为es module-cjs2esmodule
vite详解
Vite 2.0 发布了
【译】Vite2.0新特性
vite3