【每日前端面经】2024-03-14

【每日前端面经】2024-03-14

欢迎订阅我的前端面经专栏: 每日前端面经

本期题目来源: 牛客

vite 为什么比 webpack 更快

  • 开发模式:Webpack 是先打包再启动开发服务器,而 Vite 则是直接启动,然后再按需编译依赖文件
    • 使用 Webpack 时,所有的模块都需要在开发前进行打包,这会增加启动时间和构建时间
    • 而 Vite 则采用了不同的策略,它会在请求模块时再进行实时编译,这种按需动态编译的模式极大地缩短了编译时间,特别是在大型项目中,文件数量众多,Vite 的优势更为明显
  • ESM:现代浏览器本身就支持 ES Modules,会主动发起请求去获取所需文件。Vite充分利用了这一点,将开发环境下的模块文件直接作为浏览器要执行的文件,而不是像 Webpack 那样先打包,再交给浏览器执行
  • 底层原理:Webpack 是基于 Node.js 构建的,而 Vite 则是基于 esbuild 进行预构建依赖。esbuild 是采用 Go 语言编写的,Go 语言是纳秒级别的,而 Node.js 是毫秒级别的。因此,Vite 在打包速度上相比Webpack 有 10-100 倍的提升
  • 热更新
    • 在 Webpack 中,当一个模块或其依赖的模块内容改变时,需要重新编译这些模块
    • 而在 Vite 中,当某个模块内容改变时,只需要让浏览器重新请求该模块即可,这大大减少了热更新的时间

http 协议中 content-type 常用类型

  • 常见的媒体格式类型如下:
    • text/html : HTML格式
    • text/plain :纯文本格式
    • text/xml : XML格式
    • image/gif :gif图片格式
    • image/jpeg :jpg图片格式
    • image/png:png图片格式
  • 以application开头的媒体格式类型:
    • application/xhtml+xml :XHTML格式
    • application/xml: XML数据格式
    • application/atom+xml :Atom XML聚合格式
    • application/json: JSON数据格式
    • application/pdf:pdf格式
    • application/msword : Word文档格式
    • application/octet-stream : 二进制流数据(如常见的文件下载)
    • application/x-www-form-urlencoded : <form encType="">中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
  • 上传文件:
    • multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

浏览器缓存

  1. 浏览器发送请求前,根据请求头的 expires 和 cache-control 判断是否命中(包括是否过期)强缓存策略,如果命中,直接从缓存获取资源,并不会发送请求。如果没有命中,则进入下一步
  2. 没有命中强缓存规则,浏览器会发送请求,根据请求头的 last-modified 和 etag 判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步
  3. 如果前两步都没有命中,则直接从服务端获取资源。

http 状态码

  • 信息响应(100-199)
    • 100
    • 101
    • 102
    • 103
  • 成功响应(200-299)
    • 200: 请求成功
    • 201
    • 202
    • 203
    • 205
    • 206
    • 207
    • 208
    • 226
  • 重定向响应(300-399)
    • 300
    • 301
    • 302
    • 303
    • 304: 响应没有被修改,继续使用缓存
    • 307
    • 308
  • 客户端错误响应(400-499)
    • 400
    • 401
    • 402
    • 403: 没有访问权限
    • 404: 找不到请求的资源
    • 405: 目标不支持请求方法
    • 406
    • ...
  • 服务端错误响应(500-599)

electron 有哪些部分

  • net 模块: 实现了主机解析,cookies,网络改变探测,SSL,资源缓存,ftp,HTTP, OCSP实现,代理 (SOCKS和HTTP) 配置,解析,脚本获取(包括各种不同系统下实现),QUIC,socket池,SPDY,WebSockets等等
  • v8 模块: 包括字节码解析器,JIT 编译器,多代GC,inspector (调试支持),内存和 CPU 的 profiler(性能统计),WebAssembly 支持,两种 post-mortem diagnostics 的支持,启动快照,代码缓存、代码热点分析等等
  • Skia 模块: 用点画出各种图。然而里面包括十几种矢量的绘制,文字绘制、GPU加速、矢量的指令录制以及回放(还要能支持线程安全)、各种图像格式的编解码、GPU渲染优化等等
  • Blink 内核
  • 还有音视频相关、沙箱、插件、UI等等

服务端渲染的原理

SSR 是 Server Side Render 简称;页面上的内容是通过服务端渲染生成的,浏览器直接显示服务端返回的html就可以了

  • 更快的首屏加载:这一点在慢网速或者运行缓慢的设备上尤为重要。服务端渲染的 HTML 无需等到所有的 JavaScript 都下载并执行完成之后才显示,所以你的用户将会更快地看到完整渲染的页面。除此之外,数据获取过程在首次访问时在服务端完成,相比于从客户端获取,可能有更快的数据库连接。这通常可以带来更高的核心 Web 指标评分、更好的用户体验,而对于那些"首屏加载速度与转化率直接相关"的应用来说,这点可能至关重要
  • 同一的心智模型:你可以使用相同的语言以及相同的声明式、面向组件的心智模型来开发整个应用,而不需要在后端模板系统和前端框架之间来回切换
  • 更好的 SEO:搜索引擎爬虫可以直接看到完全渲染的页面

懒加载

懒加载,即延迟加载 Lazyload。简单来说就是一个长页面中需要展示很多图像的时候,如果在进入页面的时候一次性把所有图片加载完,需要很长的时间。为了提升用户体验,我们使用懒加载,当图片出现在浏览器可视区域时,才加载图片。例如各种电商页面

  • 加快页面打开速度,提升用户体验
  • 减少服务器压力和浏览器的负担

性能优化

  • 浏览器
    • 减少HTTP请求
    • 使用HTTP2.0
    • 设置浏览器缓存
    • 白屏做加载动画
  • 资源
    • 静态资源CDN
    • 静态资源单独域名
    • GZIP压缩
    • 做服务端渲染
    • 头部放置CSS,底部放置JS
  • 图片
    • 字体图标代替图片图标
    • 精灵图
    • 图片懒加载
    • 图片预加载
    • 使用PNG格式的图片
    • 图片转BASE64格式
  • 代码
    • 慎用全局变量
    • 缓存全局变量
    • 减少回流与重绘
    • 节流防抖
    • 少用闭包
    • 减少数据读取次数
    • 文档碎片优化节点
    • 减少判断层级
    • 字面量与构造式
  • 项目
    • 长列表优化
    • web worker
    • 避免iframe
    • 打包
    • 减少代码体积
    • 按需加载
    • 提取第三方库代码
    • webpack dll优化

vue3 比 vue2 的优化

  • 性能: Vue3 在性能方面有了很大的提升,包括渲染速度和内存使用。它只会对渲染初始可见的部分数据创建观察者,以提高效率。此外,Vue3 还引入了变更通知的优化,只有依赖的属性的 watcher 才会重新运行,而不是所有 watcher
  • 语法: Vue3 使用了新的语法,如 Composition API 和 Fragments。Composition API 允许更灵活地组合组件逻辑,而 Fragments 允许在模板中返回多个元素。这使得 Vue3 在代码组织和可读性方面更加优秀
  • API: Vue3 的 API 与 Vue2 有所不同。Vue2 使用选项类型 API,而 Vue3 引入了 Composition API。这使得代码更加模块化,逻辑更加清晰
  • 生命周期函数钩子: Vue3 的生命周期函数钩子与 Vue2 有所不同。Vue3 增加了一些新的钩子函数,如 onRenderTracked 和 onRenderTriggered,并在调用前需要先引入
  • 数据双向绑定原理: Vue2 的双向数据绑定是利用 ES5 的 Object.defineProperty() 对数据进行劫持,结合发布订阅模式的方式来实现的。而 Vue3 则使用了 Proxy API 代理来实现数据双向绑定,这使得数据监听更加高效和全面
  • 定义变量和方法: Vue3 提供了 setup 方法,在组件初始化构造的时候触发。使用 reactive 方法来声明数据为响应性数据,并通过 setup 方法返回响应性数据,从而 template 可以获取这些响应式数据。这与 Vue2 中将数据放入 data 中并在 methods 中定义方法的方式有所不同
  • 指令和插槽的使用: Vue3 在指令和插槽的使用方面也有所变化,提供了更多的灵活性和功能
  • 是否支持碎片: Vue3 支持碎片(Fragments),意味着它可以拥有多个根节点。而 Vue2 则不支持碎片
  • 父子之间传参: Vue2 和 Vue3 在父子之间传参方面保持一致,都是使用 props 进行父传子,使用事件 Emitting Events 进行子传父
  • Main.js: Vue3 在 main.js 文件中的设置与 Vue2 有所不同,包括新的创建应用实例的方式和一些配置选项的变化
  • TS 和 PWA 支持程度: Vue3 新加入了 TypeScript 以及 PWA 支持,这使得开发者可以使用 TypeScript 编写更加严谨和可维护的代码,并且可以将 Vue 应用打包成 PWA 应用,提高应用的性能和用户体验

vue3 响应式原理

Vue 独特的响应式系统:当 JavaScript 对象发生变化时,视图会自动更新。核心设计思想是数据劫持+观察者模式

  1. Vue 使用了一个名为 Observer 的类来实现数据劫持。当创建 Vue 实例时,Vue 会遍历传入的数据对象,对其进行递归遍历将其转化为响应式属性
  2. 当属性转化为响应式属性时,Vue 会为每个属性创建一个 Dep 依赖对象,用于收集当前属性的依赖关系
  3. 当访问一个响应式属性时,Vue 会在访问过程中收集依赖,将当前属性和对应的 Watcher 对象关联起来
  4. 当属性发生变化时,Vue 会通知该属性的 Dep 依赖对象,然后依赖对象遍历其依赖列表没通知每个依赖的 Watcher 对象进行更新操作
  • 方法1:Object.defineProperty 实现
js 复制代码
function render() {
  console.log('模拟视图渲染')
}
let obj = [1, 2, 3]
let methods = ['pop', 'shift', 'unshift', 'sort', 'reverse', 'splice', 'push']
// 先获取到原来的原型上的方法
let arrayProto = Array.prototype
// 创建一个自己的原型 并且重写methods这些方法
let proto = Object.create(arrayProto)
methods.forEach(method => {
  proto[method] = function() {
    // AOP
    arrayProto[method].call(this, ...arguments)
    render()
  }
})
function observer(obj) {
  // 把所有的属性定义成set/get的方式
  if (Array.isArray(obj)) {
    obj.__proto__ = proto
    return
  }
  if (typeof obj == 'object') {
    for (let key in obj) {
      defineReactive(obj, key, obj[key])
    }
  }
}
function defineReactive(data, key, value) {
  observer(value)
  Object.defineProperty(data, key, {
    get() {
      return value
    },
    set(newValue) {
      observer(newValue)
      if (newValue !== value) {
        render()
        value = newValue
      }
    }
  })
}
observer(obj)
function $set(data, key, value) {
  defineReactive(data, key, value)
}
obj.push(123, 55)
console.log(obj) //[1, 2, 3, 123,  55]
  • 方法3:Proxy 实现
js 复制代码
function render() {
  console.log('模拟视图的更新')
}
let obj = {
  name: '前端工匠',
  age: { age: 100 },
  arr: [1, 2, 3]
}
let handler = {
  get(target, key) {
    // 如果取的值是对象就在对这个对象进行数据劫持
    if (typeof target[key] == 'object' && target[key] !== null) {
      return new Proxy(target[key], handler)
    }
    return Reflect.get(target, key)
  },
  set(target, key, value) {
    if (key === 'length') return true
    render()
    return Reflect.set(target, key, value)
  }
}

let proxy = new Proxy(obj, handler)
proxy.age.name = '浪里行舟' // 支持新增属性
console.log(proxy.age.name) // 模拟视图的更新 浪里行舟
proxy.arr[0] = '浪里行舟' //支持数组的内容发生变化
console.log(proxy.arr) // 模拟视图的更新 ['浪里行舟', 2, 3 ]
proxy.arr.length-- // 无效

参考资料

深入浅出Vue响应式原理(完整版)
超简单直观理解懒加载(Lazyload)
Vue官方文档
深入理解Electron(一)Electron架构介绍
浏览器缓存看这一篇就够了
菜鸟教程
面试常问:为什么 Vite 速度比 webpack 快?

txt 复制代码
新人发文,礼貌求关❤️
相关推荐
腾讯TNTWeb前端团队5 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
uhakadotcom8 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
范文杰8 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪9 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy9 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom10 小时前
快速开始使用 n8n
后端·面试·github
uhakadotcom10 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom10 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom10 小时前
React与Next.js:基础知识及应用场景
前端·面试·github