欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

2024 高频前端面试问题 Vue2 和 Vue3 部分

最编程 2024-03-10 22:55:07
...

HTML和CSS篇:2024高频前端面试题 HTML 和 CSS 篇-****博客

JavaScript 和 ES6 篇: 2024高频前端面试题 JavaScript 和 ES6 篇-****博客

* Vue2 和 Vue3的区别:

1)双向数据绑定原理的区别

2)根节点的不同

Vue2只能一个根节点

Vue3在组件中可以放置多个根节点

3)Vue3中采用composition API 

vue2:采用的选项型API(opsition API)
vue3:采用的组合型API(composition API)

4)建立的数据方式不同 

vue2:数据是放置在data属性中
vue3:需要使用setup 方法,该方法在初始化构造的时候触发
注:ref:需要value 访问,内部还是使用的defineProperty set get 方法进行监听(proxy 不支持基本类型的监听)
reactive: 使用的proxy对数据进行的一个代理

5)生命周期函数不同 

6)diff算法不同

7)父子传参不同

vue2:父传子,用props,子传父用事件 Emitting Events。在vue2中,会调用this$emit然后传入事件名和对象。

vue3:父传子,用props,子传父用事件 Emitting Events。在vue3中的setup()中的第二个参数content对象中就有emit,那么我们只要在setup()接收第二个参数中使用分解对象法取出emit就可以在setup方法中随意使用了。

1. 什么是MVVM?

M - Model 数据:负责数据管理和业务逻辑。
V - View 视图:负责用户界面的展示和呈现。
VM - ViewModel 视图-数据:它是View和Model的粘合体,负责View和Model的交互和协作

vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变; 

核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法,get set 方法。

在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。

MVVM 是一种软件架构模式。它是基于 MVC 的一种演变,将视图和数据绑定的方式更加紧密地结合在一起。 

2. 什么是MVC? 

M - Model 数据:负责数据管理和业务逻辑。模型表示应用程序中的数据结构以及对数据的操作。
V - View 视图负责用户界面的展示和呈现,通常是用户可以看到和与之交互的部分。
C - Controller 控制器: 负责接收用户的输入并作出响应,它处理用户与模型和视图之间的交互。控制器将用户的操作转发给模型进行处理,并将模型的结果传递给视图进行展示。

MVC 的优势:
能够将应用程序的各个功能模块分离开来,提高代码的可维护性和可扩展性。通过明确定义了各个组件的职责,开发人员可以更好地组织和管理代码,同时也使得代码更容易被复用。

3. MVVM 和 MVC的区别 

1、mvvm各部分的通信是双向的,而mvc各部分通信是单向的;

2、mvvm是真正将页面与数据逻辑分离放到js里去实现,而mvc里面未分离

MVC允许在不改变视图的情况下改变视图对用户输入的响应方式,用户对View的操作交给了Controller处理,在Controller中响应View的事件调用Model的接口对数据进行操作,一旦Model发生变化便通知相关视图进行更新。 

4. Vue2响应式原理 

对象类型:

使用 Object.defineProperty 遍历对象的每一个属性,把每一个属性变成一个 getter 和 setter 函数,读取属性的时候调用 getter,给属性赋值的时候就会调用 setter,这就是数据劫持。

数组类型:

通过重写更新数组的一系列方法,保留原功能的基础上增加一些数据劫持的代码(也就是将数据变为可监控的)来实现拦截。

7个方法:push、pop、shift、unshift、splice、sort、reverse。

存在问题:

1.新增属性、删除属性, 界面不会更新。

2.直接通过下标修改数组, 界面不会自动更新。

解决方法:

vue2中 $set 可以解决这些问题。

5.  Vue3响应式原理 

通过(Proxy)代理实现: 拦截对象中任意属性的变化, 包括属性值的读写, 属性的添加, 属性的删除等操作。

通过(Reflect)(反射); 被代理的对象, 属性进行操作。

vue3.0 中不存在vue2.0 中说的这些问题

在一个对象中新增, 删除, 修改属性, 界面不会自动更新。

直接通过下标修改数组, 界面不会自动更新。

6. Proxy 与 Object.defineProperty 优劣对比 

1)Proxy的优势如下:

  1. Proxy可以直接监听对象⽽⾮属性 。
  2. Proxy可以直接监听数组的变化 。
  3. Proxy有多达13种拦截⽅法,不限于apply、ownKeys、deleteProperty、has等等是 Object.defineProperty 不具备的 。
  4. Proxy返回的是⼀个新对象,我们可以只操作新的对象达到⽬的,⽽ Object.defineProperty 只能遍历对象属性直接修改。
  5. Proxy作为新标准将受到浏览器⼚商重点持续的性能优化,也就是传说中的新标准的性能红利 。

2)Object.defineProperty的优势如下:

  1. 兼容性好,⽀持IE9。

7. Vue2和Vue3的diff的区别 

diff 算法有以下过程:
  • 同级比较,再比较子节点
  • 先判断一方有子节点一方没有子节点的情况(如果新的 children 没有子节点,将旧的子节点移除)
  • 比较都有子节点的情况(核心 diff)
  • 递归比较子节点
Vue2:

Vue2 的核心 Diff 算法采用了双端比较的算法,同时从新旧 children 的两端开始进行比较,借助 key 值找到可复用的节点,再进行相关操作。相比 React 的 Diff 算法,同样情况下可以减少移动节点次数,减少不必要的性能损耗,更加的优雅。

Vue3:

Vue3.x 借鉴了 ivi 算法和 inferno 算法

在创建 VNode 时就确定其类型,以及在 mount/patch 的过程中采用位运算来判断一个 VNode 的类型,在这个基础之上再配合核心的 Diff 算法,使得性能上较 Vue2.x 有了提升。该算法中还运用了动态规划的思想求解最长递归子序列。

详细内容比较多,但这个是重点部分。请跳转至:

Vue2 和 Vue3 的 Diff 算法的区别-****博客

Vue diff算法_vue2 diff算法和vue3diff算法-****博客

8. 虚拟 DOM 的优缺点 

优点:
  • 性能优化:虚拟DOM通过减少不必要的DOM操作,提高渲染性能。它使用一个高效的diff算法来计算出真正需要更新的节点,最大限度地减少DOM操作,从而提高性能。
  • 抽象化DOM操作:由于虚拟DOM以JavaScript对象为基础,不依赖真实平台环境,因此可以跨平台操作,例如在浏览器平台、Weex、Node等环境中使用。
  • 无需手动操作DOM:Vue的虚拟DOM可以自动处理视图更新,开发者只需要关注数据变化,无需手动操作DOM,大大提高了开发效率。
缺点: 
  • 首次渲染大量DOM时性能较差:由于虚拟DOM需要进行计算和比较,所以在首次渲染大量DOM时,可能会比直接操作DOM慢。
  • 不适合小型项目:对于小型项目或简单页面,使用虚拟DOM可能会增加额外的计算开销,此时直接操作DOM可能更为简单高效。

9. 生命周期的理解

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。

10. Vue2的生命周期

创建阶段:

beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created:在实例创建完成后被调用,此阶段完成了数据观测 (data observer)、属性和方法的运算,以及 watch/event 事件的设置。但是此时还没有挂载到 DOM 上。

挂载阶段:

beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用。

mounted:在实例被挂载到 DOM 后调用,此阶段完成了模板编译并且将实例挂载到 DOM 上。

更新阶段:

beforeUpdate:在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。

updated:在数据更新完成后被调用,实例的 DOM 已经更新。

销毁阶段:

beforeDestroy:在实例销毁之前调用,此时实例仍然完全可用。

destroyed:在实例销毁后调用,此阶段完成了实例的事件监听器和子组件的销毁。

两个特殊的生命周期钩子函数: 

activated:在使用 keep-alive 组件时,被激活的组件会调用该函数。

deactivated:在使用 keep-alive 组件时,被停用的组件会调用该函数。

11. Vue3的生命周期         

1)普通写法:       2)setup中写生命周期:
beforeCreate setup()
created setup()
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted

12. Vue2和Vue3生命周期区别

13. 父组件和子组件生命周期钩子函数执行顺序 

执行顺序:

父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载。

父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

14. 在哪个生命周期内调用异步请求?

可以在钩子函数 createdbeforeMountmounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。

但是本人推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  • 能更快获取到服务端数据,减少页面 loading 时间;
  • ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;

15. 父组件可以监听到子组件的生命周期吗? 

比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:

// Parent.vue
<Child @mounted="doSomething"/>
    
// Child.vue
mounted() {
  this.$emit("mounted");
}

以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示

//  Parent.vue
<Child @hook:mounted="doSomething" ></Child>

doSomething() {
   console.log('父组件监听到 mounted 钩子函数 ...');
},
    
//  Child.vue
mounted(){
   console.log('子组件触发 mounted 钩子函数 ...');
},    
    
// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ... 

当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。

16. keep-alive 

在组件切换过程中将状态保留在内存中,防止重复渲染DOM,提高页面加载性能与用户体验

可以设置以下props属性(参数):

  1. include:匹配的路由/组件会被缓存
  2. exclude:匹配的路由/组件不会被缓存
  3. max:最大缓存数

当时用keep-alive,只会创建一次,即时切出该组件,也不会销毁该组件,再进入该组件,也不会创建。

当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序 created => mounted => activated

退出时触发deactivated。当再次进入或退出时,只触发activated和deactivated。钩子的触发顺序(destroyed => activated

17. 组件中 data 为什么是一个函数? 

因为 Vue 在创建组件实例时,会为每个组件实例都创建一个独立的数据作用域

如果将 data 直接定义为一个对象,那么所有组件实例都将共享同一个数据对象,这样就无法实现数据的隔离。

data 是函数的话那么每次创建组件实例时,都会调用这个函数并返回一个新的对象

18. vue中key的作用 

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较。

作用:

是为了更高效的更新虚拟DOM,它的作用是标识虚拟DOM的唯一性,当虚拟DOM发生变化时,vue会根据key的变化来判断是否需要更新虚拟DOM。通过key的作用,可以更高效地更新虚拟DOM,提高了页面的性能和用户体验

19. computed 和 watch 的区别和运用的场景? 

computed:计算属性,依赖于其他属性,并且computed的值有缓存。只有它依赖的属性值(响应式依赖)发生变化,下一次获取computed的值时才会重新计算computed的值。

watch:更多的是【观察】的作用,类似于某些数据的监听回调,每当监听的数据发生变化时,都会执行回调进行后续操作。

运用场景:

  • computed:当我们要进行数值计算,并且依赖于其他数据时,这时应该使用computed,因为利用computed的缓存特性,可以避免每次获取值时都重复计算。
  • watch: 当我们在数据发生变化时执行异步或开销较大的操作时,应该使用watch,使用watch选项允许我们执行一步操作(访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些是computed(计算属性)无法实现的

20. watch 和 watchEffect 的区别?

watch 和 watchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式

  • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。 
  • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确
执行时机不同:

watch 是惰性地执行副作用,他不会立即执行,但可以配置immediate,使其主动触发 。

watchEffect 是立即执行的,在页面加载时会主动执行一次,来收集依赖。

参数不同:

watch 至少要有两个参数,第一个是监听的数据,第二个是回调函数,第三个是配置项。

watchEffect 只需要一个回调函数,不需要传递侦听的数据,它会在页面加载时主动执行一次,来收集依赖。

结果不同:

watch 可以获取新值和旧值

watchEffect 获取不到更改前的值

watchEffect的解释:

1、立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数
2、如果你需要侦听一个嵌套数据结构中的几个属性,watchEffect() 可能会比深度侦听器更有效,因为它将只跟踪回调中被使用到的属性,而不是递归地跟踪所有的属性。 

21. 组件间通信有哪几种方式? 

1)props / $emit

父组件通过 props 向子组件传递数据,子组件通过 $emit 和父组件通信

2)ref / $refs

子组件绑定ref父组件通过 $refs. 读取子组件的属性和方法

3)eventBus事件总线($emit / $on)
4)依赖注入(provide / inject)

子组件 inject , 父组件 provide

pc:依赖注入所提供的属性是非响应式的

5) $parent / $children

$parent 访问到的是上一级父组件的实例

$children 的值是数组,而 $parent是个对象

6)$attrs / $listeners
7)Vuex 和 Pinia
总结:
父子组件间通信

1)props,emit

2) ref,$refs 

3)provide,inject

跨代组件间通信

1)$attrs,$listeners

兄弟组件间通信

1) $parent + $refs

任意组件间通信

1)eventBus事件总线

2)Vuex 和 Pinia

详解:

vue中组件间通信的6种方式_跨组件通信vue-****博客

22. v-if 和 v-for 的优先级哪个高? 

vue2 中 v-for 的优先级更高。(2o)

vue3 中优先级改变了,v-if 的优先级更高。 (3i)

同一个标签中同时使用了 v-for 和 v-if:

由于v-for的优先级比v-if高,所以每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。

解决办法:

1)用计算属性去过滤v-for使用的数组

2)添加 <template> 让 v-for 和 v-if,不在同一标签上

23. v-show 与 v-if 有什么区别? 

v-if :

真正的条件渲染,动态的向DOM树内添加或者删除DOM元素

也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show :

就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。

总结:

所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

24. delete 和 Vue.delete 删除数组的区别是什么? 

delete:

 只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。 

Vue.delete :

是直接将元素从数组中完全删除改变了数组其他元素的键值

25. v-model 的原理 

v-model本质上是一个语法糖

v-model其实就是 :value@input事件的简写。

26. reactive 和 ref 对比区别 

定于数据角度对比:
ref 用来定义:基本类型数据
reactive 用来定义:对象、或数组类型的数据
备注:ref也可以用来定义对象或数组类型数据,它内部会自动通过 reactive 转为代理对象

原理角度对比:
ref 通过 Object.defineProperty() 的 get 与 set 来实现响应式的(数据劫持)
reactive 通过使用 Proxy 来实现响应式(数据劫持),并通过Reflect 操作源对象内部的数据。 

使用角度对比:
ref 定义的数据:操作数据需要 .value,读取数据时模版中直接读取不需要 .value
reactive 定义的数据:操作数据与读取数据,均不需要 .value 

27. toRef() 和 toRefs() 

toRef():

可以将值、refs 或 getters 规范化为 refs (3.3+)。

也可以基于响应式对象上的一个属性,创建一个对应的 ref。这样创建的 ref 与其源属性保持同步改变源属性的值将更新 ref 的值,反之亦然。

toRefs():

将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。

当从组合式函数中返回响应式对象时,toRefs 相当有用。使用它,消费者组件可以解构/展开返回的对象而不会失去响应性。

toRefs 在调用时只会为源对象上可以枚举的属性创建 ref。如果要为可能还不存在的属性创建 ref,请改用 toRef

28. NextTick()作用

vue 更新 DOM 是异步更新的,数据变化,DOM 的更新不会马上完成,nextTick 的回调是在下次 DOM 更新循环结束之后执行的延迟回调

29. scoped作用与原理 

作用:组件css作用域,避免子组件内部的css样式被父组件覆盖

原理:给元素添加一个自定义属性 v-data-xxxxx, 通过属性选择题来提高css权重值。

30. 路由守卫作用/对比axios拦截器 

相同点:
  • 都是钩子函数(回调函数的一种,到某个时机了自动触发)
  • 都是起到拦截作用
不同点: 
  • 功能不同 :axios拦截器拦截网络请求, 导航守卫拦截路由跳转
  • 应用场景不同 :
  1. axios拦截器一般用于发送token
  2. 导航守卫用于页面跳转权限管理(有的页面可以无条件跳转,例如登录注册页可以无条件跳转。有的页面需要满足条件才能跳转,例如购物车页面就需要用户登录才可以跳转)

31. 服务端渲染 SSR 的优缺点

SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成然后再把html直接返回给客户端。 

优点:
  • 更好的 SEO: 因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;
  • 更快的内容到达时间(首屏加载更快): SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;
缺点:
  • 更多的开发条件限制: 例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;
  • 更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 ( high traffic ) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。

32. vue3有哪些新的组件? 

<Teleport> 是一个内置组件,它可以将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去。

<Suspense> 是一个内置组件,用来在组件树中协调对异步依赖的处理。它让我们可以在组件树上层等待下层的多个嵌套异步依赖项解析完成,并可以在等待时渲染一个加载状态。(等待异步组件时渲染一些额外内容

33. vue 如何快速定位那个组件出现性能问题的 

timeline ⼯具。 通过 timeline 来查看每个函数的调⽤时常,定位出哪个函数的问题,从⽽能判断哪个组件出了问题。

34. Vue 项目进行哪些优化 

代码层面的优化:
  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分使用场景
  • v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
  • 长列表性能优化
  • 事件的销毁
  • 图片资源懒加载
  • 路由懒加载
  • 第三方插件的按需引入
  • 优化无限列表性能
  • 服务端渲染 SSR or 预渲染
SEO 优化 :
  • 预渲染
  • 服务端渲染 SSR
用户体验: 
  • 骨架屏
  • PWA
Webpack 层面的优化:
  • Webpack 对图片进行压缩
  • 减少 ES6 转为 ES5 的冗余代码
  • 提取公共代码
  • 模板预编译
  • 提取组件的 CSS
  • 优化 SourceMap
  • 构建结果输出分析
  • Vue 项目的编译优化
基础的 Web 技术的优化:
  • 开启 gzip 压缩
  • 浏览器缓存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶颈

35. vue 中的 spa 应用如何优化首屏加载速度?

  • 请求优化:CDN 将第三方的类库放到 CDN 上,能够大幅度减少生产环境中的项目体积,另外 CDN 能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。
  • 缓存:将长时间不会改变的第三方类库或者静态资源设置为强缓存,将 max-age 设置为一个非常长的时间,再将访问路径加上哈希达到哈希值变了以后保证获取到最新资源,好的缓存策略有助于减轻服务器的压力,并且显著的提升用户的体验
  • gzip开启 gzip 压缩,通常开启 gzip 压缩能够有效的缩小传输资源的大小。
  • http2:如果系统首屏同一时间需要加载的静态资源非常多,但是浏览器对同域名的 tcp 连接数量是有限制的(chrome 为 6 个)超过规定数量的 tcp 连接,则必须要等到之前的请求收到响应后才能继续发送,而 http2 则可以在多个 tcp 连接中并发多个请求没有限制,在一些网络较差的环境开启 http2 性能提升尤为明显。

  • 懒加载:当 url 匹配到相应的路径时,通过 import 动态加载页面组件,这样首屏的代码量会大幅减少,webpack 会把动态加载的页面组件分离成单独的一个 chunk.js 文件
  • 预渲染:由于浏览器在渲染出页面之前,需要先加载和解析相应的 html、css 和 js 文件,为此会有一段白屏的时间,可以添加loading,或者骨架屏幕尽可能的减少白屏对用户的影响体积优化
  • 合理使用第三方库:对于一些第三方 ui 框架、类库,尽量使用按需加载,减少打包体积
  • 使用可视化工具分析打包后的模块体积webpack-bundle- analyzer 这个插件在每次打包后能够更加直观的分析打包后模块的体积,再对其中比较大的模块进行优化
  • 提高代码使用率利用代码分割,将脚本中无需立即调用的代码在代码构建时转变为异步加载的过程
  • 封装:构建良好的项目架构,按照项目需求就行全局组件,插件,过滤器,指令,utils 等做一 些公共封装,可以有效减少我们的代码量,而且更容易维护资源优化
  • 图片懒加载:使用图片懒加载可以优化同一时间减少 http 请求开销,避免显示图片导致的画面抖动,提高用户体验
  • 使用 svg 图标:相对于用一张图片来表示图标,svg 拥有更好的图片质量,体积更小,并且不需要开启额外的 http 请求

*构建工具:Webpack 和 Vite 的区别 

1. 底层的语言

  • webpack是基于nodejs构建JavaScript 是以毫秒计数。
  • vite是基于esbulid预构建依赖,esbulid是采用go语言编写的,go语言纳秒级别的。

2. 打包过程

  • webpack:分析各个模块之间的依赖=>然后进行编译打=>打包后的代码在本地服务器渲染。随着模块增多,打包的体积变大,造成热更新速度变慢。
  • vite:启动服务器=>请求模块时按需动态编译显示。
vite:
  • 开发环境:基于 原生 ES 模块(Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。)
  • 生产环境:使用 Rollup 打包

3. 配置方式

  • webpack配置复杂,需要配置各种loaderplugin

  • Vite配置简单,基于 Rollup,大多数功能开箱即用

4. TypeScript支持

  • webpack需要额外的loader处理TypeScript

  • Vite内置了对TypeScript的支持

5. 生态系统

  • webpack的生态更加丰富成熟
  • Vite作为较新方案,生态还在快速发展中

6. 总结

Vite具有更快的启动速度、轻量的配置、更好的HMR和SSR支持等特点,适合现代化的框架。但它也存在部分生态缺失的问题。Webpack具有更全面的生态和插件支持,但配置复杂,构建速度较慢。不同场景下可根据需求选择不同的工具。

未完待续...