2023.12 微派网络(青藤之恋)

343 阅读14分钟

前言

八股文是一点没问,面试官脾气很好,会帮忙补充,面试体验还是极好的,就是本人太菜了,铁挂了。上来首先自我介绍,然后问本人性能优化怎么优化的。

看题吧

讲讲项目

省略

你们是根据什么得出性能瓶颈的

答曰:LightHouse

做了哪些优化

答曰:拆分公共库、使用外链、按需引入npm资源以及拆分大型第三方插件,可以优化微前端项目的性能和资源加载效率。

除了这些还有哪些性能优化的方式

答曰:没怎么答上来,随意提了一嘴图片懒加载,svg优化

以下内容来自GPT4

在Vue项目中进行性能优化通常涉及以下方面:

  1. 组件懒加载:使用Vue的异步组件和Webpack的代码分割功能来实现组件级别的懒加载。

  2. 路由懒加载:结合Vue Router,只有当路由被访问时才加载对应组件。

  3. 打包优化

    • 利用Webpack的splitChunks来拆分公共代码。
    • 使用uglifyjs-webpack-plugin进行代码压缩。
    • 移除生产环境中的console.logdebugger
  4. 树摇(Tree Shaking):移除未引用的代码,减少最终包的大小。

  5. 优化源代码

    • 使用计算属性和监听器(computed properties and watchers)来避免不必要的计算和DOM操作。
    • 避免在模板中使用复杂的表达式和函数。
    • 使用v-ifv-show智能地控制DOM的渲染。
  6. 数据获取优化:使用服务端渲染(SSR)或预渲染(Prerendering)来改善首次加载性能。

  7. 图片和媒体文件优化

    • 使用图片压缩工具减小图片体积。
    • 采用懒加载技术延迟加载非首屏图片。
    • 使用现代图片格式如WebP。
  8. 缓存优化

    • 利用HTTP缓存策略。
    • 使用Vue的keep-alive组件缓存不活跃的组件。
  9. CSS优化

    • 提取公共CSS到单独文件。
    • 使用CSS预处理器和后处理器。
    • 减少CSS的深度选择器。
  10. 性能监控:使用Vue Devtools和其他性能分析工具来监控和分析组件的渲染性能。

  11. 异步数据的状态管理:使用Vuex或其他状态管理库来管理状态,特别是对于复杂的异步数据流。

  12. 事件处理优化:对于大量的事件监听,例如滚动事件,使用防抖(debounce)或节流(throttle)技术来减少事件触发频率。

  13. 服务端性能优化:确保API响应时间短,可以使用缓存、数据库索引优化等技术提升后端性能。

  14. 使用Web Workers:对于复杂的数据处理,可以使用Web Workers在后台线程中运行,避免阻塞主线程。

  15. 静态资源优化:通过Webpack插件对静态资源进行版本控制和压缩。

实施这些性能优化措施时,应首先分析项目的性能瓶颈,然后有针对性地选择合适的优化策略,以确保最大化提升性能。

简单说说虚拟滚动的原理

对于定高的item

  1. 计算可视区域:对于固定高度的item,确定用户在屏幕上可以看到多少个列表项
  2. 渲染可视项:根据用户当前的滚动位置渲染可视区域的列表
  3. 动态加载/移除:监听滚动,滚动时动态添加进入可视区域的列表项,并移除已经离开可视区域的列表
  4. 提前占位:保持滚动条正常的行为,列表的前后添加适当大小的占位元素,以模拟完整列表的高度。

vue2 和 vue3 区别

  1. 性能改进

    • Vue 3 引入了一个更快的虚拟 DOM (VDOM) 重写和优化,减少了内存占用,并提高了渲染速度。
    • Vue 3 使用了 Proxy 作为其响应式系统的基础,这使得跟踪变化更为高效,而 Vue 2 使用的是 Object.defineProperty。
  2. 组合式 API

    • Vue 3 引入了组合式 API(Composition API),包括 ref, reactive, computed, watch, 和 setup 等函数。这提供了一种更灵活的方式来组织和重用逻辑,特别是在处理大型组件时。
    • Vue 2 主要使用选项式 API,通过 data, methods, computed, watch 等选项来组织组件的逻辑。
  3. TypeScript 支持

    • Vue 3 从一开始就考虑了对 TypeScript 的支持,提供了更好的类型推断和集成。
    • Vue 2 对 TypeScript 的支持是有限的,通常需要额外的类型声明和装饰器。
  4. 模块化

    • Vue 3 设计为更加模块化,允许开发者按需引入核心功能,这有助于减少最终打包体积。
    • Vue 2 的核心功能更加集中,不提供这种级别的模块化。
  5. 新的生命周期钩子

    • Vue 3 引入了新的生命周期钩子,如 onMounted, onUpdated, 和 onUnmounted,取代了 Vue 2 中的 mounted, updated, 和 beforeDestroy/destroyed
  6. 片段 (Fragments)

    • Vue 3 允许组件有多个根节点,而 Vue 2 要求每个组件只能有一个根节点。
  7. Teleport

    • Vue 3 新增了 Teleport 组件,允许开发者将组件的子节点渲染到 DOM 树的另一个部分,这对于模态框和通知之类的功能特别有用。
  8. Suspense

    • Vue 3 提供了 Suspense 组件,用于处理异步组件的加载状态,使得等待数据加载时的用户体验更加流畅。
  9. 自定义渲染器 API

    • Vue 3 提供了自定义渲染器 API,允许开发者创建自定义的渲染器,这在创建跨平台应用程序时非常有用。
  10. 更好的错误处理

    • Vue 3 提供了更好的错误处理机制,包括错误捕获和错误边界。

vue 虚拟DOM 原理及作用

vue 的diff 算法

Diff 算法用于比较新旧虚拟DOM树,能够以最小的代价更新DOM,从而提高应用的性能和响应速度。 Diff算法通常遵循以下步骤:

  1. 树的比较:算法首先比较两棵树的根节点,如果节点的类型不同,那么整棵树将被替换。如果节点类型相同,则继续比较子节点。
  2. 节点的比较:对于同一类型的组件,比较它们的属性或状态的差异,并记录需要更新的部分。
  3. 列表对比:当比较子节点列表时,Diff算法会尝试找出哪些子节点是新增的,哪些是移除的,哪些是移动的。React默认使用“key”属性来追踪列表中子元素的身份,这样可以更高效地比较和重排子节点。
  4. 更新DOM:根据收集到的差异信息,算法会进行批量更新,只修改需要改变的部分,而不是重建整个DOM树。

Diff算法的关键优化策略包括:

  • 同级比较:只比较同一层级的节点,而不是跨层级比较,这大大降低了比较的复杂度。
  • 类型比较:如果节点类型不同,就假设整个子树都发生了变化。
  • Key比较:使用key属性来标识列表中的唯一子元素,这样在子元素位置发生变化时,可以避免不必要的元素重建。

vue computed 和 watch 区别

在Vue 3中,computedwatch的基本概念与Vue 2相似,但有一些细微的变化和改进。下面是Vue 3中computedwatch的区别:

computed属性

  • 定义computed是基于它们的响应式依赖进行计算的响应式属性。它们只会在相关依赖发生变化时重新计算。
  • 缓存computed属性依然是缓存的,如果依赖项没有变化,多次访问computed属性会返回同一个值,不会重新计算。
  • 响应式:在Vue 3中,computed返回的是一个ref对象,你可以通过.value来访问计算后的值。
  • 用途:用于声明性地描述一个值如何根据其他响应式数据计算得出。

watch侦听器

  • 定义watch允许你对响应式引用(ref)、响应式对象(reactive)或getter函数进行观察,并在它们变化时执行一些操作。
  • 细粒度控制:Vue 3提供了watchwatchEffect两种侦听器。watchEffect会立即执行并响应其内部所有响应式状态的变化,而watch允许你更精确地指定要观察的数据和更详细地配置侦听行为。
  • 多个源:Vue 3的watchAPI允许同时观察多个源。
  • 清理效果watchwatchEffect都允许你提供一个清理效果的函数,这在侦听器需要在重新运行之前清理或取消之前的副作用时非常有用。

使用场景比较

  • computed:当你需要根据其他数据计算一个新的响应式数据时,使用computed。例如,根据用户信息计算用户的全名。
  • watch:当你需要在响应式数据变化时执行副作用,例如异步请求、长时间运行的操作或非响应式的操作时,使用watch

示例

import { reactive, computed, watch } from 'vue';

const state = reactive({
  a: 1,
  b: 2,
});

// computed属性
const aPlusB = computed(() => state.a + state.b);

// watch侦听器
watch(
  () => state.a,
  (newValue, oldValue) => {
    // 当state.a变化时执行的副作用
  }
);

// watchEffect示例
watchEffect((onInvalidate) => {
  // 依赖的响应式状态变化时立即执行
  // onInvalidate可以用来注册清理函数
});

vite 和 webpack 区别

  1. 启动速度:Vite 的冷启动速度比 Webpack 快,特别是在开发过程中,Vite 可以快速启动开发服务器并提供热更新功能。
  2. 构建方式:Vite 基于 ES Module 的原生模块系统,而 Webpack 则使用通用的模块打包方式,支持更多的资源类型和复杂的构建场景。
  3. 内置功能:Vite 内置了一堆功能,约定大于配置,webpack需要自己去配置。

详细说说前端工程化

前端工程化是指将软件工程的方法和实践应用于前端开发流程中,以提高效率、质量和可维护性。

前端工程化通常包括以下几个方面:

  1. 版本控制系统

    • 使用版本控制系统(如 Git)来管理代码的变更历史,协助团队成员之间的协作,并支持代码的分支和合并。
  2. 包管理

    • 使用包管理工具(如 npm 或 yarn)来管理项目的依赖,确保一致的开发环境,并方便地更新和安装第三方库。
  3. 模块化开发

    • 采用模块化的方式组织代码,使用如 ES6 模块或 CommonJS 来编写可复用的组件和库,提高代码的可维护性和复用性。
  4. 构建工具

    • 使用构建工具(如 Webpack、Rollup、Parcel)来自动化常见的开发任务,例如代码转译(Babel)、打包、压缩、代码分割、环境变量替换等。
  5. 代码规范和格式化

    • 通过 ESLint、Prettier 等工具实施代码规范,保持代码风格一致性,并自动格式化代码,减少代码审查中的格式问题。
  6. 样式预处理和后处理

    • 使用样式预处理器(如 Sass、Less)来编写更加结构化和可维护的样式代码。
    • 使用 PostCSS 等后处理器来自动添加浏览器前缀、优化 CSS 代码。
  7. 单元测试和集成测试

    • 使用测试框架(如 Jest、Mocha、Cypress)来编写和运行单元测试和集成测试,确保代码的质量和功能的正确性。
  8. 持续集成/持续部署 (CI/CD)

    • 利用 CI/CD 工具(如 Jenkins、Travis CI、GitHub Actions)自动化测试、构建和部署流程,快速响应代码变更,并确保部署的稳定性。
  9. 代码分析和优化

    • 使用代码分析工具(如 Lighthouse、Webpack Bundle Analyzer)来分析应用性能,识别瓶颈,并进行相应的优化。
  10. 开发环境统一

    • 使用 Docker、Vagrant 等工具来创建统一的开发环境,避免 "在我机器上可以运行" 的问题。
  11. 前端监控和日志

    • 集成前端监控工具,如 Sentry、LogRocket,来跟踪生产环境中的错误、性能问题,并分析用户行为。
  12. 文档和知识共享

    • 使用文档工具(如 Storybook、Docusaurus)来编写和维护项目文档,提高团队内部的知识共享和沟通效率。

通过前端工程化,团队可以实现自动化流程,减少人为错误,加快开发和部署速度,提高产品质量,最终达到提升开发体验和用户体验的目的。这些实践通常需要结合项目的具体需求和团队的工作流程来定制化实施。

你为前端提效做了哪些工作

提效工作都旨在减少重复性工作,自动化流程,提高代码质量,缩短反馈循环,并最终加快产品的开发和迭代速度。 作为一个人工智能助手,我虽然不直接参与前端开发,但我可以提供一些常见的策略和方法,这些可以帮助前端开发者提高开发效率:

  1. 组件库和设计系统

    • 创建和维护一个通用的组件库和设计系统,这样开发者可以重用这些组件,而不是从头开始编写每个新的UI元素。
  2. 代码生成和脚手架工具

    • 开发脚手架工具来快速生成项目结构、配置文件和代码模板,以减少重复的初始化工作。
  3. 热重载和实时预览

    • 使用支持热重载的开发服务器(如 Webpack Dev Server),这样开发者可以在代码变更后立即看到效果,无需手动刷新浏览器。
  4. 自动化任务运行

    • 使用任务运行器(如 Gulp、npm scripts)来自动执行常见任务,如代码压缩、图片优化等。
  5. 代码片段和快捷方式

    • 利用IDE或编辑器的代码片段功能,创建常用代码模板,提高编码速度。
  6. 状态管理和数据流工具

    • 使用如 Redux、Vuex、MobX 等状态管理工具来管理应用状态,避免不必要的数据传递和组件间通信的复杂性。
  7. 前端监控和性能分析

    • 定期进行性能分析,优化加载时间和运行效率,确保应用的响应速度。
  8. 规范化的提交流程

    • 通过 Git 钩子(如 pre-commit、pre-push 钩子)和代码审查工具来自动化代码质量检查和格式化,保证提交的代码质量。
  9. 模块懒加载

    • 实现路由级或组件级的懒加载,以加快应用的初始加载时间,并按需加载资源。
  10. 依赖管理和更新

    • 定期更新项目依赖,使用工具(如 Dependabot、Renovate)自动化依赖更新流程。
  11. 敏捷开发和迭代

    • 采用敏捷开发方法,如 Scrum 或 Kanban,进行小步快跑的迭代开发,确保项目持续进步。
  12. 持续学习和知识共享

    • 鼓励团队成员持续学习新技术,并通过定期的技术分享会、文档和wiki来共享知识。
  13. 工作流自动化

    • 利用CI/CD流程自动化构建、测试和部署,减少手动操作,缩短交付周期。
  14. 可视化工具和插件

    • 使用如 Chrome DevTools、React Developer Tools 等开发者工具来提高调试效率。
  15. 强化沟通和协作

    • 使用项目管理工具(如 Jira、Trello)和即时通讯工具(如 Slack)来提高团队沟通和协作效率。

手写题 比较两个版本号返回‘<’,'>','='

吃了没有沟通的亏,下意识的认为两个版本长度一致,以后面试得多跟面试官沟通

function compareVersion(version1, version2) {
  const v1Parts = version1.split('.').map(Number);
  const v2Parts = version2.split('.').map(Number);

  const maxLength = Math.max(v1Parts.length, v2Parts.length);

  for (let i = 0; i < maxLength; i++) {
    const part1 = v1Parts[i] || 0;
    const part2 = v2Parts[i] || 0;

    if (part1 > part2) {
      return 1;
    } else if (part1 < part2) {
      return -1;
    }
  }

  return 0;
}

// Example usage
const result = compareVersion('1.2.3', '1.2.4');
console.log(result); // Output: -1 (version1 is smaller than version2)