2024.05.23 更新前端面试问题总结(16 道题)
2024.05.09 - 2024.05.23 更新前端面试问题总结(16 道题) 获取更多面试相关问题可以访问 github 地址: github.com/pro-collect… gitee 地址: gitee.com/yanleweb/in…
目录:
-
中级开发者相关问题【共计 7 道题】
- 745.[webpack] mode 是做什么用?【热度: 475】【工程化】【出题公司: Shopee】
- 746.[React] 是如何处理组件更新和渲染的?【热度: 862】【web 框架】【出题公司: 快手】
- 747.[React] 介绍一下 useReducer【热度: 547】【web 框架】【出题公司: 滴滴】
- 748.[React] useEffect 钩子的工作原理是什么【热度: 459】【web 框架】【出题公司: 滴滴】
- 754.介绍一下 CSS 变量怎么声明和使用?【热度: 688】【CSS】【出题公司: TOP100 互联网】
- 755.less 函数如何使用?【热度: 229】【CSS】【出题公司: TOP100 互联网】
- 756.CSS 属性计算函数 Calc 介绍一下【热度: 228】【CSS】【出题公司: TOP100 互联网】
-
高级开发者相关问题【共计 8 道题】
- 744.V8 里面的 JIT 是什么?【热度: 694】【工程化】【出题公司: Shopee】
- 749.[webpack] optimize 配置有哪些作用【热度: 280】【工程化】【出题公司: TOP100 互联网】
- 750.[webpack] optimize 配置中, 分割代码配置 splitChunks 怎么使用【热度: 546】【工程化】【出题公司: TOP100 互联网】
- 751.CSS 在 2023 迎来重大更新, 更新内容是什么【热度: 548】【CSS】【出题公司: TOP100 互联网】
- 752.webpack 的主要配置项有哪些【热度: 766】【工程化】【出题公司: TOP100 互联网】
- 753.[React] React 19 有哪些新特性?【热度: 879】【web 框架】【出题公司: TOP100 互联网】
- 757.如何统计长任务时间、长任务执行次数【热度: 489】【web 应用场景】【出题公司: TOP100 互联网】
- 759.前端如何做 页面主题色切换【热度: 538】【web 应用场景】【出题公司: TOP100 互联网】
-
资深开发者相关问题【共计 1 道题】
- 758.前端视角 - 如何保证系统稳定性【热度: 566】【工程化】【出题公司: TOP100 互联网】
中级开发者相关问题【共计 7 道题】
745.[webpack] mode 是做什么用?【热度: 475】【工程化】【出题公司: Shopee】
关键词:webpack mode
在 webpack 中,mode
属性用来指定当前的构建环境是:development
、production
或者是 none
。设置 mode
可以使用 webpack 内置的函数,默认值为 production
。
mode
属性的主要作用是:根据当前的构建环境,启用 webpack 内置在该环境下推荐的优化。
mode 的具体作用包括:
-
development
- 主要优化了增量构建速度和开发体验。
process.env.NODE_ENV
的值设为development
。- 启用热替换模块(Hot Module Replacement)。
- 启用开发工具(如调试源码的 source map)以更好地进行调试。
-
production
- 一些处理优化,以提升应用在生产环境的性能。
process.env.NODE_ENV
的值设为production
。- 启用代码压缩(例如 TerserPlugin)。
- 删除 dead code(通过 Tree Shaking)。
- 作用域提升等各种性能优化措施。
-
none
mode
设置为none
则不启用任何默认优化选项,process.env.NODE_ENV
也不会被设置,默认为production
。
使用方法:
在 webpack 配置文件中,可以直接设置 mode
的值:
module.exports = {
mode: "development", // 'production' 或 'none'
// 其他配置...
};
或者,在命令行中使用 --mode
参数:
webpack --mode=production
设置 mode 是告诉 webpack 使用其内部的优化策略,各个模式预定义了一些 webpack 的行为,开发者可以不需要进行详细的配置,也能快速启动一个针对特定环境优化过的构建过程。
746.[React] 是如何处理组件更新和渲染的?【热度: 862】【web 框架】【出题公司: 快手】
关键词:React 组件更新、React 组件渲染
React 组件的更新和渲染遵循一个相对严格的生命周期,这个生命周期在 React 16 版本之后,也就是从引入 Fiber 架构开始,稍微有所变化。React 通过一系列的生命周期方法以及新引入的 Hooks API,对组件的更新进行管理,主要流程如下:
类组件的生命周期方法包括:
-
挂载(Mounting)
constructor()
: 组件被创建时调用,初始化 state。static getDerivedStateFromProps()
: 组件实例化后和接受新属性时将会调用。render()
: 唯一必须实现的方法,返回元素描述。componentDidMount()
: 组件挂载(插入 DOM 树中)之后调用。
-
更新(Updating)
static getDerivedStateFromProps()
: 在接收到新的 props 时调用。shouldComponentUpdate()
: 在接收到新的 props 或者 state 时,决定是否进行渲染。render()
: 重新渲染组件。getSnapshotBeforeUpdate()
: 在最新的渲染输出提交到 DOM 前将会立即调用。componentDidUpdate()
: 在组件更新后调用。
-
卸载(Unmounting)
componentWillUnmount()
: 在组件卸载及销毁之前直接调用。
React 16.3 之后的生命周期的变化
React 团队增加了新的生命周期方法,并且准备弃用某些旧的生命周期方法(如 componentWillMount
、componentWillReceiveProps
、componentWillUpdate
等)。引入了如 static getDerivedStateFromProps
和 getSnapshotBeforeUpdate
等新的生命周期方法。
函数组件和 Hooks
在 React 16.8 版本后,引入了 Hooks API,允许在不编写类的情况下使用 state 以及其他的 React 特性。对于函数组件,有几个常用的 Hooks:
useState
: 在函数组件中添加 state。useEffect
: 可以在组件中执行副作用操作(数据请求、订阅以及手动更改 React 组件中的 DOM 等)。useContext
: 允许你访问 React 的 Context 对象。useReducer
: 另一种在组件中管理 state 的方式,它用于复杂的 state 逻辑。- 其他 Hooks(如
useCallback
,useMemo
,useRef
等)。
更新和渲染流程:
- 当组件的 state 或者 props 发生变化时,React 会将新的 props 和 state 比较之前的,根据比较结果决定是否进行更新。
- 如果
shouldComponentUpdate
、PureComponent
或 React.memo 表示不需要更新,React 将不会进行更新。 - 如果需要更新,React 会调用
render
方法以及相关的生命周期方法或 Hooks,这个过程会创建一个虚拟 DOM 树。 - React 之后会对比新的虚拟 DOM 树与上一次更新时的虚拟 DOM 树,通过 DOM diffing 算法判断在哪进行实际的 DOM 更新。
- 应用必要的 DOM 更新到实际的 DOM 树上,如果有必要,调用
getSnapshotBeforeUpdate
和componentDidUpdate
方法。
这个过程保持了 React 组件的高效和可预测性,同时提供了生命周期的方法和 Hooks,使开发者能够插入自定义行为或响应组件的生命周期事件。
747.[React] 介绍一下 useReducer【热度: 547】【web 框架】【出题公司: 滴滴】
关键词:React useReducer
useReducer
是 React Hooks 的一个部分,它为状态管理提供了一个更加灵活的方法。useReducer
特别适合处理包含多个子值的复杂状态逻辑,或者当下一个状态依赖于之前的状态时。与useState
相比,useReducer
更适合于复杂的状态逻辑,它使组件的状态管理更加清晰和可预测。
基础使用:
const [state, dispatch] = useReducer(reducer, initialState);
state
:当前管理的状态。dispatch
:一个允许你分发动作(action)来更新状态的函数。reducer
:一个函数,接受当前的状态和一个动作对象作为参数,并返回一个新的状态。initialState
:初始状态值。
Reducer 函数:
Reducer 函数的格式如下:
function reducer(state, action) {
switch (action.type) {
case "ACTION_TYPE": {
// 处理动作并返回新的状态
return newState;
}
// 更多的动作处理
default:
return state;
}
}
动作(Action):
动作通常是一个包含type
字段的对象。type
用于在 reducer 函数中标识要执行的动作。动作对象也可以包含其他数据字段,用于传递动作所需的额外信息。
示例:
以下是一个使用useReducer
的简单示例:
import React, { useReducer } from "react";
// 定义reducer函数
function counterReducer(state, action) {
switch (action.type) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
}
function Counter() {
// 初始化状态和dispatch函数
const [state, dispatch] = useReducer(counterReducer, { count: 0 });
return (
<>
Count: {state.count}
<button onClick={() => dispatch({ type: "decrement" })}>-</button>
<button onClick={() => dispatch({ type: "increment" })}>+</button>
</>
);
}
在上面的例子中,我们创建了一个简单的计数器。当用户点击按钮时,会分发一个包含type
的动作到useReducer
钩子。然后,reducer
函数根据动作type
来决定如何更新状态。
使用场景:
- 管理局部组件的状态。
- 处理复杂的状态逻辑。
- 当前状态依赖上一状态时,可以通过上一状态计算得到新状态。
useReducer
通常与Context
一起使用可以实现不同组件间的状态共享,这在避免 prop drilling(长距离传递 prop)的同时使状态更新更为模块化。
748.[React] useEffect 钩子的工作原理是什么【热度: 459】【web 框架】【出题公司: 滴滴】
关键词:React useEffect
useEffect
钩子的工作原理涉及到 React 的渲染流程和副作用的调度机制。以下是其工作原理的详细说明:
-
调度副作用:当你在组件内部调用
useEffect
时,你实际上是将一个副作用函数及其依赖项数组排队等待执行。这个函数并不会立即执行。 -
提交阶段(Commit Phase):React 渲染组件并且执行了所有的纯函数组件或类组件的渲染方法后,会进入所谓的提交阶段。在这个阶段,React 将计算出的新视图(新的 DOM 节点)更新到屏幕上。一旦这个更新完成,React 就知道现在可以安全地执行副作用函数了,因为这不会影响到正在屏幕上显示的界面。
-
副作用执行:提交阶段完成后,React 会处理所有排队的副作用。如果组件是首次渲染,所有的副作用都会执行。如果组件是重新渲染,React 会首先对比副作用的依赖项数组:如果依赖项未变,副作用则不会执行;如果依赖项有变化,或者没有提供依赖项数组,副作用会再次执行。
-
清理机制:如果副作用函数返回了一个函数,那么这个函数将被视为清理函数。在执行当前的副作用之前,以及组件卸载前,React 会先调用上一次渲染中的清理函数。这样确保了不会有内存泄漏,同时能撤销上一次副作用导致的改变。
-
延迟副作用:尽管
useEffect
会在渲染之后执行,但它是异步执行的,不会阻塞浏览器更新屏幕。这意味着 React 会等待浏览器完成绘制之后,再执行你的副作用函数,以此来确保副作用处理不会导致用户可见的延迟。
通过这种机制,useEffect
允许开发者以一种优化的方式来处理组件中可能存在的副作用,而不需要关心渲染的具体时机。退出清理功能确保了即使组件被多次快速创建和销毁,应用程序也能保持稳定和性能。
754.介绍一下 CSS 变量怎么声明和使用?【热度: 688】【CSS】【出题公司: TOP100 互联网】
关键词:CSS 变量
CSS 自定义属性,又称 CSS 变量,是一种在 CSS 样式表中声明可以使用任意值的方法,这样的值在同一份 CSS 代码中可以多次引用并调用来替代特定的内容。使用 CSS 变量可以提高样式表的可维护性和灵活性。以下是如何声明和使用 CSS 变量的步骤:
声明 CSS 变量
CSS 变量的声明总是以 --
开头,跟随变量名。你可以在 CSS 的任何范围内声明变量,包括 :root
(相当于 HTML 的根),这样所有样式规则都可以访问到。
示例:
:root {
--main-color: #3498db;
--padding: 8px;
--transition-speed: 0.3s;
}
使用 CSS 变量
在 CSS 中使用变量时,你需要使用 var()
函数,并在括号中提供变量名,可以包含在--
前缀之后。
示例:
body {
background-color: var(--main-color);
padding: var(--padding);
transition: all var(--transition-speed) ease-in-out;
}
默认值
有时候,你可能想为 CSS 变量提供一个默认值,以防它未被声明时使用。在 var()
函数中,你可以添加一个可选的第二个参数作为默认值。
示例:
body {
font-size: var(--font-size, 16px);
}
在上面的例子中,如果 --font-size
变量没有在任何地方声明,body
的 font-size
将默认使用 16px
。
作用域
变量的作用域是根据它们声明的地方确定的:
- 在
:root
选择器内声明的变量是全局变量,在任何地方都可以使用。 - 在其他元素或伪类的 CSS 规则中声明的变量会在该元素或这些伪类中局部有效。
示例:
button {
--button-bg-color: #e74c3c;
}
.btn-primary {
background-color: var(--button-bg-color);
}
在上面的例子中,--button-bg-color
变量只在 button
元素中声明,因此它只在 button
下的所有样式规则中可用,.btn-primary
则是基于这个变量设置的。
CSS 变量是非常强大的工具,特别是当你需要在整个页面上保持一致性,或者是要实现主题应用时。它们有助于实现动态主题,使样式管理更系统化。
755.less 函数如何使用?【热度: 229】【CSS】【出题公司: TOP100 互联网】
关键词:less 函数
LESS 是一种基于 JavaScript 的 CSS 预处理器,它扩展了 CSS 的功能,提供了变量、嵌套、混合(Mixins)、函数等功能。LESS 中的函数允许你执行计算、转换和操纵值的操作,使得你的样式表更加灵活和动态。
使用 LESS 函数的基本步骤:
- 定义函数:你可以定义一个 LESS 函数,它接受参数并执行代码块。
.my-function(@arg) {
.result {
width: @arg;
}
}
- 调用函数:使用
@
前缀后跟函数名和所需的参数列表来调用函数。
.my-class {
.my-function(200px);
}
- 传递参数:函数可以接收一个或多个参数。上面的例子只传递一个参数。
示例:简单的 LESS 函数
// 定义一个 LESS 函数
.pi(@num) {
.pi-box {
width: @num * 3.14159;
}
}
// 调用这个函数
body {
.pi(5px);
}
在该示例中,pi
是一个接受数字参数并返回其圆周长度的 LESS 函数。这个 pi
函数在 body
选择器内部被调用,并设置了宽度为 5 * 3.14159 像素。
LESS 内建函数
LESS 还包括多个内建函数,可以直接在 LESS 代码中使用。以下是一些常见的内建函数示例:
-
percentage()
:将值转换成百分比。margin: percentage(20px / 100px); // 输出 20%
-
round()
:四舍五入数字。width: round(23.7px); // 输出 24px
-
floor()
和ceil()
:向下取整和向上取整。height: ceil(14.2px); // 输出 15px
-
unit()
和convert()
:分别用来获取值的单位和转换单位。width: convert(10, ms); // 将 10 转换为毫秒 margin: unit(25, "%"); // 输出 默认单位为 px,这次你却要改成百分比
-
color-function()
:用于操作颜色值的函数,例如lighten()
、darken()
、saturate()
等。background: lighten(#800, 10%); // 将颜色 #800 变亮 10%
-
e()
:允许你将 CSS 代码作为参数传递到&
中,用于可扩展的类选择器。.borderbox { *, *:before, *:after { .box-sizing(border-box); } }
注意事项:
- 函数可以返回任意值,包括颜色、数字、字符串和数组。
- 如果想要执行的是一个操作而非函数定义,需要注意的是 LESS 并不像 JavaScript 一样需要用
function
关键字声明。
合理使用函数可以极大增加 CSS 的动态性和灵活性,是构建维护性和复用性更强的 CSS 不可或缺的部分。
756.CSS 属性计算函数 Calc 介绍一下【热度: 228】【CSS】【出题公司: TOP100 互联网】
关键词:属性计算函数 calc
CSS 属性计算函数 calc()
是用来进行动态的尺寸计算以及数值混合运算的一种函数。它增强了纯 CSS 的灵活性,允许你在属性值的设置中直接执行基础的加(+
)、减(-
)、乘(*
)、除(/
)运算。
###使用方式
calc()
函数用于各种 CSS 属性,如 width
、height
、margin
、padding
、top
、right
、bottom
、left
、font-size
等。以下是 calc()
函数的基本语法:
property: calc(expression);
其中,expression
可以包括:
- 其他 CSS 单位值
- 数字常量
- 括号来控制运算顺序
基础示例
.element {
width: calc(100% - 50px); // 宽度是容器宽度减50px
padding: calc(1em + 10px); // 上下内边距是当前字体尺寸的1em加上10px
margin: calc(10px / 2); // 外边距为5px
font-size: calc(12px + 2vw); // 根据视窗宽度改变字体大小
}
高级用法
使用 calc()
的同时可以嵌套使用 min()
和 max()
函数,这种组合对响应式设计非常有用。
.element {
width: calc(min(100%, 500px)); // 宽度始终是容器的100%,但不超过500px
font-size: calc(max(12px, 1vw)); // 在某些实现中此用法可能不生效
}
括号
如果要进行优先级计算,你需要使用括号,比如在多重运算中:
.element {
width: calc(25% + (2em * (100vw - 200px) / 2));
}
注意事项
- 在进行除法运算时,要注意除数不能为零。
- CSS 变量可以在
calc()
中使用,使得你能够进行更灵活的样式控制。 calc()
必须确保表达式的两侧是兼容的单位,比如不能将像素(px
)和百分比(%
)相除。- 我很遗憾要指出一个小误导:
calc()
并不是 CSS 的原生属性,尽管它是 CSS 核心语法的一部分,它的适用性非常广泛。
兼容性
截至我的知识更新点(2023 年),calc()
得到了现代浏览器的广泛支持,包括 Chrome、Firefox、Safari、Edge 以及旧的 Internet Explorer 版本。唯一的例外是 Windows Phone 中的老版本浏览器。
实际应用场景
calc()
的一个常见用途是在响应式设计中,你可以用 calc()
来设置一个固定宽度和视口宽度的融合:
.container {
width: calc(100% - 20px); /* 虚拟列不存在时,容器宽度为屏幕宽度减去20px */
}
.grid {
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
/* 这部分代码创建一个栅格布局,其中每一格至少宽250px,每列最大填充至填满屏幕,如果没有空间填满则按最小宽度计算 */
}
通过 calc()
函数,开发人员可以设计出更加灵活和响应用户屏幕大小的界面布局。
高级开发者相关问题【共计 8 道题】
744.V8 里面的 JIT 是什么?【热度: 694】【工程化】【出题公司: Shopee】
关键词:V8 JIT
在计算机科学中,JIT 是“Just-In-Time”(即时编译)的缩写,它是一种提高代码执行性能的技术。具体来说,在 V8 引擎(Google Chrome 浏览器和 Node.js 的 JavaScript 引擎)中,JIT 编译器在 JavaScript 代码运行时,将其编译成机器语言,以提高执行速度。
这里简要解释下 JIT 编译器的工作原理:
-
解释执行:V8 首先通过一个解释器(如 Ignition)来执行 JavaScript 代码。这个过程中,代码不会编译成机器语言,而是逐行解释执行。这样做的优点是启动快,但执行速度较慢。
-
即时编译:当代码被多次执行时,V8 会认为这部分代码是“热点代码”(Hot Spot),此时 JIT 编译器(如 TurboFan)会介入,将这部分热点代码编译成机器语言。机器语言运行在 CPU 上比解释执行要快得多。
-
优化与去优化:JIT 编译器会对热点代码进行优化,但有时候它会基于错误的假设做出优化(例如认为某个变量总是某种类型)。如果后来的执行发现这些假设不成立,编译器需要去掉优化(Deoptimize),重新编译。
JIT 编译器的一个关键优点是它能够在不牺牲启动速度的情况下,提供接近于或同等于编译语言的运行速度。这使得像 JavaScript 这样原本被认为执行效率较低的语言能够用于复杂的计算任务和高性能的应用场景。
随着 V8 和其他现代 JavaScript 引擎的不断进步,JIT 编译技术也在持续优化,以提供更快的执行速度和更高的性能。
749.[webpack] optimize 配置有哪些作用【热度: 280】【工程化】【出题公司: TOP100 互联网】
关键词:webpack optimize
Webpack 的 optimize
选项是在指定 Webpack 配置对象时,用于配置优化选项的一个属性。该属性下包含了一系列用于调整构建输出质量和性能的设置。这里是一些 optimize
属性中可能包含的选项:
-
splitChunks:这用于代码分割,可以将公共的依赖模块提取到已有的入口 chunk 中,或者产生一个新的 chunk。这可以被用来得到更小的 bundle 体积,优化加载时间,或者更好的缓存利用。
-
runtimeChunk:该选项将 Webpack 的运行时代码分割成一个单独的 chunk。使用这个设置有利于长期缓存,并且当你使用多个入口点时推荐使用。
-
minimize:当设置为
true
时,Webpack 会启动代码压缩。通常,这会使用 UglifyJSPlugin 来进行 JavaScript 代码的压缩,但现在通常默认使用更现代的工具如 TerserPlugin。 -
minimizer:当你想要覆盖默认的压缩工具或者提供额外的压缩工具时使用。
-
noEmitOnErrors(早期版本称为
NoEmitOnErrorsPlugin
):启用该选项后,Webpack 编译错误将会导致不生成输出。这确保了不会发出包含错误的 assets。 -
concatenateModules(早期版本称为
ModuleConcatenationPlugin
):这个选项会试图找到模块图中可以安全地连接到单一模块的所有模块,来优化结果的体积。 -
usedExports(也称为 tree shaking):该选项用于标记 "tree shaking" 中未被使用的导出,使它们能被压缩工具删除。
在 Webpack 4 及以上版本中,这些优化默认在 mode
被设置为 production
时生效。通过合理地配置这些选项,开发者可以显著提高应用程序的加载和运行性能。这些优化通常包括减少 bundle 的体积和提高代码的运行时效率。在开发模式下,很多优化默认是关闭的,以提供更快的构建速度和更好的调试体验。
750.[webpack] optimize 配置中, 分割代码配置 splitChunks 怎么使用【热度: 546】【工程化】【出题公司: TOP100 互联网】
关键词:webpack 分割代码
在 webpack 中,splitChunks
选项是optimization
对象的一个属性,可以用来定义如何分割代码块。默认情况下,webpack 会将所有来自node_modules
的模块分割到一个叫做vendors
的 chunk 中,并且将共享或来自异步请求的模块分割成不同的 chunks。通过配置splitChunks
选项,你可以控制这些行为,创建更细致的代码分割策略。以下是如何使用splitChunks
来优化你的 bundle。
基本配置
module.exports = {
//...
optimization: {
splitChunks: {
chunks: "all", // 分割所有类型的chunks:初始和动态加载的chunk
},
},
};
在这个配置中,chunks: 'all'
指示 webpack 对同步和异步引入的模块都进行分割。webpack 会根据内部的一些默认标准(如模块大小、请求的 chunks 数目等)来决定是否分割一个模块。
基础属性配置
下面的表格详细描述了 splitChunks
配置选项及其作用:
配置选项 | 类型 | 默认值 | 说明 |
---|---|---|---|
chunks | 'all' , 'async' , 'initial' | 'async' | 设置优化哪些类型的 chunk。 |
minSize | Number | 20000 (20kb) | 生成 chunk 的最小体积(以字节为单位)。 |
maxSize | Number | 0 | 尝试将 chunk 分割成不大于指定体积的块。此选项正在实验中,并可能在将来的 webpack 版本中更改。 |
minChunks | Number | 1 | 模块被分享到的最少 chunk 数。 |
maxAsyncRequests | Number | 5 | 按需加载时的最大并行请求数。 |
maxInitialRequests | Number | 3 | 一个入口点的最大并行请求数。 |
automaticNameDelimiter | String | '~' | 用于生成名称的分隔符。 |
name | Boolean or String or Function | true | 分割块的名称。 |
cacheGroups | Object | - | 一个对象,它定义了对于.cacheGroups 的子选项,用来控制缓存组聚合和生成的 chunks。 |
cacheGroups.test | RegExp or Function | - | 控制哪些模块被这个缓存组捕捉。 |
cacheGroups.priority | Number | 0 | 缓存组点击时的优先级,数值越大,优先级越高。 |
cacheGroups.reuseExistingChunk | Boolean | true | 如果当前块包含已从主 bundle 分割的模块,则重用它。 |
cacheGroups.filename | String or Function | - | 允许为生成的 chunk 自定义文件名。 |
以下是针对上述表格中提及的某些属性的进一步说明:
-
chunks
选项指定是对哪些 chunks 应用这些优化措施。它可以是三个值之一:'all'会影响所有的 chunks,这使得在异步和非异步 chunks 之间共享模块成为可能;'async' 仅仅影响被异步加载的 chunks;'initial' 仅影响初始加载的 chunks。 -
minSize
和maxSize
用于控制 webpack 试图以多大的 chunk 为目标。minSize
可以避免 chunks 过小,而maxSize
可以帮助进一步分割大的 chunks。 -
cacheGroups
是配置高度定制化的代码分割策略的地方。默认情况下 webpack 会将来自node_modules
文件夹的代码分割到一个叫做vendors
的 chunk 中,另外 webpack 会将重复引入的代码分割到一个叫做default
的 chunk 中。在这里可以覆盖这些默认设置,或是增加新的缓存组。
使用实例:
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: "all",
minSize: 30000, // 最小 30kb
maxSize: 0, // 默认无上限
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: "~",
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name(module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `vendor.${packageName.replace("@", "")}`;
},
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
高级配置 - 缓存组
缓存组(cacheGroups)能让你对分割出来的 chunks 进一步细分和控制。
module.exports = {
//...
optimization: {
splitChunks: {
chunks: "all",
maxInitialRequests: Infinity, // 允许在一个入口处无限多的并行请求
minSize: 0, // 生成chunk的最小体积(以字节为单位)
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/, // 正则表达式,用于测试模块路径,匹配node_modules目录下的模块
name(module) {
// 得到模块名,可能是node_modules包名称的一部分
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `npm.${packageName.replace("@", "")}`; // 创建chunk名
},
},
},
},
},
};
这个配置创建了一个缓存组vendor
,它会将所有从node_modules
目录导入的模块分割到不同的 chunk 中,并为每个包创建一个以npm
开头的 chunk 名。例如,如果你的应用依赖于lodash
和react
,应用中就会有npm.lodash
和npm.react
两个额外的 chunks。
动态导入
当你使用像import()
这样的动态导入语法时,splitChunks
插件会自动进行代码分割。
function getComponent() {
// 当我们调用 import() 时,webpack 会对 lodash 进行代码分割
return import("lodash").then(({ default: _ }) => {
const element = document.createElement("div");
element.innerHTML = _.join(["Hello", "webpack"], " ");
return element;
});
}
getComponent().then((component) => {
document.body.appendChild(component);
});
在这个例子中,lodash
会被分成一个单独的 chunk。当getComponent
函数执行并调用import()
时,lodash
库会作为一个单独的异步 chunk 加载进来。
通过splitChunks
的适当配置,我们可以大幅度减小初始加载所需的时间,并确保用户只下载当前真正需要的代码,这样就可以加快应用程序的交互速度。
751.CSS 在 2023 迎来重大更新, 更新内容是什么【热度: 548】【CSS】【出题公司: TOP100 互联网】
关键词:CSS 2023 年重大更新
新特性非常多,总结在下面
架构基础
- 级联层
- 嵌套
- 作用域
- 选择器 :is() 和 :where()
- 选择器 :has()
- 复杂的第 n-. 选择
- CSS 三角函数
- 子网格 subgrid
排版
- 首字下沉
- 均衡和美观
颜色
- 高清色彩空间
- color-mix() 函数
- 相对颜色语法
- 响应浅色或深色模式的 light-dark() 函数
响应式设计
- 容器查询之尺寸查询
- 容器查询之样式查询
- 容器查询之状态查询
- 更新媒体查询
- 脚本媒体查询
- 降低透明度的媒体查询
- 媒体查询范围
交互动画
- 视图过渡
- 滚动驱动动效
- 离散属性动画
- @starting-style
- overlay
- 锚点定位
- 动画合成
- 缓动函数 linear()
- Scrollend 事件
- 滚动捕捉
752.webpack 的主要配置项有哪些【热度: 766】【工程化】【出题公司: TOP100 互联网】
关键词:webpack 主要配置项
Webpack 是一个现代 JavaScript 应用程序的静态模块打包器。配置文件名通常为 webpack.config.js
,它提供了一种配置 Webpack 的方式。下面是一些主要的 Webpack 配置选项:
-
entry: 入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。可以指定一个或多个入口起点。
-
output: output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为
./dist
。 -
module: module 属性用于决定如何处理项目中的不同类型的模块。
- rules: 配置模块的读取和解析规则,通常用来配置 loader。
-
resolve: 配置模块如何解析。
- extensions: 自动解析确定的扩展,此选项能够使用户在引入模块时不带扩展。
-
plugins: 插件是用来扩展 webpack 功能的。它们会在构建流程中的特定时机注入运行逻辑来改变构建结果或做你想要的事情。
-
devServer: 通过来自
webpack-dev-server
的这些选项能够对开发服务器的行为进行控制。 -
devtool: 此选项控制是否生成,以及如何生成 source map。
-
mode: 通过设置
development
或production
之中的一个,来为流程提供相应模式下的内置优化。 -
optimization: 包含一组可用来调整构建输出的选项。
- splitChunks: 配置模块的拆分,可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。
- runtimeChunk: 为每个 entry 创建一个运行时文件。
-
performance: 允许 webpack 根据某些参数,控制资产和入口起点的最大大小。
-
externals: 防止将某些 import 包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖。
每个项目的具体需求不同,Webpack 的配置也会有所不同。这些选项提供了强大的配置能力和灵活性,可以用来定制 Webpack 的打包、加载和转换行为。
753.[React] React 19 有哪些新特性?【热度: 879】【web 框架】【出题公司: TOP100 互联网】
关键词:React 19 新特性
作者总结上文的重点信息内容
React 19 的新功能
- 新型 hook:
useActionState
- React DOM:
<form>
Action - React DOM:新型 hook:
useFormStatus
- 新型 hook:
useOptimistic
- 新型 API:
use
React 服务器组件
- 服务器组件
- Server Action(服务器操作)
757.如何统计长任务时间、长任务执行次数【热度: 489】【web 应用场景】【出题公司: TOP100 互联网】
关键词:长任务统计
在 JavaScript 中,可以使用 Performance API 中的 PerformanceObserver 来监视和统计长任务(Long Task)。长任务是指那些执行时间超过 50 毫秒的任务,这些任务可能会阻塞主线程,影响页面的交互性和流畅性。
使用 PerformanceObserver 监听长任务
// 创建一个性能观察者实例来订阅长任务
let observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log("Long Task detected:");
console.log(`Task Start Time: ${entry.startTime}, Duration: ${entry.duration}`);
}
});
// 开始观察长任务
observer.observe({ entryTypes: ["longtask"] });
// 启动长任务统计数据的变量
let longTaskCount = 0;
let totalLongTaskTime = 0;
// 更新之前的性能观察者实例,以增加统计逻辑
observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
longTaskCount++; // 统计长任务次数
totalLongTaskTime += entry.duration; // 累加长任务总耗时
// 可以在这里添加其他逻辑,比如记录长任务发生的具体时间等
});
});
// 再次开始观察长任务
observer.observe({ entryTypes: ["longtask"] });
在上面的代码中,我们创建了一个PerformanceObserver
对象来订阅长任务。每当检测到长任务时,它会向回调函数传递一个包含长任务性能条目的列表。在这个回调中,我们可以统计长任务的次数和总耗时。
注意:PerformanceObserver
需要在支持该 API 的浏览器中运行。截至到我所知道的信息(2023 年 4 月的知识截点),所有现代浏览器都支持这一 API,但在使用前你应该检查用户的浏览器是否支持这个特性。
以下是如何在实际使用中停止观察和获取当前的统计数据:
// 停止观察能力
observer.disconnect();
// 统计数据输出
console.log(`Total number of long tasks: ${longTaskCount}`);
console.log(`Total duration of all long tasks: ${totalLongTaskTime}ms`);
使用这种方法,你可以监控应用程序中的性能问题,并根据长任务的发生频率和持续时间进行优化。
759.前端如何做 页面主题色切换【热度: 538】【web 应用场景】【出题公司: TOP100 互联网】
关键词:主题色切换
页面主题色切换通常涉及到修改网页中的颜色方案,以提供不同的视觉体验,例如从明亮模式切换到暗黑模式。实现这一功能,可以通过配合使用 CSS、JavaScript 和本地存储来进行。以下是实施页面主题色切换的几种方法:
使用 CSS 自定义属性
- 定义一套主题变量:
:root {
--primary-color: #5b88bd; /* 明亮主题色 */
--text-color: #000; /* 明亮主题文本颜色 */
}
[data-theme="dark"] {
--primary-color: #1e2a34; /* 暗黑主题色 */
--text-color: #ccc; /* 暗黑主题文本颜色 */
}
- 应用自定义属性到 CSS 规则中:
body {
background-color: var(--primary-color);
color: var(--text-color);
}
- 使用 JavaScript 动态切换主题:
function toggleTheme() {
const root = document.documentElement;
if (root.dataset.theme === "dark") {
root.dataset.theme = "light";
} else {
root.dataset.theme = "dark";
}
}
使用 CSS 类切换
- 为每个主题创建不同的 CSS 类:
.light-theme {
--primary-color: #5b88bd;
--text-color: #000;
}
.dark-theme {
--primary-color: #1e2a34;
--text-color: #ccc;
}
- 手动切换 CSS 类:
function toggleTheme() {
const bodyClass = document.body.classList;
if (bodyClass.contains("dark-theme")) {
bodyClass.replace("dark-theme", "light-theme");
} else {
bodyClass.replace("light-theme", "dark-theme");
}
}
使用 LocalStorage 记录用户主题偏好
// 当用户切换主题时
function saveThemePreference() {
localStorage.setItem("theme", document.body.classList.contains("dark-theme") ? "dark" : "light");
}
// 页面加载时应用用户偏好
function applyThemePreference() {
const preferredTheme = localStorage.getItem("theme");
if (preferredTheme === "dark") {
document.body.classList.add("dark-theme");
} else {
document.body.classList.remove("dark-theme");
}
}
applyThemePreference();
使用媒体查询自动应用暗黑模式
某些现代浏览器支持 CSS 媒体查询prefers-color-scheme
。你可以使用这个特性来自动根据用户的系统设置应用暗黑模式或明亮模式,而无须 JavaScript:
@media (prefers-color-scheme: dark) {
:root {
--primary-color: #1e2a34; /* 暗黑主题色 */
--text-color: #ccc; /* 暗黑主题文本颜色 */
}
}
@media (prefers-color-scheme: light) {
:root {
--primary-color: #5b88bd; /* 明亮主题色 */
--text-color: #000; /* 明亮主题文本颜色 */
}
}
通过以上方法,开发人员能够为前端页面提供灵活的主题色切换功能,从而增强用户体验。
资深开发者相关问题【共计 1 道题】
758.前端视角 - 如何保证系统稳定性【热度: 566】【工程化】【出题公司: TOP100 互联网】
关键词:稳定性
前端视角来做稳定性, 本是一个开放性话题,这里没有统一的解法, 作者在此提供几个思路和反向:
- 静态资源多备份(需要有备份)
- 首屏请求缓存
- 请求异常报警
- 页面崩溃报警
- E2E 定时全量跑用例
转载自:https://juejin.cn/post/7371716384848592947