前端经典面试合集(二)——Vue/React/Node/工程化工具/计算机网络
1. 说说 Vue 中的 Diff 算法
Vue 的 Diff 算法 主要用于优化虚拟 DOM 和实际 DOM 之间的比较过程。它通过以下几种策略来提高性能:
- 最小化对 DOM 的操作:Vue 通过在内存中构建一个虚拟 DOM 树,在虚拟 DOM 树与真实 DOM 树之间进行比较和更新,这样就避免了频繁的直接操作 DOM,提高了性能。
- 异步更新:Vue 会对数据变化进行异步更新,并且对多次更新进行批量处理,减少了不必要的 DOM 更新。
- Key 优化:当更新列表时,Vue 使用
key
来标识每个元素,避免在排序或重新渲染时产生不必要的 DOM 操作。key
有助于 Vue 精确地追踪每个节点,做到最小的 DOM 操换。 - 节点的就地复用:Vue 在进行虚拟 DOM 比较时,会尽可能复用现有节点,而不是删除旧节点并重新创建新的节点,减少性能开销。
在 Vue 2.x 中,Vue 使用的是 最小化差异比较算法(即基于两个树进行对比),它使用了 双指针算法 来遍历不同的节点,并找到它们之间的差异。
2. Vue 模板是如何编译的? 经历了哪些过程?
Vue 模板的编译过程分为两个阶段:
1. 解析阶段(Parsing)
- 模板解析:Vue 将模板字符串解析成一个抽象语法树(AST)。在此阶段,Vue 会对模板中的 HTML 标签、指令(如
v-bind
,v-for
,v-if
)等进行解析,形成 AST 树结构。 - 优化阶段:Vue 会分析静态节点(不会变化的节点),标记出这些静态部分。在更新时,静态部分不需要重新渲染,进一步提高性能。
2. 生成阶段(Code Generation)
- 生成渲染函数:Vue 将优化后的 AST 转换成渲染函数。该渲染函数最终会被执行,生成虚拟 DOM。
在此过程后,Vue 模板编译得到一个渲染函数,这个函数会根据数据的变化动态生成虚拟 DOM。
3. Vue 中 computed 和 watch 区别? 分别适用于什么场景?
computed
-
定义:
computed
是计算属性,基于它们的依赖进行缓存,只有当相关依赖发生变化时,才会重新计算。 -
特点:
- 缓存:只要依赖的响应式数据没有变化,计算属性的值就会被缓存,不会每次都重新计算。
- 简洁:适合处理复杂的逻辑,通常用于基于数据的计算。
-
适用场景:当你需要基于某些数据的变化来计算一个值,并且该值的计算过程有缓存需求时。
watch
-
定义:
watch
用于观察某个数据的变化,执行相应的副作用操作。它不像computed
那样是一个直接返回值的计算过程,而是执行一些操作。 -
特点:
- 异步处理:可以在数据变化时触发副作用,比如发送 API 请求、更新其他数据等。
- 没有缓存:每次数据变化都会触发
watch
中的回调。
-
适用场景:当你需要对某个数据变化进行额外的处理,或者执行一些副作用(例如,异步操作、DOM 操作等)时。
总结:
computed
主要用于 计算属性,且具有缓存特性,适合需要依赖计算并且返回值的场景。watch
适合处理需要执行副作用的情况,比如异步请求、深度监听等。
4. 什么是 Vuex? 使用 Vuex 有哪些好处?
Vuex 是一个 状态管理库,用于在 Vue 应用中管理全局状态。它帮助你将状态集中管理,确保所有组件以统一的方式来访问和更新状态。Vuex 的核心概念包括:
- State:存储应用的状态。
- Getters:从 State 中派生出的状态,类似于计算属性。
- Mutations:同步修改 State 的方法。
- Actions:可以包含异步操作的函数,通常用于调用 Mutations。
- Modules:将 Store 分割成多个模块,每个模块拥有自己的 state、mutations、actions 和 getters。
Vuex 的好处:
- 集中式管理:通过 Vuex 管理应用的状态,使得状态管理更加清晰、统一。
- 状态共享:多个组件可以共享状态,避免了复杂的 props 和 events 传递。
- 易于调试:Vuex 提供了插件来帮助调试状态的变化。
- 与 Vue 紧密集成:Vuex 与 Vue 完美集成,支持热重载、调试等特性。
5. Vue Router 的 $route
和 $router
对象有什么区别?
-
$route
:是 当前路由信息,它包含了关于当前路由的所有信息,如path
、params
、query
、hash
等。你可以通过$route
获取当前页面的路由信息。console.log(this.$route.path); // 当前路由的路径
-
$router
:是 路由实例,包含了控制路由跳转的方法,如push
、replace
、go
、back
等。通过$router
可以改变路由,进行页面跳转。this.$router.push('/new-route'); // 跳转到新的路由
总结:
$route
是当前路由的状态,包含当前路由的相关信息。$router
是 Vue Router 的路由实例,用来操作路由(跳转等)。
6. Vue Router 路由有哪些模式? 各模式有什么区别?
Vue Router 提供了两种主要的路由模式:
-
Hash模式(默认模式):
- 使用 URL 中的 hash (
#
) 来表示路由状态。例如:http://example.com/#/home
。 - 由于
#
后面的内容不会发送给服务器,所以可以实现前端路由跳转。 - 优点:兼容所有浏览器,不需要服务器配置。
- 缺点:URL 中带有
#
,不够美观。
- 使用 URL 中的 hash (
-
History模式:
- 使用 HTML5 的
history.pushState()
和history.replaceState()
来改变路由,而不会重新加载页面。路由的路径看起来像普通的 URL,如http://example.com/home
。 - 优点:没有
#
,URL 更加美观。 - 缺点:需要后端支持,服务器需要配置返回同一个 HTML 文件,以便 Vue Router 在浏览器端处理路由。
- 使用 HTML5 的
7. React 中的路由懒加载是什么? 原理是什么?
路由懒加载 是指仅在用户访问某个特定路由时,才加载该路由对应的组件,避免在页面加载时一次性加载所有组件,从而提高页面加载速度。
原理:
React 提供了 React.lazy
和 Suspense
来实现路由懒加载。React.lazy
允许动态加载组件,而 Suspense
组件用于在等待加载时展示一个加载状态。
示例代码:
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';const Home = lazy(() => import('./Home')); // 懒加载 Home 组件function App() {return (<Router><Suspense fallback={<div>Loading...</div>}><Switch><Route path="/home" component={Home} /></Switch></Suspense></Router>);
}
优点:
- 提高了页面加载速度,减少初始加载时的资源消耗。
- 只有在用户访问该路由时,相关组件才会被加载。
8. 你常用的 React Hooks 有哪些?
常用的 React Hooks 包括:
-
useState
:用于声明组件的状态。const [count, setCount] = useState(0);
-
useEffect
:用于执行副作用操作,如数据获取、订阅等。useEffect(() => {// 代码逻辑 }, [dependencies]); // 当 dependencies 变化时会执行
-
useContext
:用于在组件
树中访问 context。
const value = useContext(MyContext);
-
useRef
:用于获取对 DOM 元素或其他数据的引用。const myRef = useRef(null);
-
useMemo
:用于缓存值,避免不必要的计算。const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
-
useCallback
:用于缓存回调函数,避免因父组件重新渲染导致子组件不必要的重新渲染。const memoizedCallback = useCallback(() => { /* code */ }, [dependencies]);
-
useReducer
:用于管理复杂的状态逻辑,通常与useState
替代。const [state, dispatch] = useReducer(reducer, initialState);
这些 Hooks 可以帮助开发者简化组件的状态管理和副作用操作,提高代码的可维护性和可读性。
1. React 组件间怎么进行通信?
React 组件间的通信方式主要有以下几种:
1. 父子组件通信
- Props:父组件通过
props
向子组件传递数据,子组件通过props
接收数据并渲染。props
是单向数据流。
// 父组件
<ChildComponent name="Alice" />// 子组件
function ChildComponent(props) {return <div>Hello, {props.name}</div>;
}
2. 子父组件通信
- 回调函数:子组件通过回调函数将数据传递给父组件,父组件将回调函数作为
props
传递给子组件。
// 父组件
function ParentComponent() {const handleChildData = (data) => {console.log(data);};return <ChildComponent onData={handleChildData} />;
}// 子组件
function ChildComponent(props) {return (<button onClick={() => props.onData('Hello from child!')}>Send Data</button>);
}
3. 兄弟组件通信
- 通过父组件传递数据:兄弟组件之间通过将共享的数据传递到父组件,父组件再通过
props
传递给另一子组件。 - React Context API:React Context 用于跨层级共享数据,不需要通过一层层的
props
传递。
4. 全局状态管理
- Redux / MobX / Zustand:通过这些状态管理库,可以将组件的状态集中管理,任何组件都可以通过订阅和派发 actions 来共享状态。
- React Context:React 自带的 Context API 也可以作为简单的全局状态管理工具。
2. React.memo() 和 useMemo() 的用法是什么,有哪些区别?
React.memo()
- 用途:
React.memo()
是一个高阶组件,用于优化函数组件的渲染。当组件的props
没有发生变化时,React.memo()
会阻止重新渲染,从而提高性能。 - 用法:
const MyComponent = React.memo(function MyComponent(props) {return <div>{props.name}</div>;
});
- 适用场景:当组件的
props
没有变化时,避免重复渲染(尤其是在列表、表格等渲染频繁的场景)。
useMemo()
- 用途:
useMemo()
是一个 Hook,用于缓存计算结果,避免在每次渲染时重复执行高计算量的操作。 - 用法:
const memoizedValue = useMemo(() => expensiveFunction(a, b), [a, b]);
- 适用场景:适用于需要缓存某个计算结果的场景,比如依赖复杂计算或多次重复计算的值。
区别:
React.memo()
用于缓存组件的渲染结果,防止因props
不变而重新渲染。useMemo()
用于缓存函数的计算结果,防止在每次渲染时执行重复的计算。
3. 说说你对 TypeScript 的理解? 与 JavaScript 的区别?
TypeScript 的理解:
TypeScript 是 JavaScript 的一个超集,添加了静态类型检查,允许开发者在开发阶段捕捉到类型错误。它编译成标准的 JavaScript,并可以直接运行在任何支持 JavaScript 的环境中。
与 JavaScript 的区别:
- 类型系统:TypeScript 引入了静态类型,开发者可以显式地定义变量、函数、对象的类型,从而避免许多运行时错误。
- 类型推断:TypeScript 提供了类型推断,即使不显式指定类型,TypeScript 也能根据上下文推断出类型。
- 编译:TypeScript 代码需要通过 TypeScript 编译器(
tsc
)转译成 JavaScript 代码,而 JavaScript 是直接可以执行的。 - 面向对象支持:TypeScript 提供了对类(Class)、接口(Interface)、泛型(Generics)等的更好支持。
4. TypeScript 的内置数据类型有哪些?
TypeScript 提供了丰富的数据类型,常见的有:
-
基本数据类型:
number
:所有的数字类型(包括整数和浮点数)。string
:字符串类型。boolean
:布尔类型,true
或false
。symbol
:唯一且不可变的原始数据类型(ES6 引入)。null
:表示“没有值”的类型。undefined
:表示“未定义”的类型。
-
复杂数据类型:
Array
:数组类型,可以是特定类型的元素数组。Tuple
:元组类型,表示固定大小的数组,且元素类型可以不同。Object
:对象类型,用来表示非原始类型。any
:任意类型,绕过类型检查,使用时需要小心。void
:表示函数没有返回值。never
:表示从不返回的类型(例如,抛出异常的函数类型)。
5. TypeScript 中的 Declare 关键字有什么用?
declare
用于声明一个变量、类、函数或模块的类型,而不提供具体的实现。它通常用于声明外部库、全局变量等,并且在编译时不会生成 JavaScript 代码。
例如:
declare const someGlobalVar: string;
在上面的代码中,declare
告诉 TypeScript 编译器,someGlobalVar
是一个全局变量,并且它的类型是 string
,但它的实现会在运行时提供。
6. 什么是 TypeScript 中的命名空间和模块? 两者有什么区别?
命名空间:
命名空间(namespace
)是 TypeScript 中的一种组织代码的方式,它通过将相关功能封装到命名空间中来避免命名冲突。命名空间通常用于大型应用中的内部模块,特别是在没有模块化系统(如 CommonJS 或 ES Modules)的情况下。
namespace MyNamespace {export function greet() {console.log('Hello');}
}
模块:
模块(module
)是 TypeScript 中用来分割代码的机制。它允许将代码划分为多个文件,并且每个文件都是一个模块。模块中的成员默认是私有的,只有通过 export
关键字才能暴露。
// module.ts
export function greet() {console.log('Hello');
}
区别:
- 命名空间:用于组织和封装代码,通常适用于全局范围内的代码组织,尤其在没有模块化支持的环境下。
- 模块:用于将代码分割成多个文件,并使用
import
和export
来导入和导出功能。模块支持 ES6 和 CommonJS 等模块化系统,通常在较现代的前端和后端开发中使用。
7. 说说你对 Node.js 的理解? 优缺点? 应用场景?
Node.js 的理解:
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,它允许使用 JavaScript 编写服务器端代码。Node.js 是非阻塞、事件驱动的,非常适合 I/O 密集型的应用。
优点:
- 高效的异步 I/O:Node.js 使用事件驱动和非阻塞 I/O 模型,可以高效地处理大量并发请求。
- JavaScript 全栈开发:前后端使用相同的语言(JavaScript),便于开发人员统一技术栈。
- 大量的 npm 包:Node.js 拥有世界上最大的开源包管理器
npm
,为开发者提供了丰富的库和工具。 - 实时应用:非常适合实时应用(如聊天应用、实时协作工具等)。
缺点:
- 单线程:虽然 Node.js 可以通过异步非阻塞 I/O 高效处理并发,但它依然是单线程的,计算密集型任务可能导致性能瓶颈。
- 回调地狱:由于使用回调函数来处理异步操作,可能导致代码难以维护,幸好有
Promise
和async/await
可以改善这个问题。
应用场景:
- 实时应用(如聊天应用、在线游戏)。
- API 服务:Node.js 非常适合构建 RESTful API 或 GraphQL API。
- 流媒体处理:如视频流、音频流处理等。
- **
微服务架构**:由于其轻量级和高效性,Node.js 在微服务架构中得到广泛应用。
8. 什么是 Node.js 中的 process? 它有哪些方法和应用场景?
process
是 Node.js 的全局对象,提供了关于当前 Node.js 进程的相关信息和控制。它可以访问系统环境、进程的输入输出、退出状态等。
常用方法:
process.argv
:返回命令行参数。process.env
:返回环境变量。process.exit()
:退出当前 Node.js 进程。process.on('exit', callback)
:监听进程退出事件。process.stdout
、process.stderr
:向标准输出或标准错误输出数据。
应用场景:
- 获取和设置环境变量。
- 处理命令行参数。
- 在应用退出时做一些清理工作,如关闭数据库连接。
9. 什么是 npm? 你用过哪些 npm 包? 是否开发过自己的 npm 包?
npm(Node Package Manager)是 Node.js 的包管理工具,用于管理和发布 JavaScript 的第三方库和工具。它帮助开发者快速安装、更新和管理项目中的依赖。
常用 npm 包:
- express:用于构建 Web 服务器的框架。
- lodash:提供常用的 JavaScript 工具函数库。
- axios:用于发送 HTTP 请求的库。
- react 和 react-dom:用于构建前端应用的核心库。
- webpack:用于模块打包的工具。
开发 npm 包:
开发自己的 npm 包时,可以通过 npm init
创建一个新的项目,并使用 npm publish
将包发布到 npm registry 中。发布时需要提供包的名称、版本和描述等信息。
10. 什么是 Node.js 的事件循环机制? 它是怎么实现的?
Node.js 使用 事件循环(Event Loop)机制来处理异步 I/O 操作。Node.js 是基于单线程的,但它通过事件循环模型来处理并发操作,避免了传统线程模型中的开销。
事件循环的工作流程:
- 执行栈:执行 JavaScript 代码(同步代码)时,任务会被放入执行栈中。
- 事件队列:异步任务的回调函数会被放入事件队列中,等待执行。
- 事件循环:Node.js 的事件循环不断地从事件队列中取出任务,并将其放入执行栈执行。
事件循环的阶段:
事件循环包含多个阶段,包括定时器(Timers)、I/O 回调(I/O callbacks)、定时器队列(setImmediate)、关闭回调(close callbacks)等。每个阶段会根据优先级执行队列中的任务。
事件循环确保异步操作不会阻塞主线程,使得 Node.js 能够高效处理大量并发请求。
这些是关于前端开发和 Node.js 的一些常见问题与解答,希望能够帮助你深入理解这些技术。
1. Node.js 有哪些全局对象? 它们分别有什么作用?
Node.js 提供了一些全局对象,可以在任何模块中直接访问。常见的全局对象有:
-
global
:在 Node.js 中,global
是一个全局作用域对象,类似于浏览器中的window
对象。所有模块都可以通过global
访问到这个全局对象。global.myVar = 'Hello';
-
process
:提供关于当前 Node.js 进程的信息和控制方法。可以用来获取命令行参数、环境变量、控制进程的输入输出等。process.argv
:命令行参数。process.exit()
:退出进程。process.env
:环境变量。
-
__dirname
:当前模块文件所在目录的绝对路径。console.log(__dirname);
-
__filename
:当前模块文件的完整路径(包括文件名)。console.log(__filename);
-
require
:用于引入其他模块,Node.js 的模块加载系统。你可以加载本地模块、第三方模块或内置模块。const fs = require('fs');
-
module
:表示当前模块的状态。module.exports
用于导出模块内容,module.id
用于获取当前模块的唯一标识。 -
setTimeout
和setInterval
:用于设定延迟调用和定时调用。 -
Buffer
:用于操作二进制数据,特别是在处理文件和网络请求时。
2. 怎么调试 Node.js 程序?
调试 Node.js 程序有多种方式:
-
使用
console.log()
调试- 最常见的调试方法是通过
console.log()
打印变量或信息,查看程序执行情况。
- 最常见的调试方法是通过
-
Node.js 内建调试工具
- 使用
node inspect <filename>
启动调试模式,可以在命令行中进行调试。node inspect app.js
- 也可以在 Chrome 浏览器的 DevTools 中进行调试,使用
node --inspect-brk <filename>
启动并在浏览器中进行断点调试。node --inspect-brk app.js
- 然后访问
chrome://inspect
连接调试器。
- 使用
-
VSCode 调试
- VSCode 提供强大的调试支持,可以直接在编辑器中设置断点、单步执行、查看变量等。需要配置
launch.json
文件。
- VSCode 提供强大的调试支持,可以直接在编辑器中设置断点、单步执行、查看变量等。需要配置
-
使用第三方调试工具
- nodemon:自动重启应用,适合开发环境中实时调试。
- debug:一个流行的调试库,允许你有条件地打印调试信息。
3. 介绍下从 HTTP/1.0、HTTP/1.1 到 HTTP/2 再到 HTTP/3 的演化过程,各个阶段相对前一阶段做了哪些优化?
HTTP/1.0:
- 请求/响应模型:每次 HTTP 请求都会打开一个新的 TCP 连接,完成后关闭,造成连接开销较大。
- 无持久连接:每次请求都要重新建立连接,浪费了大量的资源和时间。
- 无流水线处理:HTTP/1.0 不能同时发送多个请求,必须等前一个请求响应完再发送下一个请求。
HTTP/1.1(优化版 HTTP/1.0):
- 持久连接:默认开启持久连接(
Connection: keep-alive
),请求和响应可以在同一连接上多次传输。 - 管道化(Pipelining):可以在一个 TCP 连接上并行发送多个请求,但必须按顺序响应,仍然存在队头阻塞问题。
- 分块传输编码:解决了响应内容长度不确定的情况,可以一边传输一边接收数据。
HTTP/2(基于 HTTP/1.1 进一步优化):
- 多路复用:可以在一个连接上并行处理多个请求和响应,解决了 HTTP/1.1 中的队头阻塞问题。
- 头部压缩:使用 HPACK 算法对请求头进行压缩,减少数据传输量。
- 服务器推送:服务器可以主动推送资源到客户端,而不是等客户端请求资源。
- 二进制协议:HTTP/2 使用二进制格式传输数据,相比 HTTP/1.1 的文本格式更高效。
HTTP/3(基于 QUIC 协议):
- 基于 QUIC 协议:HTTP/3 使用 Google 的 QUIC(Quick UDP Internet Connections)协议,替代了 TCP,使用 UDP 来建立连接。
- 减少连接建立延迟:QUIC 支持 0-RTT 和 1-RTT 连接建立,减少了网络延迟。
- 更强的拥塞控制:QUIC 协议具有更高效的拥塞控制和恢复机制。
- 内置加密:所有 HTTP/3 请求都加密,无需额外的 TLS 握手过程。
总结:
- HTTP/1.0 → HTTP/1.1:主要优化了连接复用和请求响应机制。
- HTTP/1.1 → HTTP/2:引入多路复用和头部压缩,减少了延迟和带宽消耗。
- HTTP/2 → HTTP/3:从 TCP 协议转向基于 UDP 的 QUIC 协议,进一步减少连接延迟并增强性能。
4. DNS HTTP 缓存有哪些实现方式? 什么是协商缓存和强制缓存?
DNS 缓存:
- 本地 DNS 缓存:操作系统和浏览器都能缓存域名解析结果,减少 DNS 查询次数,提高性能。
- DNS 记录缓存:DNS 服务器会缓存查询过的域名解析结果(例如,TTL),减少后续查询的延迟。
HTTP 缓存:
HTTP 缓存有两种方式:强制缓存和协商缓存。
强制缓存:
- 强制缓存是指资源在缓存中存在且没有过期,浏览器直接使用缓存而不发送请求。
- 常见的强制缓存机制:
Cache-Control
和Expires
。Cache-Control: max-age=3600
:资源会在缓存中保存 3600 秒。Expires
:指定缓存的过期时间。
协商缓存:
- 协商缓存是在缓存过期后,通过向服务器发送请求,确认资源是否有更新。如果资源没有变化,服务器返回
304 Not Modified
状态码,浏览器可以继续使用缓存。 - 常见的协商缓存机制:
Last-Modified
和ETag
。Last-Modified
:服务器返回资源最后修改时间,客户端下次请求时带上If-Modified-Since
,服务器根据该时间判断是否返回缓存。ETag
:资源的唯一标识符,客户端带上If-None-Match
头部,服务器根据ETag
判断资源是否更新。
5. 简述 TCP/IP 网络模型,分为几层? 每层的职责和作用是什么?
TCP/IP 网络模型分为 4 层:
-
应用层:
- 提供应用程序与网络通信的接口。
- 包括 HTTP、FTP、DNS、SMTP 等协议。
-
传输层:
- 负责数据的可靠传输。
- 主要协议有 TCP(可靠、面向连接)和 UDP(不可靠、无连接)。
-
网络层:
- 负责数据包的路由和转发,确保数据包从源主机传输到目的主机。
- 主要协议有 IP、ICMP、ARP 等。
-
数据链路层:
- 负责在物理设备之间传输数据帧,并处理硬件地址和纠错等问题。
- 主要协议有 Ethernet、PPP、HDLC 等。
6. 什么是 webpack? 它有什么作用?
Webpack 是一个模块化打包工具,用于将 JavaScript、CSS、图片等资源打包成浏览器可以加载的静态文件。
主要作用:
- 模块化:Webpack 支持将 JavaScript、CSS、图片等资源视为模块,提供模块化打包功能。
- 代码分割:Webpack 允许将代码分割成多个文件,提高加载速度。
- 自动化构建:Webpack 可以自动化处理文件压缩、优化、合并等任务。
- 加载器(Loaders):Webpack 使用加载器来
处理不同类型的文件(如 Sass、TypeScript 等)。
- 插件(Plugins):Webpack 提供插件机制来进行额外的任务,比如压缩代码、提取公共模块等。
7. 如何提高 webpack 的打包速度?
提高 Webpack 打包速度的几种方法:
- 使用
cache
配置:启用缓存,减少重复打包的时间。 - 使用多线程:使用
thread-loader
或parallel-webpack
并行处理构建任务。 - 合理配置
exclude
:避免对不必要的文件进行编译,比如 node_modules。 - 按需加载:使用代码分割(
splitChunks
)来减小打包体积。 - 优化插件和加载器配置:避免不必要的插件和加载器,尤其是对大型文件的处理。
- 升级 Webpack 版本:Webpack 5 相比 4 版本优化了构建性能。
8. 什么是 webpack 的热更新? 它的实现原理是什么?
热模块替换(HMR):Webpack 的热更新功能,即热模块替换,是一种在应用运行时动态替换模块而不需要重新加载页面的技术。
原理:
- 在开发模式下,Webpack 启动开发服务器(如
webpack-dev-server
)。 - Webpack 监控文件的变化,当文件发生变化时,Webpack 会将更新的模块推送到浏览器。
- 浏览器通过 WebSocket 连接接收到模块的更新,并动态替换页面中的模块,而不重新加载整个页面。
- 这样可以保持应用状态,同时加快开发过程中的反馈速度。
9. 什么是前后端分离? 它有什么优点和缺点?
前后端分离是指前端和后端开发通过 API 进行交互,前端和后端可以独立开发和部署。
优点:
- 开发效率高:前后端可以并行开发,不受对方开发进度影响。
- 技术栈灵活:前后端可以使用不同的技术栈,前端可以使用 React、Vue 等,后端可以使用 Node.js、Java、Python 等。
- 可扩展性强:前后端可以独立扩展和维护,容易支持多端应用(Web、Mobile)。
缺点:
- 跨域问题:前后端分离需要解决跨域请求问题,通常通过 CORS 或代理服务器来解决。
- 接口管理复杂:前后端需要共同约定接口规范,避免出现数据不一致或接口不兼容问题。
10. 你用过哪些包管理工具? 它们各有什么特点?
常见包管理工具:
-
npm(Node Package Manager)
- 最流行的 Node.js 包管理工具。
- 官方默认的包管理工具,拥有庞大的包生态。
- 支持版本控制和依赖管理。
-
Yarn
- Facebook 开发的包管理工具,兼容 npm。
- 提供更快速的安装速度和更稳定的版本锁定。
- 支持并行安装和离线缓存。
-
pnpm
- 一个高效的包管理器,使用硬链接技术来共享依赖,提高磁盘利用率。
- 相比 npm 和 Yarn,安装速度更快,减少磁盘空间占用。
-
Bower(已不再推荐使用)
- 前端包管理工具,主要用于管理前端依赖。
- 已被废弃,推荐使用 npm 或 Yarn 代替。
希望这些答案能帮助你更好地理解和解决相关问题。如果有其他问题,欢迎继续提问!
1. 什么是 CSS 工程化? 你用过哪些相关的工具?
CSS 工程化是指通过一些工具、方法和流程规范化 CSS 的开发与管理,提升开发效率、代码可维护性以及性能优化。它关注的主要问题包括代码的组织、模块化、自动化处理等。
常见的 CSS 工程化工具和方法包括:
- CSS 预处理器:如 Sass、LESS 和 Stylus,它们提供了变量、嵌套、函数、混入等功能,使得 CSS 更加灵活和模块化。
- CSS 构建工具:如 PostCSS,用于自动化处理任务,如自动加前缀(通过 autoprefixer)、压缩 CSS、合并 CSS 等。
- CSS 模块化:使用如 CSS Modules 或 Styled-components(在 React 中)来实现样式的局部作用域,避免样式冲突。
- BEM(块元素修饰符)方法论:通过规范化 CSS 类名来提高代码可读性和可维护性。
- CSS in JS:将 CSS 写入 JavaScript 中,动态生成样式,常见的库有 styled-components(React)和 Emotion。
- 工具链:使用 Webpack、Gulp、Grunt 等构建工具来自动化处理 CSS 任务,如样式压缩、合并、图片优化等。
2. 说说常规的前端性能优化手段
常规的前端性能优化手段包括:
-
资源压缩与合并:
- 使用 Webpack、Gulp 等工具压缩 JS、CSS 和图片文件。
- 合并多个 JS 或 CSS 文件,减少 HTTP 请求。
-
代码分割和懒加载:
- 对 JavaScript 和 CSS 进行代码分割,按需加载,减少首屏加载时间。
- 使用 React Lazy、Vue Async Component 等实现懒加载。
-
缓存控制:
- 设置 HTTP 缓存头(
Cache-Control
、ETag
)来缓存资源,避免重复请求。 - 使用 Service Worker 实现离线缓存,进一步提高性能。
- 设置 HTTP 缓存头(
-
图片优化:
- 压缩图片,使用合适的图片格式(如 WebP)和尺寸。
- 使用 srcset 和 picture 标签实现响应式图片加载。
-
减少 DOM 操作和重绘回流:
- 减少 DOM 操作次数,批量修改 DOM 节点。
- 避免不必要的 CSS 动画,减少页面的回流和重绘。
-
延迟加载和异步加载:
- 使用
defer
和async
属性异步加载 JS 文件,避免阻塞渲染。 - 实现 图片懒加载,延迟加载页面中的图片和媒体资源。
- 使用
-
减少第三方库和插件的使用:
- 精简不必要的第三方库或插件,避免引入过多的代码和依赖。
3. 前端性能优化指标有哪些? 怎么进行性能检测?
常见的前端性能优化指标包括:
-
首屏渲染时间(First Paint/FCP):
- 页面从开始加载到呈现出第一个内容的时间。
-
可交互时间(Time to Interactive, TTI):
- 页面完全加载并且响应用户输入的时间。
-
页面加载时间(Page Load Time):
- 页面完全加载并且呈现完毕的时间。
-
资源加载时间:
- 单个资源(如 JS、CSS、图片等)的加载时间。
-
内存使用情况:
- 页面运行时的内存消耗,过高的内存使用会导致性能下降。
-
回流和重绘次数:
- 页面布局变化和重新渲染的次数,频繁的回流和重绘会降低页面性能。
性能检测工具:
- Chrome DevTools:提供了多种性能监控和优化工具,包括网络请求监控、页面渲染过程分析、内存分析等。
- Lighthouse:Google 提供的自动化网站性能评估工具,可以分析网页的性能、可访问性、SEO 等。
- WebPageTest:可以测试网页加载速度,提供详细的性能报告。
- GTmetrix:提供网站性能检测,包括资源加载时间、页面速度等分析。
- Bundle Analyzer:Webpack 插件,用于分析项目打包后的资源体积,找出可能优化的部分。
4. DNS 预解析是什么? 怎么实现?
DNS 预解析是通过提前解析域名来加速页面加载过程的技术。在用户访问页面时,浏览器可以通过提前查询外部资源(如图片、字体、JS 文件等)域名的 IP 地址,减少请求资源时的 DNS 查找延迟。
实现方法:
-
在 HTML 中使用
<link rel="dns-prefetch" href="https://example.com">
来提前解析域名。<link rel="dns-prefetch" href="https://fonts.gstatic.com"> <link rel="dns-prefetch" href="https://example.com">
-
这种技术适用于访问多个外部资源的场景,可以显著提高加载速度。
5. 怎么进行站点内的图片性能优化?
站点内的图片性能优化可以通过以下几种方式实现:
-
选择合适的图片格式:
- 使用 WebP 格式来替代 JPG 或 PNG,以达到更高的压缩率和更小的文件大小。
- 对于简单的图标,使用 SVG 格式,它是一种矢量图形格式,支持无损缩放,文件大小小。
-
图片压缩:
- 使用工具如 ImageOptim、TinyPNG、Squoosh 等压缩图片文件大小。
-
响应式图片:
- 使用
srcset
属性和<picture>
元素来根据设备屏幕大小、分辨率加载合适的图片。
<img src="image.jpg" srcset="image-320w.jpg 320w, image-480w.jpg 480w, image-800w.jpg 800w" alt="example">
- 使用
-
图片懒加载:
- 使用
loading="lazy"
属性来延迟加载页面中的图片,尤其是那些位于屏幕外的图片。
<img src="image.jpg" loading="lazy" alt="example">
- 使用
-
图片裁剪和缩放:
- 在上传图片时,避免上传过大的图片。通过前端或服务器端裁剪和缩放图片,确保它们的尺寸适合展示。
6. SPA(单页应用)首屏加载速度慢怎么解决?
SPA 首屏加载速度慢的问题可以通过以下几种方式优化:
-
代码分割:
- 使用 Webpack 的代码分割(
splitChunks
)功能,将应用分成多个小块,按需加载,减少首屏加载时的 JS 文件体积。 - 动态导入(
import()
)来实现懒加载,只有用户访问到某个路由时才加载相应的代码。
- 使用 Webpack 的代码分割(
-
懒加载路由组件:
- 对每个路由的组件进行懒加载,使用 Vue 或 React 中的路由懒加载特性,按需加载组件。
const Home = () => import('./views/Home.vue');
-
服务端渲染(SSR):
- 使用 Nuxt.js(Vue)或 Next.js(React)等框架实现服务端渲染,提前将 HTML 渲染到服务器,减少首屏加载时间。
-
减少阻塞渲染的资源:
- 异步加载 JS 文件,使用
async
或defer
属性避免阻塞 HTML 渲染。 - 尽量将 CSS 和 JS 文件分离,减少 CSS 阻塞的情况。
- 异步加载 JS 文件,使用
7. git stash 命令有什么作用? 什么时候适合用它?
git stash
用于临时保存当前的工作进度(包括修改的文件和暂存区的内容),以便稍后恢复。
常见用途:
- 在切换分支之前,如果当前工作未完成,可以使用
git stash
保存当前的修改状态。 - 临时保存修改,以便进行紧急的 bug 修复。
示例:
git stash # 临时保存工作区的修改
git stash apply # 恢复保存的修改
git stash pop # 恢复并删除保存的修改
8. git pull 和 git fetch 命令分别有什么作用? 二者有什么区别?
git fetch
:从远程仓库获取最新的
更改(如新的提交、分支等),但不会自动合并到当前分支。
git pull
:相当于git fetch
+git merge
,从远程仓库获取更改并自动合并到当前分支。
区别:
git fetch
:不会自动合并,安全性较高。git pull
:会自动合并,可能导致合并冲突。
9. 什么是低代码? 你用过哪些低代码工具?
低代码是通过图形化界面、拖拽组件和配置表单等方式,简化开发过程的技术,使得非开发人员也能快速创建和部署应用。
常见的低代码工具:
- OutSystems:支持企业级应用的开发,提供强大的数据集成和部署能力。
- Mendix:提供可视化设计器、预构建模板和流程自动化等功能。
- Bubble:适用于构建 Web 应用,支持拖拽式开发。
- Appgyver:支持创建复杂的应用,具备丰富的组件和插件。
10. 什么是前端跨平台? 你用过哪些跨平台框架?
前端跨平台是指通过一套代码实现多个平台(如 Web、iOS、Android)上的应用。
常见的跨平台框架:
- React Native:基于 React 开发移动端应用,可以同时发布到 iOS 和 Android。
- Flutter:Google 提供的 UI 框架,支持跨平台开发,适用于 Web、移动端、桌面端等。
- Electron:用于开发跨平台桌面应用的框架,支持 Windows、macOS 和 Linux。
- Ionic:基于 Angular 和 Web 技术的跨平台开发框架,主要用于构建移动端应用。
11. 如何实现 PC 打开是 Web 应用,手机打开是一个 H5 应用?
你可以通过以下方式实现:
-
响应式设计:使用媒体查询(
@media
)根据设备屏幕大小来调整布局。@media (max-width: 768px) {/* 手机端样式 */ }
-
User-Agent 检测:通过 JavaScript 检测用户的设备类型,判断是否为移动设备,从而决定加载不同的应用。
const isMobile = /Mobi|Android/i.test(navigator.userAgent); if (isMobile) {window.location.href = 'https://m.example.com'; // 手机端跳转到 H5 应用 }
-
跳转 URL:可以通过后台判断用户的设备类型,返回不同的页面或静态文件。
相关文章:

前端经典面试合集(二)——Vue/React/Node/工程化工具/计算机网络
1. 说说 Vue 中的 Diff 算法 Vue 的 Diff 算法 主要用于优化虚拟 DOM 和实际 DOM 之间的比较过程。它通过以下几种策略来提高性能: 最小化对 DOM 的操作:Vue 通过在内存中构建一个虚拟 DOM 树,在虚拟 DOM 树与真实 DOM 树之间进行比较和更新…...

PH47代码框架 24241231 重要更新
仪式感一下:2024年最后一天,发布 PH47 代码框架的一次重要更新。当然这并不是有意的,而是直到现在才把更新的所有工作全部做完(希望确实如此)。 本次更新要点: 1、加入多IMU支持。本次更新正式加入对 MPU65…...

Qt6之QML——作用域
作用域定义了表达式可以访问哪些变量、属性或对象,并决定了在变量重名时的优先级如何处理。以下将从作用、绑定、组件作用域和使用技巧四个方面详细解析 QML 中的作用域。 1. 作用:表达式的变量访问与优先级 在 QML 中,表达式能够访问的变量…...

119.【C语言】数据结构之快速排序(调用库函数)
目录 1.C语言快速排序的库函数 1.使用qsort函数前先包含头文件 2.qsort的四个参数 3.qsort函数使用 对int类型的数据排序 运行结果 对char类型的数据排序 运行结果 对浮点型数据排序 运行结果 2.题外话:函数名的本质 1.C语言快速排序的库函数 cplusplus网的介绍 ht…...

C#封送类
封送类(Marshaling classes)在.NET框架中扮演着至关重要的角色,尤其是在托管代码与非托管代码之间进行数据交换时。封送过程涉及到将托管环境中的对象转换为非托管环境中可以理解的形式,并且反之亦然。这一过程确保了两种不同类型…...

2024年度学习总结
2024年是我学业生涯的结束,是我职业生涯的开始。2024年6月19日我顺利研究生毕业,进入体制内,陆止于此,海始于斯,知识和文化最大的魅力,大概就是教会人谦卑和敬畏。读研的目的不是为了单纯拿到哪个证书&…...

我的博客年度之旅:感恩、成长与展望
目录 感恩有你 技能满点 新年新征程 嘿,各位技术大佬、数码潮咖还有屏幕前超爱学习的小伙伴们!当新年的钟声即将敲响,我们站在时光的交汇点上,回首过往,满心感慨;展望未来,豪情满怀。过去的这…...

undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12
目录 我的解决方法: 测试: 报错: undefined symbol: __nvJitLinkComplete_12_4, version libnvJitLink.so.12 from torch._C import * # noqa: F403 ImportError: /mnt/pfs/users/lbg/envs/mmpano/lib/python3.9/site-packages/torch/lib…...

【OTA】论文笔记--《智能网联汽车整车OTA功能设计研究》智能网联汽车OTA系统设计分析报告
智能网联汽车OTA系统设计分析报告 引言 随着汽车智能化、网联化水平不断提升,现代汽车中电子控制单元(ECU)的数量和复杂度持续增加。据统计,高级轿车上电子电气元件的成本已占整车开发成本的60%~70%。为了实现对这些电控单元的软件开发调试、数据标定、文件更新和故障修复,…...

c#String和StringBuilder
目录 一,String 1,string的特点: 2,string常用方法 (1)Length (2)Substring() (3)ToUpper() (4)ToLower() (5&…...

【Linux】HTTP协议
之前,我们已经做过了自定义协议,事实上,已经有很多现成已经做好又非常好用的协议,它们都是相同的,比如HTTP协议。所谓HTTP协议,就是超文本传输协议,定义了客户端和服务器之间是如何通信的&#…...

计算机网络 (14)数字传输系统
一、定义与原理 数字传输系统,顾名思义,是一种将连续变化的模拟信号转换为离散的数字信号,并通过适当的传输媒介进行传递的系统。在数字传输系统中,信息被编码成一系列的二进制数字,即0和1,这些数字序列能够…...

《向量数据库指南》——Milvus Cloud 2.5:Sparse-BM25引领全文检索新时代
Milvus Cloud BM25:重塑全文检索的未来 在最新的Milvus Cloud 2.5版本中,我们自豪地引入了“全新”的全文检索能力,这一创新不仅巩固了Milvus Cloud在向量数据库领域的领先地位,更为用户提供了前所未有的灵活性和效率。作为大禹智库的向量数据库高级研究员,以及《向量数据…...

Unity3D 网络框架设计详解
前言 Unity3D是一款强大的跨平台游戏开发引擎,网络框架的设计对于实现客户端与服务器之间的稳定通信至关重要。本文将详细介绍Unity3D网络框架的设计原理、技术要点以及代码实现。 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一…...

网络渗透测试实验四:CTF实践
1.实验目的和要求 实验目的:通过对目标靶机的渗透过程,了解CTF竞赛模式,理解CTF涵盖的知识范围,如MISC、PPC、WEB等,通过实践,加强团队协作能力,掌握初步CTF实战能力及信息收集能力。熟悉网络扫描、探测HTTP web服务、目录枚举、提权、图像信息提取、密码破解等相关工具…...

Wend看源码-Java-Collections 工具集学习
摘要 java.util.Collections它提供了一系列静态方法,用于对集合(如List、Set、Map等)进行操作。这些操作包括排序、查找、替换、同步等多种功能,帮助开发者更方便地处理集合数据。以下是Collections 提供的一些主要方法的总结。…...

[JAVA]MyLogger
import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.*;/*** 可以自已定义日志打印格式,这样看起来比较方便些**/ class MyFormatter extends Formatter {Overridepublic String format(LogRecord ar…...

玩转OCR | 腾讯云智能结构化OCR初次体验
目录 一、什么是OCR(需要了解) 二、产品概述与核心优势 产品概述 智能结构化能做什么 举例说明(选看) 1、物流单据识别 2、常见证件识别 3、票据单据识别 4、行业材料识别 三、产品特性 高精度 泛化性 易用性 四、…...

记一次 dockerfile 的循环依赖错误
文章目录 1. 写在最前面1.1 具体循环依赖的例子 2. 报错的位置2.1 代码快速分析2.2 代码总结2.3 关于 parser 的记录 3. 碎碎念 1. 写在最前面 笔者在使用 dockerfile 多阶段构建的功能时,写出了一个「circular dependency detected on stage: xx」的错误。 解决方…...

Trimble天宝X9三维扫描仪为建筑外墙检测提供了全新的解决方案【沪敖3D】
随着城市化进程的快速推进,城市高层建筑不断增多,对建筑质量的要求也在不断提高。建筑外墙检测,如平整度和垂直度检测,是衡量建筑质量的重要指标之一。传统人工检测方法不仅操作繁琐、效率低下,还难以全面反映墙体的真…...

【MySQL】深度学习数据库开发技术:使用CC++语言访问数据库
**前言:**本节内容介绍使用C/C访问数据库, 包括对数据库的增删查改操作。 主要是学习一些接口的调用, 废话不多说, 开始我们的学习吧! ps:本节内容比较容易, 友友们放心观看哦! 目录 准备mysql…...

LabVIEW化工实验室设备故障实时监测
化工实验室中,各类设备的运行状态直接影响实验的精度与安全性。特别是重要分析仪器的突发故障,可能导致实验中断或数据失效。为了实现设备运行状态的实时监控与故障快速响应,本文提出了一套基于LabVIEW的解决方案,通过多参数采集、…...

单例模式懒汉式、饿汉式(线程安全)
饿汉式单线程安全吗 饿汉式单例(Eager Singleton)是线程安全的。这种实现方式在类加载时就创建了单例实例,因此在多线程环境中,不存在多个线程同时创建实例的问题。 饿汉式单例的实现 以下是一个饿汉式单例的示例: …...

Cursor登录按钮点击没反应
问题 系统:Windows11 Cursor:Cursor 0.44.9 当安装Cursor打开进行登录时,点击Sign in没反应 解决方案 1.打开window11的设置 2.点击应用中的默认应用 3.在设置应用程序的默认值中搜索Google(没有Google浏览器的尝试下载一个&a…...

论文实现:Reactive Nonholonomic Trajectory Generation via Parametric Optimal Control
1. 多项式螺旋 曲率: κ ( s ) a 0 a 1 s a 2 s 2 a 3 s 3 a 4 s 4 a 5 s 5 \begin{align} \kappa(s) a_0 a_1s a_2s^2 a_3s^3 a_4s^4 a_5s^5 \end{align} κ(s)a0a1sa2s2a3s3a4s4a5s5 机器人朝向: θ ( s ) a 0 s a 1 …...

基于单片机中药存放环境监测系统的实现
基于单片机中药存放环境监测系统的实现 项目开发背景 随着现代中药的广泛应用,中药材的存储环境对其质量有着至关重要的影响。温湿度、烟雾、火灾等环境因素,若不加以控制,将会导致中药材失效或变质。因此,设计一个基于单片机的…...

九垠赢+商业管理系统 Common.ashx 文件上传致RCE漏洞复现
0x01 产品简介 九垠赢+商业管理系统是基于互联网技术的进销存管理软件,适用于新零售背景下各种业态的线上线下一体化的商超经营管理。赢+ERP以商业管理系统为底座,融合了多种软、硬件解决方案,实现了从企业、供应商、三方平台到顾客等日常管理的全线数字化、智能化和移动化…...

速盾:服务器CDN加速解析的好处有哪些呢?
随着互联网应用的普及,越来越多的企业开始关注如何提升网站的访问速度和用户体验。为了实现这一目标,许多企业选择使用CDN(内容分发网络)来加速网站的内容分发。CDN通过在全球范围内分布多个节点,将内容缓存到离用户最…...

C++ 设计模式:备忘录模式(Memento Pattern)
链接:C 设计模式 链接:C 设计模式 - 状态模式 备忘录模式(Memento Pattern)是一种行为设计模式,它允许在不破坏封装性的前提下捕获和恢复对象的内部状态。这个模式在需要保存和恢复对象状态的场景中非常有用ÿ…...

Android 系统 Activity 系统层深度定制的方法、常见问题以及解决办法
Android 系统 Activity 系统层深度定制的方法、常见问题以及解决办法 目录 引言Activity 系统层概述Activity 系统架构图Activity 系统层深度定制的方法 4.1 自定义 Activity 生命周期4.2 自定义 Activity 启动流程4.3 自定义 Activity 转场动画4.4 自定义 Activity 窗口管理4…...