优化 面试题

98 阅读38分钟

工程化

前端工程化是一种将软件工程的方法和思想应用于前端开发的过程。它主要指从前端项目开始开发到部署线上再到后期迭代维护的整个过程,从工程的角度管理前端开发,形成前端开发流程的一整套开发规范或解决方案,提高前端开发效率。

前端工程化可以提升开发体验、提高开发效率和质量、提升应用的访问性能。一切以提高效率、降低成本、质量保证为目的的手段都属于工程化。

webpack

构建流程

Webpack的构建流程大致如下:

  1. 初始化参数:根据命令行和配置文件收集参数,形成最终的配置结果。
  2. 开始编译:传入参数,创建compiler实例,注册所有配置的插件,插件监听Webpack构建生命周期的事件节点,做出相应的反应,执行对象的run方法开始执行编译。
  3. 确定入口:从配置文件中指定的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去。
  4. 编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。
  5. 完成模块编译并输出:递归完后,得到每个文件结果,包含每个模块以及它们之间的依赖关系,根据entry配置生成代码块chunk。输出所有的chunk到文件系统。

优化Webpack的构建速度

优化Webpack的构建速度有很多方法,可以从以下几个方面入手:

  • 使用新版本:升级到最新版本的Webpack可以带来性能提升,因为每个版本的Webpack都会进行一些性能优化。
  • 使用缓存:可以使用缓存来加快构建速度,例如使用babel-loaderts-loaderloader的缓存选项。
  • 多线程编译:可以使用多线程来加快编译速度,例如使用thread-loaderhappypack
  • 速度分析:可以使用speed-measure-webpack-plugin来分析Webpack构建期间各个阶段花费的时间,从而快速定位到可以优化的地方。

优化Webpack的构建速度可以带来许多好处。随着项目涉及到的页面越来越多,功能和业务代码也会越来越多,相应的Webpack的构建时间也会越来越久。这个时候我们就不得不考虑性能优化的事情了。
因为这个构建时间与我们的日常开发是密切相关,当我们本地开发启动devServer或者build的时候,如果时间过长,会大大降低我们的工作效率。试想一下,我们突然碰到一个紧急bug,项目启动需要花费几分钟,改完后项目build上线也要几分钟,换谁估计都得有暴脾气了...

优化 Webpack 的打包体积

优化Webpack的打包体积可以带来许多好处。打包体积越小,应用程序的加载速度就越快,用户体验就越好。下面是一些优化Webpack打包体积的方法:

  • 提取公共代码:在多入口情况下,可以使用CommonsChunkPlugin来提取公共代码。
  • 提取常用库:可以通过externals配置来提取常用库。
  • 预编译资源模块:可以利用DllPluginDllReferencePlugin预编译资源模块。
  • 剔除多余代码:可以使用Tree-shakingScope Hoisting来剔除多余代码。例如:如果你在开发项目时将整个组件库都引入了,那么在使用Webpack打包时,可以使用Tree-shaking来自动删除没有引用的组件,从而减小打包体积。
扩展:Tree-shaking

Tree-shaking是一种通过静态分析代码,删除未引用代码的技术。它可以帮助开发人员减小打包体积,提高应用程序的加载速度。

Tree-shaking的原理是基于ES6模块的静态结构特性。由于ES6模块的导入和导出是在编译时确定的,而不是在运行时确定的,因此Webpack可以在构建过程中静态分析代码,找出未被引用的模块,并将它们从最终的打包文件中删除。

不过需要注意的是,Tree-shaking只能删除未被引用的模块,而不能删除未被执行的代码。因此,如果你想要使用Tree-shaking来优化打包体积,需要注意代码组织方式,尽量避免在一个模块中混合使用被引用和未被引用的代码。

性能优化

Webpack性能优化有很多方法,可以从以下几个方面入手:

  • 减少模块解析:可以通过配置resolve.alias来减少模块解析的时间。
  • 优化loader性能:可以通过限制loader的应用范围来提高构建速度。
  • 使用热替换(HMR):虽然热替换并不能降低构建时间,但它可以降低代码改动到效果呈现的时间。
  • 手动分包:可以通过手动分包来减少打包时间。
  • 使用新版本:使用新版本的Webpack可以带来性能提升,因为每个版本的Webpack都会进行一些性能优化。

loader && plugin

Webpack的loader和plugin是两种不同的扩展机制,它们都可以帮助开发人员定制Webpack的构建过程。

  • Loader:用于对模块的源代码进行转换。它们可以将非JavaScript文件(如CSS、图片等)转换为Webpack能够处理的模块。常用的loader有:babel-loader(用于将ES6+代码转换为ES5代码)、css-loader(用于加载CSS文件)、file-loader(用于加载文件)等。
  • Plugin:用于扩展Webpack的功能。它们可以在构建过程中执行各种任务,如优化输出文件、管理资源等。常用的plugin有:HtmlWebpackPlugin(用于生成HTML文件)、MiniCssExtractPlugin(用于提取CSS文件)、UglifyJsPlugin(用于压缩JavaScript代码)等。

git

Git是一种分布式版本控制系统,它可以帮助开发人员管理和协作代码。Git可以跟踪代码的变化历史,帮助开发人员查看每次修改的内容,并在出现问题时快速恢复到之前的状态。

Git支持分支和合并,可以帮助开发人员在不同的分支上并行开发功能,然后将它们合并到主分支上。这样,开发人员可以更好地协作,并更快地完成项目。

常用的git命令:

  • git init:初始化本地git仓库(创建新仓库)
  • git add:添加文件到暂存区
  • git commit:提交暂存区到本地仓库
  • git status:查看当前版本状态(是否修改)
  • git push:将当前分支push到远程分支
  • git pull:获取远程分支并merge到当前分支
  • git clone:clone远程仓库
  • git branch:显示本地分支
  • git branch -d:删除分支
  • git checkout:检出已存在的分支或文件
  • git checkout -b:创建+切换分支
  • git merge:合并分支

不同类型的分支:

  • master分支:通常用于线上发布使用。它应该始终保持稳定,并且只接受来自其他分支经过充分测试和验证的更改。
  • dev分支:用于平常的开发和测试。它通常包含最新的开发进度,并且可以接受来自功能分支或修复分支的更改。
  • Feature branches(功能分支):用于开发新功能。每个功能分支都应该专注于一个特定的功能,并且在功能完成后合并到dev分支。
  • Hotfix branches(修复分支):用于修复bug。每个修复分支都应该专注于修复一个特定的bug,并且在修复完成后合并到dev分支。
  • Release branches(发布分支):用于准备新版本的发布。它通常从dev分支中创建,并且只接受用于修复bug和准备发布的更改。当新版本准备好发布时,发布分支会被合并到master分支和dev分支。

ESLint

ESLint是一个用于识别和报告ECMAScript/JavaScript代码中模式的工具,旨在使代码更加一致并避免错误。它是完全可插拔的,每个规则都是一个插件,你可以在运行时添加更多。你还可以添加社区插件、配置和解析器来扩展ESLint的功能。

ESLint可以帮助你快速找到代码中的问题。它内置于大多数文本编辑器中,你可以将ESLint作为持续集成管道的一部分运行。许多ESLint发现的问题都可以自动修复。ESLint修复是语法感知的,因此你不会遇到传统查找和替换算法引入的错误。

作用:

  • 快速找到代码中的问题:ESLint静态分析你的代码以快速找到问题。
  • 自动修复问题:许多ESLint发现的问题都可以自动修复。ESLint修复是语法感知的,因此你不会遇到传统查找和替换算法引入的错误。
  • 遵循编码规范:你可以配置ESLint来强制执行特定的编码规范,以确保你的代码风格一致;如果是团队协作开发,它可以帮助团队成员遵循统一的编码规范,确保代码风格一致,便于阅读和理解彼此的代码。
  • 提高代码质量:通过识别和修复潜在的问题,ESLint可以帮助你提高代码质量并减少错误。

其他

补充说明一些常见的前端工程化工具和技术:

  • 模块化工具:如CommonJS、AMD和ES6模块等,用于将复杂的前端代码分解为更易于管理的模块。
  • 构建工具:如Grunt、Gulp和Webpack等,用于自动化执行常见的前端开发任务,如压缩、合并和转换代码等。
  • 代码检查工具:如ESLint和JSHint等,用于检查代码质量并确保遵循编码规范。
  • 单元测试工具:如Jasmine和Mocha等,用于编写和运行单元测试,以确保代码的正确性。

项目优化

性能优化

前端页面性能优化是一个复杂的过程,可以从多个方面进行优化。一些常见的优化方法包括:

  • 减少请求数量:通过合并文件、使用雪碧图、使用字体图标等方法来减少HTTP请求数量。
  • 减小资源大小:通过压缩代码、压缩图片、使用Gzip等方法来减小资源大小。
  • 优化网络连接:通过使用CDN、DNS预解析、持久连接等方法来优化网络连接。
  • 优化资源加载:通过优化资源加载位置、使用异步加载、使用懒加载等方法来优化资源加载。
  • 减少重绘回流:通过避免使用CSS表达式、避免使用table布局、避免频繁操作样式等方法来减少重绘回流。
  • 使用性能更好的API:通过使用requestAnimationFrame、使用Web Workers、使用Service Workers等方法来使用性能更好的API。

重绘回流

回流(reflow)和重绘(repaint)是浏览器渲染过程中的两个步骤。它们都会影响页面的渲染性能,因此应尽量避免。

  • 回流:当页面中的元素的布局或几何属性发生变化时,浏览器需要重新计算元素的位置和大小,这个过程称为回流。回流会影响到页面中所有元素的位置和大小,因此它是一个非常耗时的过程。
  • 重绘:当页面中的元素的外观(如颜色、背景等)发生变化,但不影响布局时,浏览器会重新绘制这些元素,这个过程称为重绘。重绘不会影响到页面中其他元素的布局,因此它比回流更快。

避免回流和重绘的一些方法包括:

  1. 避免使用CSS表达式:CSS表达式会在每次页面渲染时重新计算,这会导致大量的回流和重绘。
  2. 避免使用table布局:table布局会导致大量的回流和重绘,应尽量避免使用。
  3. 避免频繁操作样式:频繁地修改元素的样式会导致大量的回流和重绘。可以考虑使用类名来修改样式,或者将多次修改样式的操作合并为一次。
  4. 避免频繁操作DOM:频繁地操作DOM会导致大量的回流和重绘。可以考虑使用文档片段(DocumentFragment)来减少对DOM的操作。

主要方法

  • 代码优化:可以通过压缩、合并和混淆代码来减小文件大小,提高页面加载速度。例如,可以使用UglifyJS等工具来压缩JavaScript代码,使用CSSNano等工具来压缩CSS代码。此外,还可以使用Webpack等构建工具来合并多个文件为一个文件,减少HTTP请求数量。
  • 资源优化:可以通过使用CDN、启用Gzip压缩、使用浏览器缓存等方法来优化资源加载,提高页面加载速度。例如,可以将静态资源部署到CDN上,以加快资源加载速度;可以在服务器端启用Gzip压缩,以减小传输文件的大小;可以合理设置HTTP缓存头,以利用浏览器缓存加快页面加载速度。
  • 页面结构优化:可以通过合理安排页面结构,避免使用嵌套过深的HTML标签,减少DOM操作等方法来优化页面结构,提高页面渲染速度。例如,可以避免在HTML中使用过多的嵌套标签;可以尽量减少对DOM的操作,避免触发浏览器的回流和重绘。
  • 交互优化:可以通过使用懒加载预加载按需加载等技术来优化用户交互,提升用户体验。例如,可以使用懒加载技术来延迟加载页面中不可见的图片;可以使用预加载技术来预先加载页面中即将需要的资源;可以使用按需加载技术来动态加载页面中需要的JavaScript模块。
  • 可维护性优化:可以通过使用模块化组件化设计模式等技术来提高代码的可维护性,降低维护成本。例如,可以使用CommonJS或ES6模块化语法来组织代码;可以使用React或Vue等框架来构建可复用的组件;可以使用设计模式来编写可扩展、可维护的代码。

其他一些措施:

  • 移除生产环境的控制台打印:在生产环境中,应该移除所有不必要的控制台打印,以减少对性能的影响。
  • 第三方库的按需加载:可以使用按需加载技术来动态加载第三方库中需要的部分,以减小文件大小和加快页面加载速度。
  • 降低请求成本:可以通过使用HTTP/2、使用Service Workers等技术来降低请求成本,提高页面加载速度。
  • 减少请求数:可以通过合并文件、使用雪碧图、使用字体图标等方法来减少HTTP请求数量。
  • 减小传输体积:可以通过压缩代码、压缩图片、启用Gzip压缩等方法来减小传输文件的大小。

其他

浏览器渲染一帧都做了什么?

浏览器渲染一帧的过程包括以下几个步骤:

  • 处理用户输入:浏览器会处理用户的输入事件,如鼠标点击、键盘输入等。
  • JavaScript执行:浏览器会执行页面中的JavaScript代码。
  • 请求动画帧回调:浏览器会执行requestAnimationFrame回调函数。
  • 样式计算:浏览器会计算元素的最终样式。
  • 布局:浏览器会根据元素的样式和大小计算它们在页面中的位置。
  • 绘制:浏览器会根据元素的样式和位置绘制它们。
  • 合成:浏览器会将多个图层合并为一张图像,并显示在屏幕上。
    这些步骤是浏览器渲染一帧的基本过程。不同的浏览器可能会有一些细微的差别,但总体流程是相同的。

计算机基础与网络通信

HTTP和HTTPS的基本概念

HTTP(超文本传输协议)和HTTPS(超文本传输安全协议)都是用于在Web浏览器和网站服务器之间传输信息的协议。它们的主要区别在于安全性。

  • HTTP是一种明文传输协议,它不提供任何加密机制。这意味着,如果攻击者截获了HTTP传输的数据,他们可以直接读取其中的内容。因此,HTTP不适合用于传输敏感信息,如信用卡号、密码等。

    • 优点:

      1. 简单快速:HTTP协议简单,通信速度快。
      2. 灵活:HTTP允许传输任意类型的数据对象,传输类型由Content-Type加以标记。
    • 缺点:

      1. 不安全:HTTP是明文传输,数据都是未加密的,容易被窃听截取。
      2. 数据完整性未校验:HTTP传输的数据完整性未校验,容易被篡改。

    工作原理:

    1. 客户端发起HTTP请求:客户端在浏览器中输入一个HTTP网址,然后连接到服务器的80端口。
    2. 服务器处理请求:服务器收到客户端的请求后,会根据请求的内容进行处理。
    3. 服务器返回响应:服务器处理完客户端的请求后,会返回一个响应,包括状态码、响应头和响应正文。
    4. 客户端处理响应:客户端收到服务器的响应后,会根据状态码和响应头进行相应的处理。如果状态码为200,表示请求成功,客户端会渲染响应正文中的内容。
  • HTTPS则是HTTP的安全版本。它在HTTP的基础上使用了SSL/TLS协议来加密数据。HTTPS 开发的主要目的是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。整个过程中,客户端和服务器之间传输的数据都是经过加密的,这意味着即使攻击者截获了HTTPS传输的数据,他们也无法读取其中的内容,除非能够破解加密算法。

    • 优点:

      1. 安全:HTTPS通过SSL/TLS协议对数据进行加密,保护了数据的安全性。
      2. 身份认证:HTTPS提供了对网站服务器的身份认证,防止了“中间人攻击”。
    • 缺点:

      1. 相对较慢:由于HTTPS需要进行加密和解密操作,因此它比HTTP相对较慢。
      2. 需要证书:使用HTTPS协议需要申请数字证书,可能需要一定的费用。

    工作原理:

    1. 客户端发起HTTPS请求:客户端在浏览器中输入一个HTTPS网址,然后连接到服务器的443端口。
    2. 服务器发送证书:服务器收到客户端的请求后,会将网站支持的证书信息(包括公钥)发送给客户端。
    3. 客户端验证证书:客户端收到证书后,会验证证书的有效性。如果证书有效,客户端会生成一个随机值,并使用公钥对该随机值进行加密。
    4. 客户端发送加密信息:客户端将加密后的随机值发送给服务器,以便服务器获取该随机值。
    5. 服务器解密信息:服务器使用私钥解密客户端发送的加密信息,从而获得客户端生成的随机值。
    6. 服务器发送加密数据:服务器使用该随机值对数据进行对称加密,并将加密后的数据发送给客户端。
    7. 客户端解密数据:客户端使用之前生成的随机值对服务器发送的加密数据进行解密,从而获得原始数据。

    怎么保证安全性的?
    HTTPS 通过使用对称加密、非对称加密、签名算法和证书机制来保证数据安全。在 HTTPS 请求过程中,客户端首先会请求服务端的数字证书,并生成一个随机数 R1,将随机数和自己支持的加密算法告诉服务端。服务端接收到客户端的请求后,会将自己的数字证书发送给客户端,并生成一个随机数 R2,然后根据客户端支持的加密算法选择一种加密算法,并将 R2 和加密算法告诉客户端。客户端接收到服务端的响应后,会验证服务端的数字证书是否有效,如果有效,则根据 R1、R2 和服务端选择的加密算法生成一个对称加密的密钥,并使用该密钥对后续通信进行加密。

    这样,HTTPS 协议就能够保证所有信息都是加密传播,第三方无法窃听;具有校验机制,一旦被篡改,通信双方会立刻发现;配备身份证书,防止身份被冒充1。

另外,HTTP和HTTPS还有一些其他区别。例如,它们使用的端口不同:HTTP默认使用80端口,而HTTPS默认使用443端口。且由于HTTPS需要进行加密解密操作,因此它比HTTP更耗费服务器资源。

TCP

TCP(传输控制协议)是一种面向连接的协议,它使用三次握手来建立连接,并使用四次挥手来断开连接。

三次握手

1434259-20190912110810463-453568401.jpg

过程:

  1. 第一次握手:客户端向服务器发送一个SYN报文,请求建立连接。报文中包含客户端的初始序列号。
  2. 第二次握手:服务器收到SYN报文后,如果同意建立连接,则向客户端发送一个SYN+ACK报文,表示确认客户端的SYN报文。报文中包含服务器的初始序列号和对客户端初始序列号的确认。
  3. 第三次握手:客户端收到SYN+ACK报文后,向服务器发送一个ACK报文,表示确认服务器的SYN+ACK报文。此时,TCP连接建立完成。

四次挥手

821276-20151016191142288-482208736.png

过程:

  1. 第一次挥手:当客户端没有更多数据要发送时,它会向服务器发送一个FIN报文,请求断开连接。
  2. 第二次挥手:服务器收到FIN报文后,向客户端发送一个ACK报文,表示确认客户端的FIN报文。
  3. 第三次挥手:当服务器没有更多数据要发送时,它会向客户端发送一个FIN报文,请求断开连接。
  4. 第四次挥手:客户端收到FIN报文后,向服务器发送一个ACK报文,表示确认服务器的FIN报文。此时,TCP连接断开完成。
那么为什么要进行三次握手和四次挥手呢?
  • 三次握手的目的是为了防止失效的连接请求报文突然又传送到了服务器,从而产生错误。通过三次握手,可以确保双方都准备好建立连接。
  • 四次挥手的目的是为了确保双方都能够完整地发送和接收数据。由于TCP是全双工通信协议,因此每个方向都需要单独进行关闭。这就需要四次挥手来完成。
TCP/IP 怎么保证数据包传输的有序可靠?

首先,TCP使用序列号和确认应答机制来保证数据包的有序传输。 每个发送的数据包都会被分配一个序列号,接收方收到数据包后会发送一个确认应答报文,其中包含对发送方序列号的确认。这样,发送方就能够知道哪些数据包已经被接收,哪些数据包需要重传。

其次,TCP使用检验和来保证数据包的完整性。 发送方在发送数据包时会计算一个检验和,并将其附加到数据包中。接收方收到数据包后会重新计算检验和并与发送方的检验和进行比较。如果两者不一致,则说明数据包在传输过程中发生了错误,接收方会丢弃该数据包并请求重传。

此外,TCP还使用超时重传机制来保证数据包的可靠传输。 当发送方发送一个数据包后,它会启动一个定时器。如果在定时器超时之前没有收到接收方的确认应答报文,则认为该数据包丢失,并进行重传。

最后,TCP还使用流量控制和拥塞控制机制来保证网络的稳定性。 流量控制通过调整发送窗口的大小来控制发送方的发送速率,防止接收方缓冲区溢出。拥塞控制则通过调整拥塞窗口的大小来控制网络拥塞程度,防止网络拥塞。

TCP和UDP的区别
  1. TCP是一种面向连接的协议,它在传输数据之前需要建立连接。
  2. UDP是一种无连接的协议,它不需要建立连接就可以直接发送数据。
  3. TCP提供了可靠的数据传输,它通过序列号、确认应答、重传等机制来保证数据包的有序可靠传输。而UDP不提供可靠性保证,它只负责将数据包发送出去,不保证数据包能够到达目的地。
  4. TCP提供了流量控制和拥塞控制机制来保证网络的稳定性。而UDP没有这些控制机制。

总之,TCP和UDP各有优缺点。TCP提供了可靠的数据传输,但速度相对较慢;而UDP速度快,但不提供可靠性保证。选择哪种协议取决于应用程序的需求。

解决跨域问题

跨域是指浏览器为了安全起见,限制了脚本内发起的跨源HTTP请求。这种限制被称为同源策略。同源策略规定,只有当协议域名端口都相同时,两个页面才被认为是同源的。如果两个页面不同源,那么它们之间就不能进行跨域请求。

例如,运行在 api.example-a.com 的 JavaScript 代码使用 XMLHttpRequest 来发起一个到 api.example-b.com/data.json 的请求。这由于域名的不同所以不同源,这就是一个跨域请求。

但是,有时候我们需要在不同源之间进行通信。为了解决这个问题,出现了一些解决跨域问题的方法,如JSONPCORS代理postMessage等。这些方法都是通过绕过浏览器的同源策略限制来实现跨域请求的。

  1. JSONP:JSONP是一种通过动态创建<script>标签来实现跨域请求的方法。它利用了<script>标签的src属性不受同源策略限制的特点,可以获取到其他域下的数据。
    原理:

    • 首先,在页面中定义一个回调函数,用来处理获取到的数据。
    • 然后,动态创建一个<script>标签,将其src属性指向目标服务器上的一个接口,并在URL中添加一个callback参数,用来指定回调函数的名称。
    • <script>标签被插入页面后,浏览器会自动发起一个GET请求,获取目标服务器上的数据。目标服务器在接收到请求后,会将数据包装在回调函数中返回。
    • 当数据返回到页面后,浏览器会自动执行回调函数,并将数据作为参数传入。这样,我们就可以在回调函数中处理获取到的数据了。

    示例:

    <!DOCTYPE html>
    <html>
    <head>
        <title>JSONP Example</title>
    </head>
    <body>
        <h1>JSONP Example</h1>
        <p id="output"></p>
        <script>
            // 定义回调函数
            function handleResponse(data) {
                // 在回调函数中处理获取到的数据
                document.getElementById('output').innerHTML = data.message;
            }
    
            // 动态创建<script>标签
            var script = document.createElement('script');
            // 设置src属性,指定回调函数的名称
            script.src = 'https://api.example.com/getData?callback=handleResponse';
            // 将<script>标签插入页面
            document.body.appendChild(script);
        </script>
    </body>
    </html>
    

    缺点:

    • 有安全风险,如果目标服务器返回数据中包含了恶意代码,那么这些代码将被执行。
    • JSONP只支持GET请求,不支持POST、PUT、DELETE等其他类型的HTTP请求。
    • JSONP 需要后端配合返回指定格式的数据。
    • 需要服务器端兼容这种跨域请求。
    • 不容易调试,如果返回错误浏览器不会返回具体的错误,只能在控制台中查看。
  2. CORS:CORS(Cross-Origin Resource Sharing,跨源资源共享)是一种基于HTTP头的机制,它允许服务器标识除了它自己以外的其他源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。服务器可以通过设置响应头中的Access-Control-Allow-Origin字段来指定哪些源可以访问它的资源。

  3. 代理:可以在服务器端设置一个代理,将前端发出的请求转发到目标服务器上,然后再将目标服务器返回的数据转发回前端。这样,前端就可以绕过浏览器的同源策略限制,实现跨域请求。

  4. postMessage:postMessage是HTML5中新增的一个API,它允许不同源之间的窗口进行通信。可以通过监听message事件来接收其他窗口发送过来的消息。

浏览器

从输入url到页面展示出来的整个过程

  1. 浏览器会检查缓存,如果请求的资源在缓存中并且新鲜,就会直接使用缓存中的资源。如果资源未缓存或缓存不够新鲜,浏览器会发起新请求。
  2. 浏览器会解析URL,获取协议、主机、端口和路径。
  3. 浏览器会通过DNS查询获取主机的IP地址。
  4. 浏览器会与目标IP地址和端口建立TCP连接。
  5. TCP连接建立后,浏览器会发送HTTP请求。
  6. 服务器接收到请求并进行处理,然后返回HTTP响应。
  7. 浏览器接收到HTTP响应,并根据情况选择关闭TCP连接或保留重用。
  8. 浏览器检查响应状态码,并根据资源类型决定如何处理。如果资源是HTML文档,浏览器会解析HTML文档,构建DOM树,下载资源,构建CSSOM树,执行js脚本等操作。

浏览器缓存机制

浏览器提供了多种缓存机制,包括HTTP缓存、Cookie、Web Storage(包括localStorage和sessionStorage)和IndexedDB等。

  • HTTP缓存: HTTP缓存是一种通过重复使用之前获取的资源来提高网站性能的机制。它通过设置HTTP响应头中的缓存控制字段来实现。
  • Cookie: Cookie是一种用于在客户端存储少量数据的机制。它通常用于保存用户的登录状态、偏好设置等信息。Cookie的大小有限制,通常不能超过4KB。
  • Web Storage: Web Storage包括localStoragesessionStorage两种类型。它们都提供了一种在客户端存储键值对数据的机制。localStorage和sessionStorage的区别在于,localStorage中存储的数据会持久保存在客户端,即使浏览器关闭也不会丢失;而sessionStorage中存储的数据只在当前会话期间有效,当浏览器关闭时会被清除。
  • IndexedDB: IndexedDB是一种在客户端存储大量结构化数据的机制。它提供了丰富的查询功能,并支持事务。
  • 此外,还有一种名为session的机制,它用于在服务器端存储用户会话信息。session与上述几种缓存机制不同,它不是在浏览器中实现的,而是在服务器端实现的。
Cookie、sessionStorage、localStorage 的区别
  • 生命周期:Cookie的生命周期可以通过设置过期时间来控制,过期后会被自动删除。sessionStorage中存储的数据只在当前会话期间有效,当浏览器关闭时会被清除。localStorage中存储的数据会持久保存在客户端,即使浏览器关闭也不会丢失。
  • 存储容量:Cookie的大小有限制,通常不能超过4KB。sessionStorage和localStorage的存储容量要大得多,一般可以达到5MB或更多。
  • 作用域:Cookie在同一个域名下是共享的,可以在不同页面之间共享数据。sessionStorage和localStorage的作用域是以窗口或标签页为单位的,它们只能在同一个窗口或标签页中共享数据。
  • 数据传输:Cookie会随着每次HTTP请求一起发送到服务器端,这会增加额外的网络流量。而sessionStorage和localStorage中存储的数据只存在于客户端,不会被发送到服务器端。

浏览器缓存

浏览器缓存(Browser Caching)是为了节约网络的资源加速浏览,浏览器在用户磁盘上对最近请求过的文档进行存储,当访问者再次请求这个页面时,浏览器就可以从本地磁盘显示文档,这样就可以加速页面的阅览。

通常浏览器缓存策略分为两种:强缓存(Expires,cache-control)和协商缓存(Last-modified ,Etag),并且缓存策略都是通过设置 HTTP Header 来实现的。

  • 强缓存是指在缓存期间不需要请求,state code为200。它可以通过Expires和Cache-Control来实现。Expires是HTTP/1.0的产物,表示资源的过期时间,受限于本地时间。如果修改了本地时间,可能会造成缓存失效。Cache-Control是HTTP/1.1的产物,用来控制资源在本地缓存的有效期。它的max-age属性可以指定资源的最大生命周期。
  • 协商缓存是指在强缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。其中协商缓存的标识也是在响应报文的HTTP头中和请求结果一起返回给浏览器的。它可以通过Last-Modified/If-Modified-Since和Etag/If-None-Match来实现。

当浏览器请求资源时,首先会检查资源的Expires和Cache-Control。如果命中强缓存,状态仍然返回200,但不会请求数据,在浏览器中能明显看到from cache字样。如果强缓存失效,则会携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。如果命中协商缓存,则返回304状态码,并且不会返回数据。

img

304协商缓存

协商缓存是一种服务端的缓存策略,即通过服务端来判断某件事情是不是可以被缓存。服务端判断客户端的资源,是否和服务端资源一致,如果一致则返回304,反之返回200和最新的资源。

当网页不是首次加载时,如果设置了强缓存,数据则会从缓存中读取,不请求服务端。如果强缓存时间过期,则会请求服务端,服务端判断是否命中协商缓存,如果协商缓存时间或者哈希没变,则返回304。如果协商缓存时间对比不一样或资源变化,则数据重新被获取,返回200。

进程、线程、协程

进程、线程和协程是计算机程序执行的三种不同方式。

  • 进程是操作系统分配资源和调度的基本单位,它拥有独立的内存空间和系统资源。一个进程可以包含多个线程,线程共享进程的资源。
  • 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。线程共享进程的内存空间和系统资源,但拥有独立的运行栈和程序计数器。
  • 协程是一种轻量级的线程,它避免了无意义的调度,由此可以提高性能。但也因此,程序员必须自己承担调度的责任。协程也失去了标准线程使用多CPU的能力。
进程和线程的区别与联系

进程和线程是两个密切相关但又不同的概念。

进程和线程之间的区别主要在于它们是不同的操作系统资源管理方式。

  1. 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响。
  2. 而线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间。
  3. 同一进程的所有线程共享该进程的所有资源,一个线程死掉就等于整个进程死掉。
  4. 一个线程只能属于一个进程,而一个进程可以有多个线程,且至少有一个线程。

网络攻击

网络攻击是指损害网络系统安全属性的危害行为,危害行为导致网络系统的机密性、完整性、可控性、真实性、抗抵赖性等受到不同程度的破坏。

常见的网络攻击类型包括:

  • 恶意软件:一种可以执行各种恶意任务的应用程序。
  • 网络钓鱼攻击:攻击者试图诱骗毫无戒心的受害者交出有价值的信息,例如密码、信用卡详细信息、知识产权等。
  • 中间人攻击(MITM):攻击者拦截两方之间的通信以试图监视受害者、窃取个人信息或凭据,或者可能以某种方式改变对话。
  • 分布式拒绝服务(DDoS)攻击:攻击者实质上用大量流量淹没目标服务器,以试图破坏甚至关闭目标。
  • SQL注入攻击:一种特定于 SQL 数据库的攻击类型。SQL 数据库使用 SQL 语句来查询数据,这些语句通常通过网页上的 HTML 表单执行。如果未正确设置数据库权限,攻击者可能会利用 HTML 表单执行查询,从而创建、读取、修改或删除存储在数据库中的数据。
  • 零日漏洞利用:网络犯罪分子获悉在某些广泛使用的软件应用程序和操作系统中发现的漏洞,然后将使用该软件的组织作为目标,以便在修复程序可用之前利用该漏洞。
  • 还有其他的例如:DNS隧道攻击、商业电子邮件攻击 (BEC) 和加密劫持等。

部分攻击的防御措施:

  • 防御网络攻击的方法有很多,具体取决于所面临的威胁类型。例如,防止恶意软件攻击需要安装最新最好的反恶意软件/垃圾邮件保护软件,确保员工接受过识别恶意电子邮件和网站的培训,拥有强大的密码策略,并尽可能使用多因素身份验证,为所有软件打补丁并保持最新,仅在绝对必要时才使用管理员账户,控制对系统和数据的访问,并严格遵守最小权限模型,监控网络是否存在恶意活动,包括可疑文件加密、入站/出站网络流量、性能问题等。
  • 防止网络钓鱼攻击需要员工接受过充分的培训,能够识别可疑的电子邮件、链接和网站,并且知道不要输入信息或从他们不信任的网站下载文件。下载任何可以帮助识别恶意网站的附加组件也是一个好主意。
  • 防止 MITM 攻击需要使用 VPN(虚拟专用网络),尤其是当从公共 Wi-Fi 热点连接时。当心虚假网站、侵入性弹出窗口和无效证书,并在每个 URL 的开头查找“HTTPS”。
  • 防止 DDoS 攻击需要使用下一代防火墙或入侵防御系统 (IPS) 将实时了解任何流量不一致、网络性能问题、间歇性网络崩溃等。将服务器放在不同的数据中心也是一个好主意,因为如果当前服务器发生故障,可以切换到另一台服务器。在许多方面,保护网络免受 DDoS 攻击的最佳方法是制定一个久经考验的响应计划,这将能够尽快让系统恢复在线并维持业务运营。
  • 防止 SQL 注入攻击,可以采用参数化语句并加强对用户输入的验证等。

其他

get和post的区别

GET和POST是两种HTTP请求方法,它们之间有一些区别。

  • GET方法用于从指定的资源请求数据。它将参数显示在URL上,例如:/test/demo_form.php?name1=value1&name2=value2。GET方法提交的数据量有限制,因为它是通过URL添加数据来发送的,而URL的长度是受限制的。GET方法只允许ASCII字符。此外,GET请求可被缓存、保留在浏览器历史记录中、收藏为书签。但是,GET请求不应在处理敏感数据时使用。
  • POST方法用于向指定的资源提交要被处理的数据。它通过表单提交不会显示在URL上,因此POST方法更具隐蔽性。POST方法可以传输大量的数据,对数据长度没有要求。POST方法没有限制,也允许二进制数据。此外,POST请求不会被缓存、不会保留在浏览器历史记录中、不能被收藏为书签。

http常见状态码

HTTP状态码用来表明特定HTTP请求是否成功完成。响应被归为以下五大类:

  • 信息响应 (100–199)
  • 成功响应 (200–299)
  • 重定向消息 (300–399)
  • 客户端错误响应 (400–499)
  • 服务端错误响应 (500–599)

一些常见的HTTP状态码包括:

  • 200 OK:请求成功。
  • 301 Moved Permanently:请求的资源的URL已永久更改。
  • 302 Found:请求的资源的URI已暂时更改。
  • 304 Not Modified:所请求的资源未修改,客户端可以继续使用相同的缓存版本的响应。
  • 400 Bad Request:客户端请求的语法错误,服务器无法理解。
  • 401 Unauthorized:请求要求用户的身份认证。
  • 403 Forbidden:客户端没有访问内容的权限。
  • 404 Not Found:服务器找不到请求的资源。
  • 500 Internal Server Error:服务器内部错误,无法完成请求。

CDN

CDN是Content Delivery Network的缩写,即内容分发网络。它的基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。

CDN的工作原理就是将源站的资源缓存到CDN各个节点上,当请求命中了某个节点的资源缓存时,立即返回客户端,避免每个请求的资源都通过源站获取,避免网络拥塞、缓解源站压力,保证用户访问资源的速度和体验。

简单来说,CDN通过在全球范围内部署大量节点服务器,将网站内容缓存在这些节点服务器上,当用户访问网站时,CDN会根据用户的地理位置和网络状况等因素,智能调度用户访问离其最近的节点服务器,从而加快网站访问速度、提高网站可用性。

主要作用:

  • 加快网站访问速度:通过将网站内容缓存在全球范围内的节点服务器上,CDN能够让用户就近访问所需内容,从而加快网站访问速度。
  • 提高网站可用性:CDN能够通过智能调度、负载均衡等技术,保证用户能够快速、稳定地访问网站,提高网站的可用性。
  • 缓解源站压力:CDN能够将大量用户请求分流到各个节点服务器上,从而减轻源站的压力,保证源站能够稳定运行。
  • 节省带宽成本:CDN能够通过缓存技术、数据压缩技术等手段,有效减少数据传输量,从而节省源站的带宽成本。