滴滴前端面试总结

滴滴前端开发面试总结

面试题目

1、js中的单线程和事件循环,宏任务和微任务

2、Js实现继承有哪几种方式?

3、Js 中apply(),call()和bind()的区别

4、从输入url到渲染页面

5、js 中的闭包及其使用场景

6、介绍一下Promise的状态及其方法

7、介绍一下async/await 的实现原理

8、箭头函数和普通函数有什么区别

9、什么是BFC?

10、什么是Css中的回流(重排)与重绘?

11、Css中移动端适配有哪些方案?

12、常用的跨域解决方案有哪些?

13、Vue2与Vue3中的双向数据绑定

14、Vue中template模版的编译原理

15、Vue2中的diff流程

16、Vue3中的diff流程

17、Vue中的组件间通信有哪些?

18、Vue-router中如何实现懒加载?

19、Vue3相对于Vue2进行了哪些优化?

20、React有哪些常用的hooks?

21、介绍下React中的useEffect

22、React中常用的高阶组件有哪些?

23、介绍一下React Fiber

24、React Hook为什么不能放到条件语句中?

25、Webpack中有哪些核心概念?

26、Vite 和 Webpack 的区别

27、Webpack常见的优化方案有哪些?

28、浏览器中强缓存与协商缓存的缓存机制

面试详解

1、js中的单线程和事件循环,宏任务和微任务

JS是单线程的,同一时间只能执行一个任务,如果执行的任务需要等待一段时间才能完成,那么就会导致程序阻塞,影响用户体验。

JavaScript 事件循环是一种执行模型,用于处理代码执行过程中的异步操作和回调函数。它负责管理 JavaScript 代码的执行顺序,使得异步操作能够以非阻塞的方式进行。

事件循环由一个主线程和一个任务队列组成。当 JavaScript 执行代码时,同步任务会立即执行,而遇到异步任务时,它们会被放入任务队列中等待执行。当主线程空闲时,事件循环会从任务队列中取出一个任务并执行。这个过程不断重复,即事件循环的运行机制。

宏任务(macrotask): setTimeout、setInterval、I/O 操作、事件等。

微任务(microtask): Promise 的回调函数、MutationObserver、Object.observe 等。

一般情况下,微任务会优先于宏任务执行。

当 JavaScript 执行到某个宏任务时,会先执行当前任务中的所有微任务,然后再执行下一个宏任务。换句话说,微任务会在当前宏任务执行完毕之前被处理。

2、Js实现继承有哪几种方式?

  1. 原型链继承:将父类的实例作为子类的原型,通过 prototype 进行继承
  2. 构造继承:将父类的实例属性复制给子类,通过 call 进行继承
  3. 实例继承:为父类实例添加新特性,作为子类实例返回
  4. 拷贝继承:将父类实例通过循环拷贝给子类
  5. 组合继承:就是 原型链继承 和 构造继承,一起使用
  6. 寄生组合继承:通过寄生方式,砍掉父类的实例属性,避免了 组合继承中,在调用两次父类的构造时,初始化两次实例方法/属性 的缺点

3、Js 中apply(),call()和bind()的区别

都可以用来改变函数内部的 this 指向

  • call() 和 apply() 是立即调用函数,并改变函数的执行上下文。
  • call() 的参数是逐个传入,而 apply() 的参数是以数组形式传入。
  • bind() 创建一个新函数,不会立即执行,可以稍后调用。

4、从输入url到渲染页面

  1. 户在浏览器中输入 URL 地址或点击链接,触发请求的发送
  2. DNS 解析:浏览器会解析 URL 中的域名部分,以获取对应的 IP 地址。
  3. 建立 TCP 连接:浏览器通过 TCP 协议与服务器建立连接
  4. 发送 HTTP 请求:浏览器根据用户请求的方法(GET、POST 等)和请求头信息构建 HTTP 请求报文。
  5. 服务器处理请求:服务器接收到请求后,根据请求的 URL 和参数等进行处理。
  6. 服务器发送 HTTP 响应:服务器生成 HTTP 响应报文,发送回客户端
  7. 客户端接收响应:浏览器接收到服务器发送的 HTTP 响应报文。
  8. 浏览器渲染页面:如果响应的内容是 HTML 页面,浏览器会解析 HTML,并构建 DOM 树。同时,浏览器还会解析 CSS 样式和 JavaScript 脚本,并进行相应的处理。最终,浏览器将解析后的内容渲染成可视化的页面。

5、js 中的闭包及其使用场景

闭包是指在一个函数内部定义的另一个函数,这个内部函数可以访问到其外部函数中的变量和参数,即使外部函数已经执行完毕并返回了,内部函数仍然可以保留对这些变量和参数的引用,形成了一个“闭合”的作用域,因此称为闭包。

简单的来说:闭包是指有权访问另外一个函数作用域中的变量的函数

应用场景:

  • 保护变量:可以用闭包来保护变量不被意外修改。
  • 封装私有变量和方法
  • 延迟执行:可以实现防抖节流

6、介绍一下Promise的状态及其方法

Promise 是异步编程的一种解决方案

promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。

  • then(onFulfilled, onRejected):用于指定当异步操作成功时(Fulfilled 状态)和失败时(Rejected 状态)所执行的回调函数。可以通过链式调用多个 then 方法来处理异步操作的结果。
  • catch(onRejected):用于指定当异步操作失败时(Rejected 状态)所执行的回调函数。通常用于捕获异常情况。
  • finally(onFinally):无论 Promise 对象最终状态如何(Fulfilled 或 Rejected),都会执行指定的回调函数。通常用于无论成功还是失败都需要执行一些清理工作。
  • Promise.all(iterable):接收一个可迭代对象(比如数组),当所有 Promise 对象都变为 Fulfilled 或其中之一变为 Rejected 后,返回一个新的 Promise 对象。结果是包含多个异步任务结果的数组
  • Promise.race(iterable):接收一个可迭代对象,返回一个 Promise 对象,一旦迭代器中的某个 Promise 对象变为 Fulfilled 或 Rejected,返回的 Promise 对象就会采用这个 Promise 的状态和值。

7、介绍一下async/await 的实现原理

async/await 是一种处理异步操作的语法糖,它让异步代码看起来更像同步代码,更易于理解和编写。实现原理:

  • 在底层,async/await 实际上是基于 Promise 实现的。
  • 当遇到 await 关键字时,JavaScript 引擎会暂停当前 async 函数的执行,并注册一个微任务(microtask)。
  • 等待 await 后的 Promise 对象状态变化后,微任务队列中的任务会被执行,继续执行 async 函数后面的代码。
  • 在实际执行时,async/await 可以理解为 Generator 函数和 Promise 的结合,通过 Generator 的暂停和恢复特性,实现了暂停和继续执行异步操作的能力。

8、箭头函数和普通函数有什么区别

  • 写法不同:箭头函数使用箭头(=>)来定义,而普通函数使用 function 关键字定义
  • this 的处理方式不同:在箭头函数中,this 的值与外层作用域的 this 绑定。而在普通函数中,this 的值由调用该函数的方式决定。
  • 箭头函数没有 arguments 对象:箭头函数中没有自己的 arguments 对象,它的参数只能通过参数列表来传递。
  • 箭头函数不能用作构造函数:由于箭头函数中没有自己的 this 值,因此不能用作构造函数来创建对象实例。

9、什么是BFC?

BFC(块级格式化上下文)它是页面中一个独立的渲染区域,拥有自己的布局规则。BFC具有一些特性,例如浮动元素不会覆盖BFC区域,BFC可以包含浮动元素,BFC可以阻止垂直外边距重叠等。

有几种方式可以触发一个元素的BFC,实现方法如下:

  1. 设置浮动(float):将元素设置为浮动,例如将其float属性设置为left或right,这会触发元素的BFC。
  2. 设置定位(position):将元素的position属性设置为absolute或fixed
  3. 设置overflow属性:将元素的overflow属性设置为非visible的值,如auto、hidden、scroll
  4. 设置display属性为inline-block、table-cell、table-caption或inline-flex
  5. 使用块级格式化上下文的根元素:HTML文档中的根元素(通常是html或body元素)本身就是一个BFC。

10、什么是css中的回流(重排)与重绘?

回流指的是当页面的布局和几何属性发生变化时,浏览器会重新计算元素的位置和大小,然后更新页面的布局。回流会影响到整个页面的渲染,并且比较消耗性能。常见引起回流的操作包括改变窗口大小、修改元素的尺寸、添加或删除元素等。

重绘指的是当页面的外观属性(如颜色、背景等)发生变化时,浏览器会重新绘制受影响的部分,但不会重新计算位置和大小。重绘的开销比回流小很多,因为它只需要重新绘制元素的外观,而不需要重新计算布局。

11、css中移动端适配有哪些方案?

  • 媒体查询(Media Queries)
  • rem布局:rem是指相对于根元素(html)字体大小的单位,可以根据根元素的字体大小来确定其他元素的大小
  • vw/vh布局:vw/vh是指相对于视口宽度/高度的单位,可以根据视口的大小来确定元素的大小。

12、常用的跨域解决方案有哪些?

跨域:浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

  • CORS: 全称是跨域资源共享,是一种 ajax 跨域请求资源的方式,支持现代浏览器,支持IE10以上。当你使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin(访问控制允许来源); 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
  • JSOP: JSONP是通过script 标签加载数据的方式去获取数据当做 JS代码来执行 提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后在原始数据上「包裹」这个函数名,发送给前端。换句话说,JSONP需要对应接口的后端的配合才能实现。
  • Proxy:在前端应用内部建立一个代理服务器,将请求发送到该服务器上,再由该服务器转发请求到后端,最后将响应结果返回给前端。虽然代理可以解决跨域问题,但是会增加服务器负担,因此需要合理使用。

13、Vue2与Vue3中的双向数据绑定

当数据传入vue的实例中作为data数据时,vue将遍历此对象的所有property,并且使用Object.defineProperty把他们转化为getter和setter方法,而get和set正是对属性的读写进行监控

Vue 2.x能够监听数据对象的变化,但是监听不到对象属性的增删、数组元素和长度的变化;Vue 3.x 采用了 Proxy 换掉了 Vue 2.x 中的 Object.defineProperty 实现双向绑定

14、Vue中template模版的编译原理

Vue 中的模板编译原理可以简单概括为将模板字符串转换成渲染函数(render function),这个过程涉及到以下几个步骤:

  1. 解析模板:Vue 编译器会先对模板进行解析,将模板字符串转换成抽象语法树(AST)的形式。
  2. 静态分析:在静态分析阶段,Vue 会识别模板中的指令、插值表达式、事件处理等,并建立相应的 AST 节点。
  3. 优化:Vue 会对生成的 AST 进行优化,包括静态节点提升、标记静态根节点等优化操作,以提高渲染性能。
  4. 生成渲染函数:最终,Vue 将优化后的 AST 转换成渲染函数,这个渲染函数接收一个 createElement 函数作为参数,用于创建 VNode(虚拟 DOM 节点)。
  5. 执行渲染函数:当组件需要渲染时,会执行生成的渲染函数,通过 createElement 创建 VNode,并最终渲染成真实的 DOM 元素。

总的来说,Vue 的模板编译原理将模板字符串转换成渲染函数,通过渲染函数的执行来生成虚拟 DOM,并最终更新到真实的 DOM 上,实现数据驱动视图的更新。这个过程大大简化了开发者编写组件的工作,同时也提高了 Vue 应用的性能和效率。

15、Vue2中的diff流程

在更新视图时,通过比较新旧虚拟 DOM 树的差异,找出最小的变更,并将这些变更应用到实际的 DOM 中,以实现视图的高效更新

  1. 生成新的虚拟 DOM 树:当数据发生变化时,Vue 会重新渲染组件,生成新的虚拟 DOM 树。
  2. 比较新旧虚拟 DOM 树:Vue 会将新的虚拟 DOM 树和旧的虚拟 DOM 树进行比较,找出两者之间的差异。
  3. Diff 算法:Vue 使用了一种基于深度优先搜索的算法来进行 Virtual DOM 的差异比较。在比较过程中,Vue 会尽量复用已存在的节点,减少对实际 DOM 的操作,从而提高性能。
  4. 生成变更记录:在比较过程中,Vue 会生成一份变更记录,记录需要对实际 DOM 进行的操作,包括插入、移动、更新和删除等操作。
  5. 应用变更:最后,Vue 会根据变更记录逐条对实际 DOM 进行操作,将变更应用到实际 DOM 上,完成视图的更新。

16、Vue3中的diff流程

Vue 3 中的 diff 流程与 Vue 2 中有所不同,主要是因为 Vue 3 引入了新的响应式系统和编译器优化。

  1. 编译器优化:在编译期间,Vue 3 的编译器会对模板进行静态分析,并将静态节点提取出来,生成标记静态根节点的渲染函数。这样可以减少渲染函数的生成和执行次数,提高渲染性能。
  2. 响应式更新:当数据发生变化时,Vue 3 的响应式系统会立即触发组件的重新渲染。
  3. 生成新的虚拟 DOM 树:重新渲染组件时,Vue 3 会生成新的虚拟 DOM 树。
  4. 比较新旧虚拟 DOM 树:Vue 3 会将新的虚拟 DOM 树和旧的虚拟 DOM 树进行比较,找出两者之间的差异。
  5. Diff 算法:Vue 3 中使用了一种名为“递归分裂算法”的 diff 算法,它通过将新旧节点的子节点按照一定规则分成多个小区间,然后进行比较和更新,从而减少了无意义的比较,提高了 diff 的效率。
  6. 生成变更记录:在比较过程中,Vue 3 会生成一份变更记录,记录需要对实际 DOM 进行的操作,包括插入、移动、更新和删除等操作。
  7. 应用变更:最后,Vue 3 会根据变更记录逐条对实际 DOM 进行操作,将变更应用到实际 DOM 上,完成视图的更新。

Vue 3 中的 Virtual DOM diff 流程借助编译器优化和新的递归分裂算法,提高了渲染性能和效率,同时保证了视图的正确性。这个过程减少了无意义的比较,提高了 diff 的效率,从而实现了性能优化和视图的高效更新。

17、Vue中的组件间通信有哪些?

Vue 组件间通信有以下几种方式:

  • 父子组件通信:父组件通过props将数据传递给子组件,子组件通过$emit触发自定义事件回传数据
  • 子父组件通信:子组件通过this.parent访问父组件实例,或通过emit触发自定义事件回传数据
  • 兄弟组件通信:通过一个事件总线(Event Bus)或者Vuex来实现,Event Bus 就是通过一个新的 Vue 实例来实现数据传输
  • 跨级组件通信:通过provide/inject来实现,provide可以在祖先级别中注册一个变量,inject可以在子孙级别中注入

18、Vue-router中如何实现懒加载?

在路由配置文件中使用动态导入import()语句,并用箭头函数返回实现路由懒加载。

const routes = [  {    path: '/home',    name: 'Home',    component: () => import('./views/Home.vue')  },  {    path: '/about',    name: 'About',    component: () => import('./views/About.vue')  }];const router = new VueRouter({  routes});

19、Vue3相对于Vue2进行了哪些优化?

  • Vue 3 引入了 Composition API,这是一种基于函数的 API 风格,使得代码组织更加灵活和可复用。相比于 Vue 2 的 Options API,Composition API 更适合大型项目和复杂组件的开发。
  • 性能优化:Vue 3 在编译器、响应式系统和虚拟 DOM 等方面进行了优化,提高了整体性能。具体来说,Vue 3 引入了编译器优化、树懒执行、静态提升、模块化的运行时,以及更快的虚拟 DOM 渲染等功能,从而使应用程序更加高效。
  • 更灵活的响应式系统:Vue 2.x 中响应式系统的核心是 Object.defineProperty,劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter和setter,实现响应式。Vue 3.x 中使用 Proxy对象重写响应式系统。
  • 更快的渲染速度:Vue3 的编译器生成的渲染函数比 Vue2 生成的更高效。
  • 编译阶段:Vue 2.x 通过标记静态节点,优化 diff 的过程。Vue 3.x中标记和提升所有的静态节点,diff的时候只需要对比动态节点内容。
  • 更小的体积:Vue3 将源码拆分为多个独立的模块,这样就可以按需导入所需的模块,从而减小了整个库的体积。
  • 更好的 TypeScript 支持:Vue3 对 TypeScript 的支持更加友好,内部使用了更先进的 TypeScript 特性,并为其提供了更好的声明文件。
  • 更好的组件系统:比如,Vue3中引入了一个新的 Fragment 组件,它可以替代原来的 template 标签作为根节点

20、React有哪些常用的hooks?

  • useState:通过 useState,可以创建一个状态变量及其更新函数,并在组件内使用该变量来保存和更新组件的状态。
  • useEffect:用于在组件渲染完成后执行一些副作用操作(例如订阅数据、更新 DOM 等)。通过 useEffect,可以在组件加载、更新和卸载时设置和清理副作用操作,并且可以在副作用操作之间共享状态。
  • useContext:用于在组件之间共享一些全局的状态或函数,以避免通过多层嵌套的 Props 传递进行数据传输。通过 useContext,可以让组件在全局状态或函数的上下文中运行,并让它们能够方便地读取或更新全局状态或函数。
  • useReducer:通过 useReducer,可以创建一个状态容器及其更新函数,并在组件内使用该容器来保存和更新组件的状态。
  • useMemo:用于在组件渲染完成后缓存一些计算结果,以避免因为重复计算导致的性能问题。通过 useMemo,可以创建一个缓存变量,并在组件内使用该变量来保存计算结果并缓存。
  • useCallback:用于在组件渲染完成后,将一些函数进行缓存,以避免因函数重复创建导致的性能问题。通过 useCallback,可以创建一个缓存函数,并在组件内使用该函数来代替重复创建的函数。
  • useRef:用于在组件渲染完成后创建一个引用,以便在组件多次渲染时能够保留上一次渲染中的值。通过 useRef,可以创建一个引用变量,并在组件内使用该变量来保存一些持久化的数据。
  • useImperativeHandle:用于在组件中实现一些自定义的 Ref 对象,并且要求将一些组件内部的方法或状态暴露给父组件使用。通过 useImperativeHandle,可以创建一个自定义的 Ref 对象,并在组件内指定一些公开的方法或属性。
  • useLayoutEffect:该 Hook 与 useEffect 类似,但它会在浏览器渲染更新之前同步执行副作用操作,以确保 React 组件与浏览器同步更新。通常情况下,应该使用 useEffect,但在需要直接操作 DOM 元素或进行测量布局界面时,应当使用 useLayoutEffect。
  • useDebugValue:该 Hook 可以帮助开发者在调试工具中显示额外的信息,以便更好地理解 Hook 的使用和行为。通常情况下,这个 Hook 只用于调试过程中,而不是实际的应用程序代码中。

21、介绍下React中的useEffect

useEffect 的作用是在每次渲染后执行一些副作用操作,比如访问 DOM 元素、发送网络请求、设置定时器等。它接收两个参数:一个函数和一个可选的依赖数组。

  • 函数参数表示需要执行的副作用操作。该函数会在第一次渲染后和每次更新后执行。如果希望在组件卸载时执行某些清理操作,可以在该函数中返回一个清理函数。
  • 依赖数组参数是一个可选的数组,用于指定需要监视的变量。只有当依赖数组中的变量发生变化时,useEffect 才会重新执行。如果不传递依赖数组,则每次组件更新时都会执行该函数。

22、React中常用的高阶组件有哪些?

高阶组件可以用来复用组件逻辑、增强组件功能或者封装共享的代码。 以下是一些常用的高阶组件:

  • withRouter:withRouter 是 React Router 提供的高阶组件,用于将 history、location 和 match 对象传递给组件。这样可以让非路由组件也能获取路由信息。
  • connect(Redux):connect 是 React Redux 提供的高阶组件,用于连接 Redux 的 store 到 React 组件。通过 connect,组件可以访问 Redux store 中的状态和 dispatch 函数。
  • memo:memo 是 React 提供的用于性能优化的高阶组件。它可以缓存组件的渲染结果,只有在 props 发生变化时才会重新渲染组件。
  • forwardRef:forwardRef 是 React 提供的高阶组件,用于向子组件传递 ref。通常用于需要访问子组件实例的情况。
  • Provider(Context API):Provider 是 React Context API 提供的高阶组件,用于在组件树中向下传递数据。通过 Provider,可以在应用中使用全局的状态。
  • withStyles(Material-UI):withStyles 是 Material-UI 提供的高阶组件,用于处理组件样式。它可以将样式对象转换为 CSS 类名,并注入到组件中。
  • compose:compose 是 Redux 提供的高阶函数,用于组合多个高阶组件。通过 compose,可以将多个高阶组件串联起来,简化组件的嵌套。

23、介绍一下React Fiber

React Fiber是React框架中一种新的协调引擎,旨在改善渲染性能和用户体验。它通过引入优先级调度、增量渲染和可中断的工作单元等机制,将渲染任务分解成小的可中断的单元,从而使React能够更好地处理大型应用程序和高优先级任务,提供流畅且响应迅速的用户界面。

24、React Hook为什么不能放到条件语句中?

React 需要依赖 Hook 的调用顺序来正确地管理组件的状态。将 Hook 放在条件语句中可能导致 Hook 的调用顺序发生变化,从而破坏 React 对 Hook 调用顺序的依赖,引发一些潜在的问题。

如果将 Hook 放在条件语句中,那么在条件满足或不满足的情况下,Hook 的调用顺序可能发生变化,这将导致 React 无法准确地追踪每个 Hook 的状态变化,可能会导致组件状态错乱、重复渲染等问题。

将 Hook 的调用放在函数组件的最顶层,而不是嵌套在条件语句、循环中。这样可以确保每次渲染时 Hook 的调用顺序保持一致,帮助 React 正确地管理组件状态,保证组件的行为和预期一致。

25、Webpack中有哪些核心概念?

  • Entry(入口):Webpack在打包时需要从哪个文件开始构建依赖关系图,就是入口。可以设置多个入口文件,以生成多个输出文件。
  • Output(输出):打包后的文件放在哪里,以及如何命名这些文件。可以指定输出目录、文件名、公共路径等。
  • Loader(模块加载器):Webpack只能处理JavaScript文件,而其他类型的文件如CSS、图片等需要通过Loader转换才能被Webpack处理。Loader用于对模块内容进行转换处理。
  • Plugin(插件):Plugin可以用于执行各种任务,例如打包优化、错误处理和环境变量注入等。Webpack本身只提供了一些基本的Plugin,但社区中有很多第三方Plugin可供使用。
  • Mode(模式):Webpack提供了三种模式:development、production和none。不同的模式会启用不同的Webpack内置Plugin和Loader,以便于开发和生产环境的优化。
  • Chunk(代码块):Webpack在打包时会把所有相关联的模块组成一个Chunk。可以通过Code Splitting技术将代码拆分成多个Chunk,以实现按需加载。
  • Module(模块):Webpack把每个文件都看作一个模块,它可以是JavaScript、CSS、图片等。这些模块通过依赖关系进行组合,构成整个应用程序。

26、Vite 和 Webpack 的区别

  • 打包速度:Vite 的打包速度比 Webpack 更快。Vite 利用了浏览器原生 ES 模块的特性,在开发模式下无需将代码打包成一个文件,而是通过浏览器直接引入模块,从而大大提高了打包速度。
  • 开发体验:Vite 支持热更新,可以在修改代码后快速更新浏览器中的页面。同时 Vite 提供了可视化的构建信息和源码调试功能,可以帮助开发者更好地理解代码的运行情况。
  • 插件生态:Webpack 生态更加成熟,拥有更多的插件和 loader。但是 Vite 也支持大部分 Webpack 的插件和 loader,而且 Vite 本身已经集成了常用的功能,因此在某些场景下,使用 Vite 可以减少依赖和配置文件的数量,简化项目结构。
  • 构建目标:Webpack 可以构建多种类型的项目,包括 Web 应用、Node.js 应用、桌面应用等。而 Vite 更加专注于 Web 应用的构建。

27、Webpack常见的优化方案有哪些?

  • 代码分割(Code Splitting):通过代码分割,将代码拆分成多个小块,按需加载,可以减少首次加载时间,提高页面加载速度。可以使用 Webpack 的内置工具如 SplitChunksPlugin 来实现代码分割。
  • 懒加载(Lazy Loading):只在需要时再加载特定的模块,而不是一次性加载所有模块。可以通过动态 import 或使用 React.lazy、Vue异步组件等技术来实现懒加载。
  • Tree Shaking:通过去除未使用的代码,减少打包后的文件大小。可以通过配置 Webpack 的 mode 为 production 来启用 Tree Shaking 功能。
  • 缓存(Caching):利用浏览器缓存机制,避免重复加载已经加载过的资源,减少请求次数,提高页面加载速度。可以使用 Webpack 的 [contenthash] 或 [chunkhash] 来生成文件名,实现缓存控制。
  • 多进程打包:通过 Webpack 多进程打包,加快打包速度。可以使用 thread-loader 或 HappyPack 等插件来实现多进程打包。
  • 优化图片资源:对图片资源进行压缩、转换或使用 url-loader、file-loader 等加载器将小图片转成 base64 格式,减少请求次数和文件大小。
  • 优化字体文件:对字体文件进行压缩,将其转换为 base64 格式或使用 CDN 加载,减少文件大小和请求次数。
  • 代码压缩:使用 Webpack 插件如 terser-webpack-plugin 对代码进行压缩,减少文件大小,提高页面加载速度。

28、浏览器中强缓存与协商缓存的缓存机制

  • 强缓存通过设置响应头中的Cache-Control或Expires字段,告诉浏览器在一定时间内直接使用本地缓存,不需要发送请求到服务器。只有当缓存过期或被清除时,浏览器才会发送请求到服务器获取新的资源。
  • 协商缓存通过设置响应头中的ETag和Last-Modified字段,浏览器在每次请求时携带If-None-Match和If-Modified-Since字段,与服务器进行比较。如果资源未发生变化,则服务器返回304 Not Modified状态码,并告知浏览器继续使用缓存;如果资源发生变化,则服务器返回新的资源。

强缓存是基于时间的缓存控制,而协商缓存则是通过与服务器进行交互来判断是否使用缓存,更加灵活。

全部评论
我滴妈,对React和Vue都要这么了解才行吗
1 回复 分享
发布于 10-11 19:33 上海
佬儿,有手撕吗
点赞 回复 分享
发布于 10-15 23:21 湖北

相关推荐

13 52 评论
分享
牛客网
牛客企业服务