Vue 基本使用

指令、插值

  • 插值、表达式
  • 指令、动态属性
  • v-html 会有xss风险,会覆盖子组件

computed 和 watch

  • computed 有缓存,data不变则不会重新计算
  • watch 如何深度监听
  • watch 监听引用类型,拿不到oldVal
watch : {
    handler (oldVal, val) {
        console.log('watch info', oldVal, val)
    },
    deep: true
}

class style

  • 使用动态属性
  • 使用驼峰式写法

条件渲染

  • v-if v-else 的用法,可以使用变量,也可以使用 === 表达式
  • v-if 和 v-show 的区别
  • v-if 和 v-show 的使用场景

循环列表的渲染

  • 如何遍历对象——也可以使用 v-for
  • key 的重要性,key不能乱写,如random 或者 index
  • v-for 和 v-if 是不能一起使用的

事件

  • event 参数,自定义参数($event,原生event)
  • 事件修饰符,按键修饰符
  • 【观察】事件被绑定到哪里(写在哪,挂载在哪)

image.png

image.png

表单

  • v-model
  • 常见的表单项, textarea,checkbox,radio,select
  • 修饰符 lazy number trim

image.png

vue 组件使用

  • props 和 $emit
  • 组件间通讯-自定义事件
  • 组件生命周期

单个组件

  • 挂载阶段
  • 更新阶段
  • 销毁阶段

created vue实例化完成 mounted 元素挂载完成 ​

父子组件 image.png 创建从外到内,渲染从内到外 image.png

image.png

Vue 高级特性

  • 自定义 v-model
  • $nextick
  • slot
  • 动态、异步组件
  • keep-alive
  • mixin

v-model

<intput :value='text' @input="$emit('change', $event.target.value)"/>
export default {
  model: {
  	prop: 'text',
    event: 'change'
  },
	props: {
  	text: String,
    default: ''
  }
}

$nextTick

  • Vue 是异步渲染
  • data 改变之后,DOM 不会立刻渲染
  • $nextTick 会在DOM渲染之后被触发,以获取最新的DOM节点

image.png

slot

  • 基本使用
  • 作用域插槽
  • 具名插槽

动态组件

  • :is=“component-name” 用法 <component :is="NextTick" />
  • 需要根据数据,动态渲染的场景。即组件类型不确定

Vue 如何加载异步组件

  • import() 函数
  • 按需加载,异步加载大组件

keep-alive

  • 缓存组件
  • 频繁切换,不需要重复渲染
  • Vue 常见的性能优化

mixins

  • 多个组件有相同的逻辑,抽离出来
  • mixin 并不是最完美的解决方案,会有一些问题
  • Vue3 提出的 CompositionAPI 旨在解决这些问题

mixin 缺点

  • 变量来源不明确,不利于阅读
  • 多个 mixin 可能会造成命名冲突
  • mixin 和组件可能会出现多对多的关系,复杂度高

Vuex 使用

基本概念

  • state
  • getters
  • action
  • mutation

用于vue 组件

  • dispatch
  • commit
  • mapState
  • mapGetters
  • mapActions
  • mapMutations

image.png

VueRouter

  • 路由模式,(hash,H5 history)
  • 路由配置,(动态路由,懒加载)

Vue 原理

  • 组件化
  • 响应式
  • vdom 和 diff
  • 模板编译
  • 渲染过程
  • 前端路由

组件化基础

  • “很久以前”就有组件化
  • 数据驱动视图(MVVM,setState)

  • 传统组件,只是静态渲染,更新还是要依赖于操作DOM
  • 数据驱动视图 - Vue MVVM
  • 数据驱动视图 - React setState

Vue MVVM

image.png

Vue 响应式

  • 核心API Object.defineProperty
  • proxy 有兼容性的问题,且无法polyfill
  • 监听对象,监听数组
  • 复杂对象,深度监听
  • 几个缺点

  • Object.defineProperty 深度监听,需要递归到底,一次性计算量大
  • 无法监听新增属性,删除属性
  • 无法监听原生数组,需要做特殊处理

虚拟DOM 和 diff

  • vdom 是实现 vue 和 React 的重要基石
  • diff 算法是 vdom 中最核心最关键的部分
  • vdom 是一个热门话题,也是面试中最热门的话题

  • DOM 的操作非常耗费性能
  • 以前使用 jQuery,可以自行控制DOM操作的时机,手动调整
  • Vue 和 React 是数据驱动视图,如何有效的控制 DOM 操作

  • 有了一定复杂度,想减少计算次数比较难
  • 能不能把计算,更多的转移为JS计算,因为JS执行速度很快
  • vdom - 用 js 模拟DOM 结构,计算出最小的变更,操作DOM

  • vue3 重写了vdom的代码,优化了性能
  • 但是vdom的基本里边不变,面试考点也不变

snabbdom 使用

  • 用JS模拟DOM结构(vnode)
  • 新旧vnode对比,得出最小的更新范围,最后更新DOM
  • 数据驱动视图的模式下,有效控制DOM的操作

diff 算法

树diff 的时间复杂度是O(n^3)——算法不可用的 优化时间复杂度到O(n) ​

  • 只比较同一层级,不跨级比较
  • tag 不相同,则直接删掉重建,不再深度比较
  • tag 和 key, 两者都相同,则认为是相同节点,不在深度比较

image.png image.png h 函数: 返回一个vnode ​

  • patchNode
  • addVnodes removeVNodes
  • updateChildren

  • 细节不重要,updateChildren的过程也不重要,不要深究
  • vdom 的核心概念很重要,h,vnode,patch、diff、key
  • vdom存在的价值更加重要:数据驱动视图,控制DOM操作

模板编译

  • 模板是vue 开发中最常用的部分,即与使用相关联的原理
  • 他不是html,有指令、插值、JS表达式到底是什么
  • 面试不会直接问,但是会通过“组件渲染和更新过程”考察

  • v-if 三元表达式
  • v-for _l renderList
  • 事件
  • v-model

vue-template-compiler ​

组件 渲染/更新 过程

  • 响应式:监听data属性的getter 和 setter (包括数组)
  • 模板编译:模板到render函数,再到vnode
  • vdom :patch(ele, vnode) patch(vnode, newVNode)

初次渲染的过程

  • 解析模板为render函数,(或者在开发环境中已经完成,vue-loader)
  • 触发响应式,监听data属性getter setter
  • 执行render函数,生成vnode,patch(ele, vnode)

更新过程

  • 修改 data, 触发setter(此前在getter 中已被监听)
  • 重新执行render 函数,生成newVNode
  • patch(vnode, newVnode)

image.png

异步渲染

  • 回顾$nexttick
  • 汇总 data 的修改,一次性更新视图
  • 减少DOM的操作次数,提高性能

前端路由的原理

路由模式

  • hash
  • history

hash 的特点

  • hash 变化会触发网页的跳转,即浏览器的前进后退
  • hash 变化不会刷新页面,SPA必备特点
  • hash 永远不会提交到 server 端

window.onhashchange = () => {} ​

H5 history

  • 用url规范的路由,但跳转时不刷新页面
  • history.pushState
  • window.onpopstate
  • 需要后端配合

Vue 面试真题

v-show v-if 区别

为何在v-for中使用key

  • 必须用key,且不能是index和random
  • diff 算法中通过tag 和 key 来判断,是否是 sameNode
  • 减少渲染次数提升渲染性能

描述Vue 组件的生命周期

  • 单组件的生命周期图
  • 父子组件生命周期关系

Vue 组件如何通讯

  • 父子组件 props 和 this.$emit
  • 自定义事件,event.$on event.$off event.$emit
  • vuex

描述组件渲染和更新的过程

image.png

双向数据绑定v-model的实现原理

  • ipnut元素的value = this.name
  • 绑定input事件this.name = $event.target.value
  • data 更新触发 re-render

对 mvvm 的理解

computed 有何特点

  • 缓存,data 不变不会重新计算
  • 提高性能

为何组件data 必须是一个函数

ajax 请求应该放在那个生命周期中

  • mounted
  • js是单线程的,ajax 异步获取数据
  • 放在mounted 之前没有用只会让逻辑更加复杂

如何将组件所有props传递给子组件

  • v-bind="$props"

如何自己实现一个v-model

多个组件有相同的逻辑,怎么抽离

mixin ​

何时要使用 异步组件

  • 加载大组件
  • 路由

何时需要使用keep-alive

  • 缓存组件,不需要重复渲染
  • 性能优化

何时需要使用 beforeDestory

  • 解绑自定义事件event.$off
  • 清除定时器
  • 解绑自定义的DOM事件

什么是作用域插槽

Vuex 中action 和 mutation 有什么区别

image.png

vue-router常用的路由模式

vue-router 异步加载

请用 vnode 描述一个DOM 结构

监听data变化的核心API是什么

Vue 如何监听数组变化

请描述响应式原理

Diff 算法的时间复杂度

简述diff算法的过程

image.png

Vue 为何是异步渲染,$nextTick 何用

Vue 性能优化

  • 合理使用 v-show 和 v-if
  • 合理使用 computed
  • v-for 时加 key ,避免和v-if 同时使用
  • 自定义事件,以及DOM事件要及时销毁
  • 合理使用 异步组件
  • 合理使用 keep-alive
  • data层级不要太深
  • 使用 vue-loader 在开发环境做模板预编译
  • webpack 层的优化
  • 前端通用的优化,图片懒加载
  • 使用SSR

Vue3

Vue3 对 Vue2 有什么优势

  • 性能更小
  • 体积更小
  • 更好的TS开发的
  • 更好的代码组织
  • 更好的逻辑抽离

Composition API 和 Options API

  • 不建议共用,会引起混乱
  • 小型项目业务逻辑简单,用Options API
  • 中大型项目、复杂逻辑,用Composition API

ref

  • 生成值类型的响应式数据
  • 可用于模板和reactive
  • 通过 .value 修改值

toRef

  • 针对一个响应式对象(reactive封装)的prop
  • 创建一个ref,具有响应式
  • 两者保持引用关系

toRefs

  • 将响应式对象(reactive封装)转换为普通对象
  • 对象的每一个prop都是对应的ref
  • 两者保持引用关系

toRef 和 toRefs 的最佳使用方式

  • 用 reactive 做对象的响应式,用ref做值类型的响应式
  • setup 中返回toRefs(state) 或者 toRef(state, ‘xxx’)
  • ref 的变量命名都用xxxRef
  • 合成函数返回响应式对象时,使用 toRefs

深入理解 ref

为什么使用ref

  • 返回值类型,会丢失响应式
  • 如 setup, computed,合成函数,都有可能返回值类型
  • Vue 如不定义ref,用户会自造ref,反而混乱

为什么需要.value

  • ref 是一个对象(不丢失响应式),value 存储值
  • 通过 .value 属性的get 和 set 实现响应式
  • 用于模板、reactive 时,不需要.value,其他情况下都需要

为什么需要 toRef 和 toRefs

初衷:不丢失响应式的情况下,把数据对象 分解/扩散 前提:针对的是响应式对象(reactive封装的)非普通对象 注意:不创造响应式,而是延续响应式 ​

vue升级了哪些重要的功能

  • createApp
  • emit 属性
  • 生命周期
  • 多事件
  • Fragment
  • 移除 .sync
  • 异步组件的写法
  • 移除 filter
  • suspense
  • composition API

Vue2 如何实现响应式

Object.defineProperty 的缺点

  • 深度监听需要一次性递归
  • 无法监听新增属性和删除属性
  • 无法监听数组,需要特殊处理

image.png

Reflect 作用

  • 和 Proxyu 能力一一对应
  • 规范化、标准化、函数式
  • 代替 object 的工具函数

Proxy 实现响应式

  • 深度监听,性能更好
  • 可监听 新增、删除属性
  • 可监听数组变化

image.png

watch 和 watchEffect 区别

  • 两者都可以监听data 属性变化
  • watch 需要明确监听哪个属性
  • watchEffect 会根据其中的属性,自动监听其变化

image.png image.png

setup 中如何获取组件的实例

  • 在setup 和其他compositionAPI 中没有this
  • 可以通过 getCurrentInstance 获取当前实例
  • 若使用 options API 可照常使用this

Vue3 为何比Vue2快

  • Proxy 响应式
  • PatchFlag
  • hoistStatic
  • cacheHandler
  • SSR 优化
  • tree-shaking

PatchFlag

  • 编译模板时,动态节点做标记
  • 标记,分为不同类型,如TEXT,PROPS
  • diff 算法时,可以区分静态节点,以及不同类型的动态节点

image.png

hoistStatic

  • 将静态节点的定义,提升到父作用域,缓存起来
  • 多个相邻的静态节点会被合并起来
  • 典型的那空间换时间的优化策略

cacheHandler

  • 缓存事件

SSR 优化

  • 静态节点直接输出,绕过了vdom
  • 动态节点,还是需要动态渲染

vite 是什么

  • 一个前端的打包工具,Vue作者发起的项目
  • 借助Vue 的影响力,发展较快,和webpack 竞争
  • 优势: 开发环境下无需打包,启动快

Vite 为何启动快

  • 开发环境使用 ES Module,无需打包——非常快
  • 生产环境下使用rollup,并不会快很多

es module: type=‘module’ ​

Composition API 和 react hooks 对比

  • 前者setup 只会调用一次,而后者函数会被调用很多次
  • 前者无需调用useMemo,useCallback 因为setup 只会调用一次
  • 前者无需顾虑调用的顺序,而后者需要保证hooks的顺序一致
  • 前者 reactive 和ref 比后者useState,要更加难以理解

Vue3 和 JSX

image.png

jsx 和 template 区别

  • 语法上是有很大的区别的

  • 本质是相同的

  • 具体示例,插值,自定义组件,属性和事件,条件和循环

  • jsx 的本质就是js代码,可以使用js的任何能力

  • template 只能嵌入简单的js表达式,其他需要指令,如 v-if

  • jsx 已经成为es规范,template 还是Vue 自家的规范

Vue3 script setup

React

关于 react 17

  • 没有明显的新特性,使用是和react 16 是一致的
  • 面试时也不会被重点考察

React 基本使用

事件

  • bind this
  • 关于 event 参数
  • 传递自定义参数

react 中的event 不是原生的event ,而是 syntheticEvent(组合事件)

react事件和DOM 事件的区别

  • event 是 SyntheticEvent ,模拟出原生事件所有的能力
  • event.nativeEvent 是原生事件对象
  • 多有的时间都被挂载到document上
  • 和DOM时间不一样,和Vue 事件也不一样

image.png

React 16 绑定到 document上 react 17 绑定在 root 组件上 有利于多个react 版本并存,例如微前端 ​

image.png

表单

  • 受控组件
  • input textarea select 用value
  • checkbox radio 用 checked

setState

  • 不可变值
  • 可能是异步更新
  • 可能会被合并

setState 是同步还是异步的

  • 正常情况下是异步的
  • setTimeout中setState 是同步的
  • 自定义DOM事件中也是同步的

setState 可能会被合并

  • 传入对象会被合并
  • 传入函数不会被合并

单组件生命周期

image.png

生命周期

React 高级特性

  • 函数组件
  • 非受控组件
  • Portals
  • context
  • 异步组件
  • 性能优化
  • 高阶组件HOC
  • Render Props

函数组件

  • 输入 props 输出 jsx
  • 没有实例,没有生命周期,没有state
  • 不能扩展其他方法

什么是非受控组件

  • ref
  • defaultValue defaultChecked
  • 手动操作DOM元素

使用场景

  • 必须手动操作DOM元素,setState实现不了
  • 文件上传,input type=‘file’
  • 某些富文本编辑器,需要传入DOM元素

受控组件 vs 非受控组件

  • 优先使用受控组件,符合React 设计原则
  • 必须操作DOM时,再使用非受控组件

Portals

  • 组件默认会按照既定的层级嵌套渲染
  • 如何让组件渲染到父组件外

ReactDOM.createPortals ​

image.png

context

  • 公共信息(语言,主题)如何传递给每个组件
  • 用props太繁琐
  • 用redux 小题大做

react 如何加载异步组件

image.png

性能优化

  • shouldComponentUpdate
  • PureComponent 和 React.memo
  • 不可变值 immutable.js

image.png

React 默认:父组件更新,子组件则默认无条件更新 性能优化对于 React 更加重要! ​

SCU一定每次都要用吗——需要的时候才会优化 ​

shouldComponentUpdate 在做深层比较的时候,如果使用isEqual会对数组或者对象做深层比较,(一次性递归到底) ​

  • SCU 默认返回true,即React 默认重新渲染所有子组件
  • 必须配合不可变值一起使用
  • 可先不使用shouldComponentUpdate ,有性能问题时在考虑使用

PureComponent 和 memo

  • PureComponent,scu中实现了浅比较
  • React.memo. 函数组件中的PureComponent
  • 浅比较已经适用大部分情况(尽量不要做深度比较)

immutable.js

  • 彻底拥抱“不可变值”
  • 基于共享数据(不是深拷贝),速度好
  • 有一定学习和迁移成本,按需使用

image.png

关于组件公共逻辑的抽离

  • mixin 已经被React 废弃
  • 高阶组件HOC
  • render props

高阶组件不是一种功能,而是一种模式

  • 透传所有 props(Vue 中 v-bind $props)
  • 增加mouse属性

redux connect 是高阶组件 ​

向组件属性中传入render函数

Redux 使用

  • 基本概念
  • 单向数据流
  • react-redux
  • 异步action
  • 中间件

基本概念

  • store state
  • action
  • reducer

流程

  • dispatch(action)
  • reducer -> newState
  • subscribe触发通知

react-redux

  • connect
  • mapStateToProps mapDispatchToProps

image.png image.png

  • redux-thunk
  • redux-promise
  • redux-saga

image.png

react router

  • 路由模式(hash ,H5 history)
  • 路由配置(动态路由,懒加载)
  • 掌握基本使用

React原理

  • 大厂使用React 概率更高
  • react 对开发人员要求更高
  • 大厂更偏爱考察原理

  • 函数式编程
  • vdom 和 diff 算法
  • JSX的本质
  • 合成事件
  • setState batchUpdate
  • 组件渲染过程

函数式编程

  • 一种编程范式,概念比较多
  • 纯函数
  • 不可变值

vdom 和 diff

  • h函数
  • 返回 vnode 数据结构
  • patch 函数

diff 算法的改造

  • 只比较同一层级,不跨级比较
  • tag 相同,则之间删掉重建,不再深度比较
  • tag 和 key ,两者都相同,则认为是相同节点,不在深度比较

  • Vue2 Vue3 React 三者实现vdom细节均不相同
  • 核心概念和实现思路都一样
  • 面试主要考察后者,不用全部掌握细节

JSX的本质

  • JSX等同于Vue 的模板
  • Vue 模板不是HTML
  • JSX 也不是 JS

  • React.createElement 即h函数,返回vnode
  • 第一个参数,可能是组件,也可能是 html tag
  • 组件名,首字母必须大写(React 规定)

react 合成事件机制

image.png

为什么要合成事件机制

  • 更好的兼容性和跨平台
  • 挂载到 document上,减少内存消耗,避免频繁解绑
  • 方便事件的统一管理

image.png

React 的batchUpdate 机制

  • 有的时候是异步的(普通使用),有时同步(setTimeout,DOM事件)
  • 有时合并(对象形式),有时不合并(函数形式)
  • 后者比较好理解,向Object.assign ,主要讲解后者

  • setState 主流程
  • batchUpdate 机制
  • transaction (事物)机制

image.png

image.png

  • setState 无所谓异步还是同步
  • 看是否可以命中 batchUpdate 机制
  • 判断 isBatchingUpdates

那些可以命中batchUpdate机制

  • 生命周期(和它调用的函数)
  • React中注册的时间(和它调用的函数)
  • React 可以“管理”的入口

  • setTimeout setInterval 等(和它调用的函数)
  • 自定义的DOM 事件(和它调用的函数)
  • React “管不到”的入口

简述 transaction 事务机制

image.png image.png

组件渲染和更新过程

  • JSX 如何渲染为页面
  • setState 之后如何更新页面
  • 面试考察全流程

  • props state
  • render() 生成vnode
  • patch(elem, vnode)

  • setState(newState) –> dirtyComponents(可能有子组件)
  • render() 生成 newVnode
  • patch(vnode, newVnode)

更新的两个阶段

  • 上述patch 被拆分成了两个阶段
  • reconciliation 阶段 - 执行diff 算法,纯JS 计算
  • commit 阶段 - 将diff结果渲染DOM

如果不拆分成两个阶段,可能会有性能问题

  • js是单线程,且和DOM渲染公用一个线程
  • 当组件足够复杂,组件更新时计算和渲染都压力大
  • 同时再有DOM操作需求,(动画,鼠标拖拽),将卡顿

解决方案 fiber

  • 将reconciliation阶段进行任务拆分,(commit 无法拆分)
  • DOM 需要渲染时暂停,空闲时恢复
  • window.requestIdleCallback

React 面试真题

组件间如何通讯

JSX 的本质是什么

context是什么如何应用

shouldComponentUpdate的用途

redux 单向数据流

setState场景题

image.png

什么是纯函数

React 组件证明周期(单组件,父子组件)

ajax 应该在那个生命周期上

渲染列表,为何使用key

函数组件和class组件的区别

什么是受控组件

何时使用异步组件

多个组件有公共逻辑,如何抽离

redux 如何进行异步请求

react-router 如何配置懒加载

image.png

PureComponent有何区别

React事件和DOM 事件的区别

React性能优化

  • 渲染列表时使用key
  • 自定义事件 DOM 事件及时销毁
  • 合理使用异步组件
  • 减少函数bind this 的次数
  • 合理使用 shouldComponentUpdate PureComponent 和 memo
  • 合理使用 Immuta.js
  • webpack 层面的优化
  • 前端通用的性能优化,如图片懒加载
  • 使用 SSR

React 和 Vue 的区别

共同点

  • 都支持组件化
  • 都是数据驱动视图
  • 都使用vdom操作DOM

不同点

  • React 使用 jsx 拥抱js ,vue 使用模板拥抱html
  • React函数式编程,Vue声明式编程
  • React 更多的需要自力更生,Vue 把想要的都给你

Webpack

  • webpack 已经是前端打包构建的不二选择
  • 每日必用,面试必考
  • 成熟的工具,重点在于配置和使用,原理并不高优

webpack 5

  • webpack 5 主要是内部效率的优化
  • 对于 webpack4 ,没有太多使用上的改动
  • 你可以直接使用webpack5

webpack 基本配置

  • 拆分配置 和 merge
  • 启动本地服务
  • 处理es6
  • 处理样式
  • 处理图片
  • (模块化)

postcss 兼容性处理 ​

webpack 高级配置

  • 多入口

image.png

  • 抽离 css 文件

image.png

  • 抽离公共代码

image.png

  • 懒加载
  • 处理 jsx 处理 vue

module chunk bundle 的区别

  • module - 各个源码文件,webpack中一切皆模块
  • chunk - 多模块合成的 如entry import() splitChunk
  • bundle - 最终输出的文件

image.png

webpack 性能优化

webpack怎么优化打包构建速度,开发体验和效率 优化产出代码 - 产品性能 ​

优化 babel-loader image.png

ignorePlugin 避免引用无用模块 image.png image.png

noParse 避免重复打包 image.png

ignorePlugin vs noParse

  • IgnorePlugin直接不引入,代码中没有
  • noParse 引入,但不打包

happyPack 多进程打包

  • JS 单线程,开启多进程打包
  • 提高构建速度,特别是多核CPU

image.png image.png

parallelUglifyPlugin 多进程压缩JS

  • webpack 内置 uglify 工具压缩 JS
  • JS 单线程,开启多进程压缩更快
  • 和 happyPack 同理

image.png

关于开启多线程

  • 项目较大,打包较慢,开启多线程能提升速度
  • 项目较小,打包较快,开启多进程会降低速度
  • 按需使用

自动刷新 image.png

热更新

  • 自动刷新:整个网页全部刷新,速度较慢
  • 自动刷新网页的状态会丢失
  • 热更新就是新代码生效,网页不刷新,状态不丢失

image.png image.png image.png

dllPlugin 动态链接库插件

  • 前端框架如 vue react 体积大,构建慢
  • 较稳定,不常更新版本
  • 同一个版本只构建一次即可,不用每次都重新构建

  • webpack已经内置了DllPlugin支持
  • DllPlugin - 打包出 dll 文件
  • DllReferencePlugin - 使用dll 文件

const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
  mode: 'development',
  // JS 执行入口文件
  entry: {
    // 把 React 相关模块的放到一个单独的动态链接库
    react: ['react', 'react-dom']
  },
  output: {
    // 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称,
    // 也就是 entry 中配置的 react 和 polyfill
    filename: '[name].dll.js',
    // 输出的文件都放到 dist 目录下
    path: distPath,
    // 存放动态链接库的全局变量名称,例如对应 react 来说就是 _dll_react
    // 之所以在前面加上 _dll_ 是为了防止全局变量冲突
    library: '_dll_[name]',
  },
  plugins: [
    // 接入 DllPlugin
    new DllPlugin({
      // 动态链接库的全局变量名称,需要和 output.library 中保持一致
      // 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
      // 例如 react.manifest.json 中就有 "name": "_dll_react"
      name: '_dll_[name]',
      // 描述动态链接库的 manifest.json 文件输出时的文件名称
      path: path.join(distPath, '[name].manifest.json'),
    }),
  ],
}

image.png

webpack 优化构建速度(可以用于生产环境)

  • 优化 babel-loader include exclude
  • IgnorePlugins
  • noParse
  • happyPack
  • ParallelUglifyPlugin

webpack 优化构建速度(不可用于生产环境)

  • 自动刷新
  • 热更新
  • DllPlugin

webpack 性能优化 - 产出代码

  • 体积更小
  • 合理分包,不重复加载
  • 速度更快,内存使用更小

  • 小图片 base64 编码
  • bundle 加 hash
  • 懒加载
  • 提取公共代码
  • IgnorePlugin
  • 使用 CDN 加速
  • 使用 production
  • Scope Hosting

使用 Production

  • 开启代码压缩
  • vue react 等会删掉调试代码(如开发环境下的warning)
  • 启用 tree shaking

必须使用ES6 Module 才能让tree-shaking 生效 commonjs就不行 ​

ES Module 和 Commonjs 的区别

  • ES module 静态引入,编译时引入
  • commonjs 动态引入,执行时引入
  • 只有 ES6 Module 才能静态分析,实现 Tree-shaking

Scope Hosting

  • 代码体积会更小
  • 创建函数作用域更少
  • 代码的可读性更好

image.png

babel

  • 环境搭建
  • .babelrc 配置
  • preset 和 plugins

preset 是 plugins 的集合 ​

什么是 babel-polyfill

  • 什么是polyfill
  • core-js 和 regenerator
  • babel-polyfill 就是上面两者的集合

  • babel-polyfill 在babel 7.4之后被弃用
  • 推荐直接使用 core-js 和 regenerator

core-js: polyfill 集合 ​

babel-polyfill 如何按需引入

  • 文件较大
  • 只有一部分功能,无需全部引入
  • 配置按需引入

{
    "presets": [
        [
            "@babel/preset-env",
            {
                "useBuiltIns": "usage",
                "corejs": 3
            }
        ]
    ],
    "plugins": [
        [
            "@babel/plugin-transform-runtime",
            {
                "absoluteRuntime": false,
                "corejs": 3,
                "helpers": true,
                "regenerator": true,
                "useESModules": false
            }
        ]
    ]
}

问题

  • 污染了全局环境
  • 如果做一个web系统,则无碍
  • 如果是一个第三方的lib,会有问题

babel-runtime

Webpack 面试题

前端为什么要进行打包构建

  • 体积更小(tree-shaking、压缩、合并),加载更快
  • 编译高级语言或语法(TS,ES6+,模块化,scss)
  • 兼容性和错误检查(Polyfill,postcss,eslint)

  • 统一高校的开发环境
  • 统一的构建流程和产出标准
  • 继承公司构建规范(提测、上线)

module chunk bundle 的区别

loader 和 plugins 的区别

常见 loader和plugins

babel和webpack的区别

如何产出一个lib

babel-polyfill 和 babel-runtime 的区别

webpack如何实现懒加载

为何 Proxy 不能被polyfill

webpack优化构建速度

webpack 优化产出代码

组件设计

  • 从功能上拆分层次
  • 尽量让组件原子化
  • 容器组件(只管理数据) UI组件(只显示视图)

React Hooks

  • 可选功能
  • 100% 向后兼容,没有破坏性改动
  • 不会取代class 组件,尚无计划要移除 class 组件

函数组件的特点

  • 没有组件实例
  • 没有生命周期
  • 没有state和setState,只能接受props

class 组件的问题

  • 大型组件很难拆分和重构,很难测试(即class不易拆分)
  • 相同业务逻辑,分散到各个方法中逻辑混乱
  • 复用逻辑复杂,Mixins,HOC,Render Props

react组件更易用函数表达

  • react 倡导函数式编程
  • 函数更灵活更易拆分,更易测试
  • 但函数组件太简单,需要增强能力——hooks

state hook

  • 默认组件没有state
  • 函数组件是一个纯函数,执行完就销毁,无法储存state
  • 需要 state hook ,即把state功能“钩”到纯函数中

Effect

  • didMount didUpdate - useEffect
  • didMount - useEffect(()=>{},[])

image.png

模拟 unmount的时候注意事项

image.png

其他 hooks

  • useRef
  • useContext
  • usereducer
  • useMemo
  • useCallback

image.png

自定义 hooks

  • 封装通用的功能
  • 开发和使用第三方hooks
  • 自定义hook带来无线的扩展性,解耦代码

Hooks 使用规范

  • 只能用于react 组件和自定义hook中,其他地方不可以
  • 只能用于顶层代码,不能用于循环判断中使用hooks
  • eslint 插件 eslint-plugin-react-hooks

为何Hooks 要依赖于调用顺序

  • 函数组件,纯函数,执行完即销毁
  • 所以,无论组件初始化,还是组件更新
  • 都会执行过一次这个函数,获取最新的组件
  • render: 初始化 state 的值 “张三”
  • re-render:读取state的值 “张三”

  • render: 添加 effect 函数
  • re-render:替换 effect 函数,内部的函数也会重新定义

class 组件逻辑复用

  • mixin 早已废弃
  • 高阶组件HOC
  • render props

mixin 问题

  • 变量作用域来源不清楚
  • 属性重名
  • mixin引入过多会导致顺序冲突

HOC

  • 组件层级嵌套过多,不易渲染,不一调试
  • HOC 会劫持props,必须严格遵守规范,容易出现疏漏

render props

  • 学习成本较高,不易理解
  • 只能传递纯函数,默认情况下纯函数功能有限

Hooks 组件逻辑复用有什么好处

  • 完全符合Hooks原有规则,没有其他要求,易理解记忆
  • 变量作用域很明确
  • 不会产生组件嵌套

React Hooks 注意事项

  • useState初始化值,只有第一次有效
  • useEffect 不能修改state
  • useEffect 可能出现死循环