Skip to content

[toc]

1. 浏览器缓存机制有哪些?

  • HTTP 缓存(Expires 和 Cache-Control)

    • Expires:HTTP/1.0 的头部,用于指定资源到期的时间。浏览器将不会请求过期时间之前修改过的资源。
    • Cache-Control:HTTP/1.1 的头部,提供了更灵活的控制方式,如 max-ageno-cacheno-storepublicprivate 等指令。
  • ETag(Entity Tag)

    • 服务器通过 ETag 头部提供一个资源的唯一标识符。浏览器在后续的请求中会通过 If-None-Match 请求头部将这个标识符发送回服务器。如果 ETag 没有改变,服务器返回 304 Not Modified,告诉浏览器可以使用缓存中的版本。
  • Last-Modified 和 If-Modified-Since

    • 服务器通过 Last-Modified 头部提供资源的最后修改时间。浏览器在后续请求中通过 If-Modified-Since 请求头部发送这个时间戳。如果资源未被修改,服务器返回 304 Not Modified
  • 强缓存:利用 ExpiresCache-Control 头部实现,命中后直接从缓存读取,避免请求发到服务器。

  • 协商缓存:利用 Last-ModifiedETag 头部字段,缓存过期后由客户端向服务器验证资源是否更新,未更新则继续使用缓存。

2. 讲一下React虚拟DOM

React 的虚拟 DOM 是对真实 DOM 的抽象表示。通过虚拟 DOM,可以在内存中对 DOM 进行快速更新,然后将差异(diff)应用到实际的 DOM 上,减少直接操作 DOM 的性能开销,提高渲染效率。

3. 讲一下React的diff算法

React 的 diff 算法主要用于比较两棵虚拟 DOM 树的差异。算法假设同一层级下的元素类型相同,逐层比较节点,采用分而治之的策略,(dfs深搜)大大减少了复杂度。对于列表类型的组件,通过 key 属性来识别节点,避免不必要的重渲染。

4. React有哪些Hooks?

  • useState:用于在函数组件中添加状态。
  • useEffect:用于处理副作用(如数据获取、订阅等)。
  • useContext:用于在组件树中传递和接收上下文数据。
  • useReducer:用于复杂的状态逻辑处理。
  • useMemo:用于性能优化,避免不必要的计算。
  • useCallback:用于性能优化,避免不必要的函数重新创建。
  • useRef:用于获取 DOM 节点或保存任意变量的引用。
  • useImperativeHandle:定制 useRef 暴露给父组件的实例值。
  • useLayoutEffect:与 useEffect 类似,但它会在所有 DOM 变更之后同步触发。
  • useDebugValue:用于自定义 Hook 在 React 开发者工具中的标签。

5. React Hooks和高阶组件有什么区别?

  • React Hooks:允许在函数组件中使用状态和其他 React 特性,代码更加简洁和模块化,不会增加组件嵌套的复杂度。
  • 高阶组件(HOC):是一种模式,用于重用组件逻辑,通过将一个组件传递给高阶组件,返回一个增强版组件。它增加了组件嵌套的复杂度,可能导致“Wrapper Hell”。

6. 高阶组件有哪些?

常见的高阶组件包括:

  • withRouter:将路由相关的 props 注入到组件中。
  • connect:在 React-Redux 中使用,将 Redux 状态和操作注入到组件中。
  • withAuth:自定义的高阶组件,通常用于鉴权,限制访问权限。

7. ES6 map和weakmap的区别

    • 键值对集合,键可以是任意类型(对象、原始值)。
    • 强引用,键不会被垃圾回收。
  • WeakMap
    • 键必须是对象,值可以是任意类型。
    • 弱引用,键可以被垃圾回收,因此更适合存储临时对象。

WeakMap 的关键特性是它对键的弱引用,适用于存储那些与对象相关但不需要强引用的值,这样可以有效避免内存泄漏,特别适合在缓存、DOM 操作和隐藏私有数据等场景中使用。

8. Vite vs Webpack 深入对比

Webpack 设计原理与特点

  • 模块打包:Webpack 是一个模块打包工具,可以处理 JavaScript、CSS、图片等多种资源文件,并将其打包成一个或多个 bundle 文件,减少 HTTP 请求数,提升页面加载性能。
  • 依赖图:Webpack 构建项目时,会从入口文件开始,递归地解析所有依赖,生成一个依赖图(Dependency Graph),并根据图中的关系进行打包。
  • 多功能插件:Webpack 提供了强大的插件系统,几乎可以拦截打包过程中的每一个环节,开发者可以通过插件扩展 Webpack 的功能,如代码压缩、热模块替换(HMR)、静态资源优化等。
  • 灵活配置:Webpack 的配置文件 webpack.config.js 允许用户进行高度定制,可以根据项目需求配置各种打包策略。
  • 慢启动,快构建:由于 Webpack 需要分析整个依赖图,因此在大型项目中,初次构建时间可能较长,但随着增量构建和持久缓存策略的引入,后续的构建速度会显著加快。

Vite 设计原理与特点

  • ES Modules 原生支持:Vite 采用浏览器原生支持的 ES Modules 进行开发阶段的模块加载,不需要对所有文件进行打包,避免了 Webpack 的繁重构建过程。
  • 极速启动:Vite 只在需要时按需编译文件,因此启动速度极快,特别适合大型项目的开发环境。
  • 基于 Rollup 打包:在生产环境中,Vite 通过 Rollup 进行打包,生成优化后的静态文件。Rollup 专注于高效打包和代码拆分,生成的包体积更小。
  • 内置优化:Vite 内置了许多优化策略,如依赖预构建、按需加载、模块热替换(HMR)等,开发体验流畅。
  • 插件系统:Vite 也支持插件,插件基于 Rollup 实现,可以与 Rollup 生态中的许多插件共享。

对比总结

  • 启动速度:Vite 的启动速度远快于 Webpack,特别是在开发阶段,Vite 的体验更加流畅。
  • 打包方式:Webpack 是一切皆模块的打包工具,而 Vite 更依赖于浏览器原生的模块系统,生产环境则借助 Rollup 打包,二者在打包策略上有本质区别。
  • 复杂度:Webpack 提供了更为复杂和全面的配置能力,适用于复杂的企业级项目;Vite 则更注重简洁性和开发效率,适合快速开发。
  • 生态系统:Webpack 拥有广泛的插件和 loader 生态,能处理几乎所有前端开发需求;Vite 则借助 Rollup 插件系统,并逐步形成自己的生态。