赞
踩
| 特性 | Cookie | localStroage | sessionStorage | indexDB |
| — | — | — | — | — |
| 数据生命周期 | 一般由服务器生成,可以设置过期事件 | 除非被清理,否则一直存在 | 页面关闭时就被清理 | 除非被清理,否则一直存在 |
| 数据存储大小 | 4kb | 5mb | 5mb | 无限 |
| 与服务端的通信 | 会一直携带在请求头 | 不参与下 | 不参与 | 不参与 |
PS:没有大量的数据需求的话,可以使用localStorage和sessionStorage,对于不怎么改变的数据,尽量使用localStorage。
Service Worker是运行在浏览器背后的独立线程,一般可以用来实现缓存功能,使用Service Worker的话,传输协议必须使用HTTPS。
使用Service Worker实现缓存一般分为三个步骤:
1)首先要注册Service
2)监听install,拿到需要缓存的文件
3)下次用户访问的时候就可以通过拦截请求方式查询是否存在缓存,存在缓存的话就可以直接读取缓存文件,否则就去请求数据
缓存可以是性能优化中简单高效的一种方式
对于一个数据请求,分为3个阶段,分为网络请求、后端处理、浏览器响应。浏览器缓存可以帮助我们在第一和第三步中优化性能。比如直接使用缓存而不发请求,或者发请求但后端的数据与前端一致,那么就没有必要再将数据回传回来,这样就减少可数据响应。
接下来我们将通过以下几个方面来探讨浏览器的缓存机制
缓存位置
缓存策略
实际场景应用缓存策略
我知道的浏览器的缓存位置有Service Worker、网络请求,并且有各自的优先级,当一次查找缓存并且都没有命中的时候,才会请求网络。
通常浏览器的缓存策略可以分为两种:强缓存和协商缓存。并且这两种缓存策略都是通过设置 HTTP Header 来实现的
1)强缓存(有两种设置方式)
Expires:缓存受限于本地的时间
Cache-Control:通过max-age来设置缓存的时间期限
2)协商缓存(两种设置方式)
简单的说,如果缓存过了,就需要发起请求验证资源是否更新。即当浏览器发送请求验证时,如果资源没有发生改变,那么服务器就返回304状态码,并更新浏览器的缓存有效期。(相当于浏览器和服务器进行协商,是否返回新的数据)
Last-Modified表示本地文件最后修改日期,当 Last-Modified的值发送给服务器,循环服务器在该日期后资源是否有变更,有则返回新的资源,否则返回304状态码
当ETag的值发送给服务器,询问该资源是否有更新,有则返回新的资源(并且ETag的资源比Last-Modified高)
一般来说,现在都会使用工具来打包代码,那么我们可以对文件名进行哈希处理,只有当代码修改之后生产新的文件名。基于此,我们就可以给代码设置缓存有效期一年Cache-Control:max-age=3153600,这样只有html文件中引入的文件名发生了改变,才回去下载新的代码,否则就一直使用缓存。
使用分页技术
若不分页,则使用虚拟滚动技术(比如elment-ui中的scrollbar可以实现)
虚拟滚动:原理时只渲染可视区域内的内容,非可视区的则不渲染,当用户在滚动的时候就实时去替换渲染的内容。
我们知道,在浏览器的渲染线程和JS引擎线程时互斥的,因此在渲染时,若遇到script标签时,则此时会渲染会停止下来,等待script代码加载完毕,再从暂停的地方重新渲染。也就是说,当你想首屏渲染越快,那么就不应该再首屏加载js文件,也就是建议将script标签放在body标签底部的原因。当然,你也可以给script标签添加defer或者async属性,那么此时的script可以放在任意位置,因为此时js文件会并行下载,若时defer,会等待页面渲染结束才执行,而async会在加载完毕之后立即执行。
只是defer和async表示js文件的加载和解析不会阻塞渲染。‘
重绘是节点更改了外观而不影响布局,比如更改元素的color属性
回流是改变了节点的布局或者几何属性,比如改变元素的宽高等属性
回流必然发生重绘,重绘不一定引发回流。
1.使用transform替换top
2.使用visibility替换display:none,因为前者只会引发重绘,而后者会引发回流
3.少用table布局,因为table布局很小的一个改动会引发整个table的重新布局
4.将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点。(比如video标签,浏览器会自动将该节点变为图层)
XSS(Cross-Site Scripting)—跨站脚本攻击,简称XSS,是一种代码注入攻击,攻击者通过在目标网址注入恶意脚本,使之在用户的的浏览器上运行。利用这些恶意脚本,攻击者获取用户敏感信息如Cookie、SessionID等,进而危害数据安全
XSS的本质:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行
由于问题的源头是js代码的注入,那么我们便想办法不让js生效
方式1:使用转义字符
即需要注意两头的防范:
1)输入
在提交表单时,前端最好将文本内容转成html实体编码,也就是过滤掉
2)输出
在显示文本时,最好也要做一次html实体编码转换后再显示,防止
方式2:CSP建立白名单
建立白名单,即是明确告诉浏览器哪些外部资源可以加载和执行。(我们只需要配置规则,如何拦截是由浏览器自己实现的)
通常可以通过两种方式来开启CSP:
1)设置HTTP Header中的Content-Security-Policy
2)设置meta标签的方式
CSRF中文名为跨站请求伪造,原理是攻击者诱导受害者进入第三方网站,在第三方网站中向被攻击网站发送跨站请求,利用受害者在被攻击已获取的注册凭证,绕过后台的验证,达到冒充用户对被攻击的网站执行某项操作的目的。
几种常见的攻击类型
1)GET类型的CSRF利用非常简单,只需要一个HTTP请求,一般会这样利用
在受害者访问这个img页面之后,浏览器会自动向https://i-blog.csdnimg.cn/blog_migrate/ab97726867f1f152380ff52b11b9d26c.png
发送一次http请求,bank.example就会收到包含受害者登录信息的一次跨域请求(因此此时受害访问了A网站,那么其是包含着认证信息的,攻击者利用这一特性,隐形中让受害者向上网站(B)发起HTTP请求,那么此时请求头自然也会包含了受害者的认证信息,那么攻击者的目的便达到!)
CSRF通常是第三方网站发起的,被攻击者的网站无法防止攻击的发生,只能通过增强自己的网站针对CSRF的防护能力来提升安全性
SCRF的两个特点:
SCRF(通常)发生在第三方域名
SCRF攻击者不能取到Cookie等信息,只是冒用
针对以上两个特点,我们可以专门指定防护策略,如下:
阻止不明外域的访问
同源检测
Samesite Cookie
提交时要附加本域才能获取信息
CSRF Token
双重Cookie验证
前面讲的CSRF的一特征是,攻击者无法直接窃取到用户的信息(Cookie、Header,网站内容等,仅仅是冒用Cookie中的信息)
而CSRF攻击之所以能成功,是因为服务器误把攻击者发送的请求当成了用户的请求,那么所有用户请求都会携带一个CSRF攻击者无法获取到的Token,服务器便可以通过校验请求是否携带正确的Token,来把正常的请求和攻击请求区分开来,也可以防范CSRF的攻击
参考文章:https://my.oschina.net/meituantech/blog/2243958
点击劫持就是攻击者利用iframe将受害者网站嵌入自己的网页中,并将iframe设置为透明,在页面中透出一个按钮诱导用户点击。
通常可以使用以下两种方式进行防御:
1)设置HTTP响应头:X-FRAME-OPTIONS
这个响应头主要是用来防御iframe嵌套的点击劫持,其有三个可选值,分别是:
DENY:表示页面不允许通过iframe的方式展示
SAMEORINGIN:表示页面可以在相同的域名下通过iframe的方式展示
ALLOW-FROM:表示页面可以在指定来源iframe中展示
2)通过JS防御
因为有些浏览器不支持1)的方式
JS防御的原理是通过iframe的方式加载页面时,攻击者的页面直接不显示内容。
尽可能的将js、css文件合并为一个文件,减少了向服务器发送请求(webpack)
若浏览器支持,尽可能使用webp格式的图片代替其他图片格式
尽量使用字体图标或者SVG图代替传统的png图
尽量使用精灵图或者说时雪碧图(一方面可以减少向服务器发送请求,另一方面则是降低了资源占用空间大小)
可以适当的使用缓存技术,比如对于不怎么发生变化的数据,使用h5新增等的localstorage、sessionStorage,以减少发送请求的次数
闭包-------在js中尽量减少使用闭包(因为闭包所在的上下文不会被释放)
重绘和回流-----减少对DOM的操作,主要时减少DOM的重绘和回流
-scc与js代码的位置----- 把css代码放在body上,把js代码放在body下面(以提高首屏加载的速度,当然也可以对script标签使用defer和async属性)
css的导入方式-----css的导入尽量减少使用@import,因为@import是同步操作,可以使用link导入
懒执行-----对某些特定的逻辑代码进行懒执行操作。主要用于某些耗时的逻辑操作,且不需要在首屏就使用时,便可以使用定时器或者时间调用来唤醒。
懒加载-------懒加载是将不关键的资源延后加载
1.优化Loader
2.实现按需加载
比如在一个SPA项目中,项目会有十几个甚至更更多的路由页面,我们可以实现按需加载,以减少一些不必要代码的加载
1)Hash模式
Hash模式是根据#后面哈希值的变化时,触发了hashchange事件来监听到url的变化,从而进行页面的跳转。并且无论哈希值怎么样变化,服务器接收到的url永远都是#前面部分的url
如www.test.com/#/---------->www.test.com
2)History模式
History模式是H5新推出来的功能,主要使用history.pushState和history.repalceState改变url,同样,通过History模式改变url也不会引起页面的刷新,只会更新浏览器的历史记录
3)两种方式的区别
Hash模式只可以更改#后面的内容,History模式可以通过API设置任意的同源URL
Hash不需要后端配置,兼容性好。History模式再用户手动输入地址或者刷新的时候会发送url请求,后端需要配置index.html页面用于匹配不到的静态页面资源。
我当时使用webpack的主要原因是为了简化页面依赖的管理,并且通过将其打包为一个文件来降低页面加载时请求的资源数。
我认为webpack的主要原理是,它将所有的资源看成一个模块,并且把页面逻辑当成一个整体,通过一个给定的入口文件,webpack从这个文件开始,找到所有的依赖文件,将这个依赖文件模板通过loader和plugins处理后,然后打包在一起,最后输出一个浏览器可以识别的js文件。
简单的说,函数式编程是一种编程范式,也就是如何编写程序的方法论
它具有以下特性:闭包和高阶函数、惰性计算、递归
第一种最常见的就是回调函数的方式,使用回调函数的方式有一个缺点就是,多个回调嵌套的时候会造成回调函数地狱,上下两层的回调函数间的代码耦合度太高,不利于代码的可维护。
第二种是Promise的方式,使用Promise的方式可以将嵌套的回调函数作为链式调用,但是使用这种方法,有时会造成多个then的链式调用,可能会造成代码的语义不够明确。
第三种是使用async函数的形式,它内部自带执行器,当函数内部执行一个awiait语句的时候,如果语句返回一个promise对象,那么函数就会将等待promise对象的状态变为resolve后再继续向下执行。因此我们可以将异步逻辑,转换成同步的顺序来书写,并且这个函数可以自动执行。
URI:统一资源标识符
URL:统一资源定位符
URN:统一资源名称
PS:‘
1)URI指的是统一标识符,用唯一的标识来确定一个资源,它是一种抽象的定义,也就是说,不管使用什么方法来定义,只要能唯一标识一个资源,就可以成为URI
2)URL和URN是URI的子集,URL可以理解为使用地址来标识资源,URN可以理解为使用名称来标识资源。
缓存一般适用于那些不会更新服务端数据的请求,一般get请求都是查找请求,不会对服务器资源造成修改,而post请求一般都会对服务器数据造成修改,所以,一般会对get请求进行缓存,很少会对post请求进行缓存。
相关知识点:
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染
懒加载:
懒加载也叫做延迟加载,即是当用需要访问时,在去加载,这样可以提高网站首屏加载速度,提升用户的体验,并且还可以减少服务器的压力。它适用于图片很多时,页面很长的电商网站的场景。懒加载的实现原理是,将页面上的图片的src属性设置为空字符串,将图片的真是路径保存在一个自定义的属性中,当页面滚动时候,进行判断,如果图片进入页面可视区域,则从自定义的属性中取出真是路径赋值给图片的src属性,以此来实现图片的延迟加载。(比如在vue中使用v-lazy)
预先加载:
预先加载指得是将所需的资源提前加载到本地,这样后面在需要用到时就直接从缓存资源通过预加载能够减少用户的等待时间,提高用户的体验。我了解的预加载最常用的方式是使用js中的image对象,通过image对象设置src属性,来实现图片的预加载。
总:
这两种方式都是提高网页性能的方式,两者主0 要区别是一个要提前加载好,一个是延迟加载。懒加载对服务前端有一定的缓解压力的作用,预加载则会增加服务端压力。
设计模式可以分为三大类:
结构型模式:通过识别系统中组件间的简单关系来简化系统色设计
创建型模式:处理对象的创建,根据实际情况使用合适的方式创建对象
行为型模式:用于识别对象之间常见的交互模式并加以实现,如此增加了这些交互的灵活性。
说明:你可以想象一个场景,假设有一份很复杂的代码需要用户去调用,但是用户并不关心这些复杂的代码,只需要你提供一个接口去调用,用户只负责传递需要的参数,至于这个参数怎么使用,内部逻辑不用关心,只需要你最后返回一个实例,这个构造过程就是工厂。
工厂起到的作用就是隐藏了创建实例的复杂度,只需要一个接口,简单清晰。
现实生活中的工厂按照既定的程序制造产品,随着生产原料和流程不同生产出来的产品也会有区别。应用到软件工厂的领域,工厂可以看成是一个制造其他对象的对象,制造出来的对象也会随着传入共产对象的参数的不同而有所区别
那么,什么时候适合使用共产模式而不是直接new一个对象呢?当构造函数过多不便管理,且需要创建的对象之间存在某些关联(有同一个父类,实现同一个接口)时,不妨使用工厂模式,工厂模式提供一种集中化,统一化的方式,避免了分散创建对象导致的代码重复、灵活性差的问题。
举例如下:(构造一个简单的汽车工厂来生产汽车)
//汽车构造函数
function Car1(color) {
this.color = color
this.brand = ‘Car1’
}
//汽车构造函数
function Car2(color) {
this.color = color;
this.brand = ‘Car2’
}
//汽车构造函数
function Car3(color) {
this.color = color;
this.brand = ‘Car3’
}
//汽车的品牌
const BRANDS = {
car1: 1,
car2: 2,
car3: 3
}
//汽车工厂
function createCar() {
this.create = function (brand, color) {
switch (brand) {
case BRANDS.car1:
return new Car1(color);
case BRANDS.car2:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-1kBjWD9L-1712781935228)]
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-zUcYzjG5-1712781935228)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。