前端顶尖面试宝典2

111 阅读46分钟

说说http不同版本的一些区别

考察点

● 面试官希望了解你对 Web 基础协议演进的理解
● 是否理解各版本提升性能、安全性和效率的关键点
● 是否能结合项目场景说明协议优化对性能的影响
● 是否具备实际配置或调优经验(如 Nginx、浏览器请求)

参考答案

一、HTTP 各版本的核心区别概览

特性HTTP/1.0HTTP/1.1HTTP/2HTTP/3
连接复用❌ 不支持✅ 默认支持✅ 多路复用基于 QUIC 多路复用
传输协议TCPTCPTCPQUIC (UDP)
首部压缩✅ HPACKQPACK
请求顺序阻塞✅ 队头阻塞✅ 队头阻塞
服务端推送✅ 支持✅(实验中)
建连效率慢(三次握手)较慢较慢快(0-RTT)
明文 / 加密明文明文建议加密(TLS)默认加密(TLS + QUIC)

二、详细说明各版本的关键特性

2. HTTP/1.1 —— 主流的基础版本

  • 缓存控制(Cache-Control、ETag)
  • 分块传输编码(chunked)支持动态响应体长度

实际中,队头阻塞依旧是性能瓶颈,特别是在移动端弱网下


4. HTTP/3 —— 面向未来的版本

  • 基于 QUIC 协议(UDP 之上) :替代 TCP,天然支持多路复用和连接迁移(IP 变化不丢连接)
  • 0-RTT 握手:历史连接可实现“秒连”,提升移动端体验
  • TLS 1.3 加密默认启用,更快更安全
  • 服务端推送实验中:性能不稳定,部分浏览器已弃用该特性

实际中,Chrome、Edge、Firefox 等主流浏览器已逐步支持 HTTP/3但服务端部署仍需特别配置(如 Nginx + QUIC)


三、协议演进背后的性能优化目标

  1. 减少连接建立成本
  2. 提升并发请求能力
  3. 减少冗余(如请求头)传输体积
  4. 提升弱网环境下的可靠性
  5. 增强安全性(强制加密通信)

答题要点

  • 不要只背版本号,要结合网络原理理解每一代协议的“问题 → 优化”演进路径
  • 强调HTTP/2 的多路复用解决了什么痛点HTTP/3 又为移动场景带来了哪些变化
  • 说明你是否有实际接触过 HTTP/2 / 3 的部署或调试,提升可信度

如果页面有多张图片 http是怎么加载的

页面中多张图片的 HTTP 加载流程主要遵循浏览器并发限制、资源优先级、缓存策略等规则,核心过程如下:

  1. 解析 HTML 触发请求浏览器解析 HTML 时,遇到<img>标签会立即生成 HTTP GET 请求(若未设置loading="lazy"),请求图片资源

  2. 并发请求限制浏览器对同一域名下的并发 HTTP 请求数有限制(Chrome 默认 6 个),超出的请求会排队等待。因此多张图片会分批加载:先加载前 6 张,完成后再加载后续图片

  3. 资源优先级排序浏览器按图片在视口内的位置、标签属性(如preload)分配优先级:首屏图片优先级高,优先加载;非首屏图片(或设置loading="lazy")延迟到进入视口时加载。

  4. 缓存复用若图片已缓存(符合强缓存 / 协商缓存规则),浏览器直接读取本地缓存,无需发起新请求;未缓存的图片则通过 HTTP 请求获取,响应后存入缓存。

  5. HTTP/2 优化若使用 HTTP/2,支持多路复用:同一 TCP 连接可并行传输多个图片请求,突破 HTTP/1.1 的并发限制,大幅提升多图加载效率。

简言之,多张图片加载是 “并发请求 + 排队等待 + 优先级调度 + 缓存复用” 的过程,HTTP/2 的多路复用可进一步优化加载速度。

结合TCP连接方面讲一下图片数据请求,串行还是并行

  • 说 “图片请求串行”:仅针对 HTTP/1.1 的单个 TCP 连接
  • 说 “图片请求并行”:要么是 HTTP/1.1 的多 TCP 连接并发,要么是 HTTP/2 + 的单连接多路复用并行
  • 现代前端优化(如用 CDN 拆分域名、启用 HTTP/2),核心都是突破 HTTP/1.1 的 TCP 连接和串行限制,提升多图加载速度。

用过http抓包嘛

http2.0有哪些缺点

考察点

● 面试官希望了解你对 HTTP/2 的全面理解,尤其是其局限性和不足
● 是否能理性分析新技术的优缺点,具备实际项目中技术选型的判断力
● 是否了解 HTTP/2 在不同场景或部署上的挑战

参考答案

一、HTTP/2 的缺点与局限性

1. 队头阻塞(Head-of-Line Blocking)仍存在于 TCP 层

虽然 HTTP/2 在应用层通过多路复用解决了队头阻塞问题,但它依赖于 TCP 连接,而 TCP 本身存在队头阻塞:

  • TCP 是面向连接的可靠协议,数据包必须按序到达,否则后续数据包会被阻塞等待重传
  • 当某个包丢失时,所有后续的数据都需等待重传完成,影响整体性能
  • 这在高丢包率的网络环境 (如移动网络)表现尤为明显

2. 加密(TLS)成为常态,增加了服务器负担

  • 虽然 HTTP/2 并不强制使用 HTTPS,但主流浏览器要求 HTTP/2 必须在 TLS 上运行
  • TLS 握手、加密解密增加了服务器 CPU 负担
  • 对资源有限的服务器和旧设备可能有性能影响

3. 服务器推送(Server Push)实际应用效果有限

  • 服务器主动推送资源虽然理论上能减少请求延迟,但实际中常出现推送了用户不需要的资源,反而浪费带宽
  • 管理和缓存策略复杂,导致使用门槛较高
  • 目前很多主流网站和浏览器对服务器推送支持不积极,甚至部分弃用

4. 部署和调试复杂度较高

  • HTTP/2 的二进制分帧和多路复用机制使得网络抓包和分析更加困难
  • 一些老旧或中间网络设备(如代理、防火墙)可能对 HTTP/2 支持不佳,影响兼容性
  • 需要服务器和 CDN 升级支持,对运维成本和技术要求提升

5. 单一 TCP 连接的瓶颈

  • 虽然多路复用提高了并发能力,但所有请求共享同一个 TCP 连接
  • 当连接出现故障或被中断时,影响所有请求
  • 这也是 HTTP/3 转向 QUIC(UDP)协议的一个主要动因

二、总结

缺点说明
TCP 层队头阻塞网络丢包导致所有请求阻塞,影响性能
必须依赖 TLS加密带来性能开销,部署成本增加
服务器推送复杂且使用受限推送资源管理困难,实际效果有限
部署调试复杂抓包分析困难,兼容性受限
单一 TCP 连接故障风险连接断开影响所有请求

答题要点

  • 明确指出 HTTP/2 并非完美,TCP 层的队头阻塞依然是性能瓶颈
  • 结合实际场景分析加密和推送的实际挑战
  • 体现对部署调试复杂度的认识,表现实际工程视角
  • 体现对 HTTP/3 设计的理解(如基于 UDP 解决 TCP 队头阻塞)

HTTP 与 HTTPS 的主要区别

维度HTTPHTTPS
传输协议TCPTCP + TLS/SSL
数据传输安全性明文传输,数据易被窃取或篡改加密传输,防止窃听、中间人攻击、篡改
端口号默认端口 80默认端口 443
证书需申请数字证书,验证身份
性能开销较低加密/解密带来一定计算开销
SEO 优势搜索引擎倾向 HTTPS,提升排名
用户信任度高,浏览器地址栏显示安全标识

http1对同时并发请求的数量是有限制的

一、HTTP/1.x 并发请求限制的背景

  • HTTP/1.0 和 HTTP/1.1 中,每个 TCP 连接一般只能处理一个请求(HTTP/1.0 不支持持久连接,HTTP/1.1 支持持久连接但无多路复用)
  • 浏览器为了避免过多打开 TCP 连接,对同一域名的并发 TCP 连接数量有限制
  • 该限制主要由浏览器厂商定义,不同浏览器限制数略有差异,通常为 6-8 个并发连接

二、常见浏览器并发连接数限制举例

浏览器同一域名最大并发连接数
Chrome6
Firefox6
Edge6
Safari6-8
IE 116

三、限制产生的原因和影响

1. 资源和性能平衡

  • 限制并发连接数避免因连接数过多导致服务器压力增大和客户端资源枯竭(如文件描述符耗尽)
  • 限制过低会造成请求排队,降低页面加载速度,尤其是多个资源并发请求时表现明显

2. 队头阻塞和阻塞现象

  • 并发连接数限制导致后续请求必须排队等待空闲连接,形成“队头阻塞”
  • 对页面首屏加载性能有明显影响

四、解决方案和优化措施

1. 域名分片(Domain Sharding)

  • 利用多个子域名分散请求,突破单域名并发限制
  • 但会增加 DNS 查询、TCP 握手成本,且 HTTP/2 不建议使用此策略

2. 使用 HTTP/2

  • HTTP/2 支持单连接多路复用,彻底解决此类限制问题
  • 推荐升级到 HTTP/2 或以上版本

3. 资源合并和压缩

  • 合并 JS、CSS 减少请求数量
  • 使用雪碧图减少图片请求数

HTTPS 加密的核心技术组成

1. 非对称加密(公钥加密)

  • 使用一对密钥:公钥(公开)和私钥(保密)
  • 用公钥加密的数据只能用私钥解密,反之亦然
  • 优点:解决密钥分发问题
  • 缺点:加解密速度慢,通常用于密钥交换

2. 对称加密

  • 双方使用同一密钥进行加密和解密
  • 加密速度快,适合大量数据传输

3. 数字证书和证书链

  • 由权威的证书颁发机构(CA)签发
  • 用于验证服务器身份,防止假冒
  • 含公钥、证书颁发机构(CA)信息、服务器的域名、签发机构等信息

三、补充说明:TLS 握手的类型

  • 完全握手(Full handshake) :第一次连接时完整的密钥协商过程
  • 复用握手(Session resumption) :重连时通过 Session ID 或 Session Ticket 快速恢复密钥,节省握手时间
  • 0-RTT(TLS 1.3) :允许客户端提前发送加密数据,进一步减少延迟

答题要点

  • 清晰区分非对称加密用于密钥交换对称加密用于数据传输
  • 理解数字证书的身份验证作用
  • 熟悉握手过程的具体步骤和意义
  • 理解握手安全性及性能优化(Session 重用、TLS 1.3 特性)
  • 能结合项目场景谈 HTTPS 加密带来的安全保障

async await.具体是怎么实现的

考察点

● 深入理解 async/await 的底层实现机制
● 掌握 async/await 与 Generator、Promise 的关系
● 理解 async 函数的执行流程和状态管理
● 能解释 await 如何暂停和恢复异步操作

参考答案

一、async/await 的核心思想

  • async/await 是基于 Generator 函数和 Promise 的语法糖,目的是让异步代码写得像同步代码一样简洁、直观
  • async 函数本质上会返回一个 Promise 对象
  • await 用于等待一个 Promise 解析,暂停 async 函数的执行直到 Promise 解决(fulfilled)或拒绝(rejected)

二、async/await 的底层实现原理

1. async 函数返回 Promise

  • 编译后,async 函数会自动包装成一个返回 Promise 的函数
  • 函数内部执行的同步代码正常执行,遇到 await 会暂停,并挂起后续操作,直到等待的 Promise 解析完成

2. await 实现原理

  • await 实际等待的是一个 Promise
  • 当遇到 await promise 时,async 函数暂停执行,将控制权返回给调用者(挂起执行上下文)
  • 当 Promise 状态变为 fulfilled 或 rejected,恢复函数执行并将结果(或错误)返回

3. 结合 Generator 函数模拟 async/await

  • Generator 通过 yield 暂停函数,外部驱动执行(next()

  • async/await 类似于 Generator + Promise 的结合:

    • await 相当于 yield 一个 Promise
    • 通过递归调用 .then() 来自动推进 Generator 的执行

三、async 函数执行流程

  1. 调用 async 函数,立即返回一个 Promise
  2. 函数内部代码同步执行,遇到 await 时暂停,返回控制权
  3. 等待 await 后的 Promise 解析完成(fulfilled 或 rejected)
  4. 根据 Promise 结果,恢复函数执行(执行下一步)
  5. 最终函数执行完毕,Promise 变为 resolved 或 rejected,返回对应值或异常

四、错误处理机制

  • async 函数中,await 后的 Promise 如果 reject,会抛出异常
  • 可以通过 try/catch 捕获这些异常,类似同步代码异常处理
  • 未捕获异常会导致返回的 Promise 变为 rejected,触发外部 .catch()

答题要点

  • async/await 是基于 Generator + Promise 的语法糖
  • async 函数返回 Promise,await 负责暂停和恢复异步操作
  • await 实际等待一个 Promise 的解析
  • 通过内部自动执行 Promise 的 .then() 推进 Generator,简化异步流程
  • 错误处理可用同步风格的 try/catch,异常会反映在返回的 Promise 中

想知道你们的项目大概是什么样的结构,你在开发的时候会从什么地方下手

考察点

  • 理解典型前端项目的整体结构及模块划分
  • 掌握从项目启动到开发流程的系统思路
  • 能清晰描述如何快速定位入口及关键代码区域
  • 展示合理的开发习惯与代码管理思路
  • 体现对团队协作和版本控制的认知

参考答案

一、典型前端项目结构说明
  1. 目录结构

    • src/:项目源码,包含页面(Page)、组件(Component)、样式(Styles)、工具函数(Utils)、状态管理(Store)等
    • public/ 或 static/:静态资源,如图片、字体、favicon 等
    • build/ 或 scripts/:构建相关脚本和配置
    • config/:环境配置文件,如开发、测试、生产环境参数
    • tests/:单元测试和集成测试代码
    • 配置文件如 package.json.babelrcwebpack.config.js 或 vite.config.js
  2. 关键文件

    • 入口文件(如 src/main.jssrc/index.js)负责挂载应用
    • 路由配置文件定义页面导航
    • 状态管理文件(如 Vuex、Redux)管理全局状态
    • 公共组件库及工具函数模块
    • API 接口封装层,统一管理后端请求

IntersectionObserver的事件回调是宏任务还是微任务?如何判断呢

答题要点

  • IntersectionObserver 回调属于宏任务,因为它与浏览器渲染密切相关,属于事件循环中宏任务队列执行
  • 判断方法可通过输出顺序和事件循环机制分析
  • 微任务一般紧跟同步代码执行后立即执行,优先级更高;宏任务通常发生在事件循环的下一轮

假如你是一个项目的负责人,面对一个新需求你会如何判断以及决策

考察点

  • 评估候选人对需求分析和项目管理流程的理解
  • 探查其在技术可行性、资源评估、风险管理等方面的判断能力
  • 了解候选人如何在多方利益、时间与质量之间做权衡决策
  • 关注其沟通协调和方案落地的思路

参考答案

一、需求理解与评估
  1. 明确需求背景和目标

    • 充分沟通业务方,理解需求的业务价值核心目标和痛点
    • 判断该需求是新增功能、优化还是技术债清理
  2. 技术可行性分析

    • 评估现有系统架构、技术栈对该需求的支持程度
    • 识别技术难点和潜在风险,如性能、安全、兼容性等问题
  3. 资源与时间评估

    • 估算开发、测试、上线所需的人力、时间和成本
    • 考虑团队现有工作负载,排期合理性
二、方案设计与风险控制
  1. 设计多套实现方案

    • 比较不同方案的优劣,如技术复杂度、扩展性、维护成本
    • 结合业务优先级和技术条件选择最优方案
  2. 风险预判与缓解

    • 识别潜在风险点,设计应对措施(如技术预研、灰度发布)
    • 规划阶段性验收,快速反馈,减少偏差
三、决策与执行
  1. 结合业务战略和团队实际作出决策

    • 权衡需求价值与资源限制,明确是否优先推动或延期
    • 与产品、设计、测试等多方协作,达成共识
  2. 推动方案落地

    • 制定详细开发计划,分解任务,明确负责人和时间节点
    • 跟踪进展,快速解决过程中出现的问题
  3. 复盘与优化

    • 需求完成后组织复盘,总结经验,优化流程

答题要点

  • 业务价值与需求背景明确 / 技术可行性与风险评估 / 资源与时间合理估算
  • 多方案设计与优劣比较 / 风险预判及缓解措施
  • 结合团队和业务做权衡决策 / 明确执行计划与责任 / 持续跟进与复盘优化
  • 沟通协调能力和风险管理能力是关键
  • 决策既考虑短期交付,也兼顾长期维护和团队承受能力

哪些浏览器会在图片兼容性上有问题呢

具体浏览器兼容问题分析
  1. Safari(尤其旧版本)

    • 早期版本不支持WebP AVIF 格式图片
    • SVG部分高级特性兼容有限
  2. IE浏览器(已停止维护,但部分企业仍用)

    • 不支持WebP、AVIF等现代格式
    • SVG支持不完善,存在安全漏洞和渲染差异
  3. 部分安卓浏览器

    • 一些第三方或老版本浏览器对WebP兼容不完全
    • 对SVG支持不稳定
三、兼容性处理方案
  • 格式回退机制

    • 通过<picture>标签,结合source元素按浏览器能力加载对应格式图片
    • 使用JS检测支持情况,动态切换图片资源
  • 构建工具自动转换

    • 利用构建工具(如webpack、vite)对图片进行多格式转换,生成兼容资源
  • 合理选择图片格式

    • 关键内容优先保证主流格式兼容,增强用户体验

答题要点

  • WebP和AVIF是现代高效格式,但旧Safari和IE不支持
  • Safari对WebP支持从14版本开始,AVIF更晚
  • IE浏览器兼容性差,现代格式均不支持
  • SVG兼容性存在差异,需注意安全和复杂特性
  • 采用<picture>和格式回退方案保障兼容
  • 构建工具多格式自动转换,兼顾性能与兼容
  • 动态检测用户环境,选择合适图片格式

h5是如何和移动端做通信的呢

考察点

  • 理解H5页面与移动端原生环境通信的基本机制
  • 掌握主流通信方式及其优缺点和适用场景
  • 能结合项目需求选择合适的通信方案,并处理安全和性能问题

参考答案

一、H5与移动端通信的基本概念
  • H5页面运行在移动端浏览器或WebView内,和原生App环境是不同的执行上下文
  • 通信需要跨环境桥接,传递消息、数据和调用能力
  • 典型场景包括H5调用原生功能,原生通知H5事件
二、常见通信方式
  1. URL Scheme(协议拦截)

    • H5通过修改window.location或iframe跳转带有自定义协议的URL(如myapp://action?param=xxx
    • 原生拦截该URL并解析执行相应操作
    • 优点:实现简单,兼容性好
    • 缺点:只能单向通信,数据量有限,频繁跳转体验差
  2. JavaScript Interface(JSBridge)

    • 通过原生提供的桥接接口,将JS方法映射到原生函数
    • H5调用window.Native.method(params),原生接收并处理
    • 原生也可调用JS回调实现双向通信
    • 优点:交互灵活,支持复杂数据传输
    • 缺点:实现复杂,需维护多平台桥接代码
  3. PostMessage机制(WebView专用)

    • 利用window.postMessage API实现跨环境异步通信
    • 原生WebView提供监听接口捕获消息并响应
    • 适用于iOS WKWebView和Android WebView
    • 优点:安全、标准,支持双向通信
    • 缺点:需保证协议设计安全,防止注入攻击
  4. 事件监听和回调

    • 结合JSBridge或postMessage,使用事件机制通知双方状态变化
    • 便于管理复杂交互和异步回调
三、实际项目中的应用示例
  • 用户点击H5按钮调用原生相机功能:通过JSBridge调用原生API
  • 原生扫码结果通过postMessage传给H5,H5页面更新UI
  • 通过URL Scheme唤起App某个页面或功能
  • 结合Hybrid框架(如Weex、React Native WebView模块)统一通信接口
四、需要注意的问题
  • 安全性:防止恶意注入或非法调用,校验传入参数和来源
  • 性能:避免频繁通信导致卡顿,合理设计调用频率
  • 兼容性:处理不同平台(iOS/Android)桥接差异
  • 异步处理:通信多数为异步,需设计完善的回调或Promise机制
  • 版本维护:原生和H5接口需同步升级,保持兼容

答题要点

  • H5与移动端通信主要通过URL Scheme、JSBridge、postMessage等方式
  • URL Scheme简单但单向且数据有限
  • JSBridge灵活支持

小程序上线

uniapp

1.uniapp如何做微信小程序登录?

2.手机号验证码和第三方微信授权登录和逻辑?

3.做过消息推送吗?和后台如何保持实时推送?

4.做过寻路吗?注意什么?

5.如何适配?样式适配? 浏览器适配?

下拉刷新和上拉加载?

vite的构建过程了解吗?那刚刚说到构建过程分开发构建和线上构建,他们分别的流程是什么?

Webpack 打包产物是什么?

  • bundle.js(合并后的 JS 代码)
  • vendor.js(第三方库)
  • index.html(入口文件)
  • assets/(图片、字体等)

html元素节点上,有多个class名称,这几个class名称对应的样式渲染优先级是如何的?

若多个 class 选择器定义了相同的 CSS 属性,浏览器会按照以下规则决定哪个样式优先应用:

  1. 特指度:在多个 class 选择器的情况下,优先应用特指度更高的规则。例如,.class1 和 .class2 的特指度相同,那么后定义的样式会覆盖先定义的样式。
  2. 样式表的顺序:如果多个样式规则的特指度相同,那么后定义的规则会覆盖先定义的规则。例如,如果 CSS 文件中 .menu { color: red; } 在 .header { color: blue; } 之后,那么 .menu 的样式会被应用。
  3. 内联样式:内联样式(即 style 属性中的样式)具有比外部样式表更高的特指度。如果元素上有内联样式,它们会覆盖 class 中定义的样式。
  4. !important 声明:如果 CSS 属性使用了 !important,它将具有最高的优先级,覆盖所有其他没有 !important 的规则。

属性的可继承性

继承属性

css中,继承是指的是给父元素设置一些属性,后代元素会自动拥有这些属性 关于继承属性,可以分成:

- 字体系列属性

font:组合字体
font-family:规定元素的字体系列
font-weight:设置字体的粗细
font-size:设置字体的尺寸
font-style:定义字体的风格
font-variant:偏大或偏小的字体

- 文本系列属性

text-indent:文本缩进
text-align:文本水平对齐
line-height:行高
word-spacing:增加或减少单词间的空白
letter-spacing:增加或减少字符间的空白
text-transform:控制文本大小写
direction:规定文本的书写方向
color:文本颜色

- 元素可见性

visibility

- 光标属性

cursor:箭头可以变成需要的形状

继承中比较特殊的几点:

  • a 标签的字体颜色不能被继承
  • h1-h6标签字体的大下也是不能被继承的

无继承的属性

  • display
  • 盒子模型的属性:margin padding border
  • 背景属性(background):背景图片、颜色、位置等
  • 定位属性:浮动、清除浮动、定位position等

防止font-family在子元素上继承

方法 1:显式设置子元素的font-family

直接给需要 “取消继承” 的子元素,指定新的font-family(比如浏览器默认字体),覆盖父元素的继承值:

/* 父元素设置字体 */
.parent {
  font-family: "微软雅黑", sans-serif;
}

/* 子元素重置字体(用浏览器默认字体) */
.parent .child {
  font-family: initial; /* 恢复为浏览器默认字体(或指定具体字体,如 "宋体") */
}
  • initial:表示使用 CSS 属性的初始默认值font-family的初始值是浏览器默认字体,如系统的 “Times New Roman” 或 “微软雅黑”);
  • 也可以直接指定具体字体(如font-family: "宋体", serif;),更精准控制。

方法 2:使用all: initial重置所有继承属性(谨慎用)

如果需要重置子元素的所有继承属性(不仅是font-family),可以用all: initial(但会重置所有样式,需注意):

.parent .child {
  all: initial; /* 重置所有CSS属性为初始值,包括font-family、颜色、边距等 */
  /* 之后可重新设置子元素需要的样式 */
  font-size: 14px;
}

方法 3:利用 CSS 作用域(局部样式)

如果是模块化开发(如 Vue/React),可以通过CSS 作用域(如 Vue 的scoped、CSS Modules)限制父元素样式的影响范围,避免子元素继承:

<!-- Vue中scoped样式,父元素样式仅作用于当前组件,不会渗透到子组件 -->
<style scoped>
.parent {
  font-family: "微软雅黑", sans-serif;
}
</style>

关键说明

  • font-family可继承属性(CSS 中多数文本类属性,如colorfont-size都默认继承),无法 “禁止继承”,只能通过 “重置子元素属性” 覆盖继承值;
  • 推荐用方法 1(显式重置),更灵活且不会影响其他属性。

inheritinitialunset的区别与作用

关键字作用(继承 / 样式初始化)
inherit强制元素继承父元素的该属性值无论属性是否默认继承
initial将属性重置为CSS 规范定义的初始默认值(与浏览器默认样式无关)
unset若属性是可继承属性,则表现为inherit;若属性是不可继承属性,则表现为initial

inherit强制继承样式

默认不继承的属性,显式设置inherit即可强制继承父元素值。示例:

.parent {
  border: 1px solid red; /* border默认不继承 */
}
.child {
  border: inherit; /* 强制继承父元素的border样式 */
}

initialunset的特定行为与默认值的区别

  • initial的行为:重置为 CSS 规范的初始值(如display: initial对应inline,而非浏览器默认的block),与 “浏览器默认样式” 无关。

  • unset的行为:依赖属性的继承性:

    • 可继承属性(如color):等价于inherit
    • 不可继承属性(如border):等价于initial
  • 与 “默认值” 的区别:“默认值” 通常指浏览器预设的样式(如body默认margin: 8px),而initial是 CSS 规范的初始值(margin: initial对应0)。

继承样式对性能的影响

  1. 正常继承:无额外渲染负担。浏览器原生支持样式继承,仅存储 “继承关联” 而非重复复制样式值,CSSOM 构建和渲染时无需额外计算。

  2. 异常 / 过度继承:会增加负担。

    • 强制继承非默认属性(如border: inherit):需额外查询父元素属性;
    • 多层级深度继承(≥3 层):CSSOM 遍历路径变长,重排时需逐层追溯;
    • 频繁重写继承样式(如initial覆盖):触发额外样式计算与重绘。

复杂继承样式的优化方案

  1. 扁平化结构:避免>3 层嵌套,用 BEM 命名(如.card-title)替代多层继承选择器。
  2. 精准控制继承范围:不用body/html做全域继承,按需给目标元素定义样式。
  3. 替代深度继承:用 CSS 变量存储复用值(如:root { --color: #333; }),子元素直接取值。
  4. 减少重写操作:提前规划样式层级,避免 “继承→覆盖” 的反复操作。
  5. 工具优化:用 PostCSS/Sass 压缩冗余规则,禁用*选择器(避免全域继承遍历)。

iconfont 相关问题

什么是 IconFont

顾名思义,IconFont 就是字体图标。严格地说,就是一种字体,但是,它们不包含字母或数字,而是包含符号和字形。您可以使用 CSS 设置样式,就像设置常规文本一样,这使得 IconFont 成为 Web 开发时图标的热门选择。

Iconfont 核心原理是

将图标封装成字体文件(如 TTF/WOFF),像使用普通文字一样调用图标,本质是把图形符号映射为字体编码利用字体渲染机制展示图标

具体拆解:

  1. 图标矢量化:将图标转为矢量图形,映射到字体文件的「私有 Unicode 编码」(如\e600);
  2. 字体文件生成:把所有图标对应的矢量图形打包成通用字体文件(兼容 TTF/WOFF/WOFF2 等格式);
  3. 样式关联:通过 CSS 定义字体族(font-family: iconfont),并为每个图标绑定专属类名,类名通过content属性关联对应 Unicode 编码;
  4. 页面渲染:页面中添加对应类名的元素,浏览器会像渲染文字一样,加载字体文件并渲染出矢量图标,支持缩放、变色等文字样式调整。

优势

  • 矢量无失真、体积小、可复用
  • 且能通过 CSS 轻松修改颜色 / 大小 / 间距
  • 兼容所有支持字体的浏览器

不足

  • 不能用来显示复杂图像
  • 通常只限于一种颜色,除非应用一些 CSS 技巧

如何检测浏览器所支持的最小字体大小?

核心思路

浏览器对字体大小有最小渲染限制(如 Chrome 默认最小 12px),即使设置font-size: 8px,实际渲染仍为最小值。检测原理是:创建不同字号的隐藏元素,通过对比元素实际宽度 / 高度,找到浏览器开始不再缩小的临界值

font-family 涉及的一些问题

1. font-family的作用与对字体显示的影响

  • 作用:指定元素文本的字体类型,决定浏览器渲染文本时使用的字体。
  • 对显示的影响:浏览器会优先匹配font-family中指定的字体,若字体不存在 / 不支持,则按 “字体回退机制” 选择替代字体,直接决定文本的视觉样式(如字形、可读性)。

2. 指定多个备选字体与字体系列的使用

  • 指定方式:用逗号分隔多个字体名,浏览器按顺序匹配(如font-family: "微软雅黑", "宋体", sans-serif;)。
  • 字体系列:是一类风格相似的字体集合(如sans-serif(无衬线)、serif(有衬线)、monospace(等宽)),作为最终兜底选项(浏览器会选择系统中该系列的默认字体)。

3. 字体回退机制与浏览器处理逻辑

  • 字体回退机制:当font-family中靠前的字体不存在、不支持或无法显示部分字符时,浏览器自动选择后续字体的机制。
  • 处理逻辑:按font-family的顺序依次检查字体可用性,若所有指定字体都不可用,则使用浏览器默认字体(通常是系统默认的无衬线 / 有衬线字体)

4. font-familyfont中字体选择的区别及优雅选字体

  • 区别

    • font-family是单独指定字体的属性;
    • font是字体相关属性的简写(包含font-familyfont-size等),其中的字体选择逻辑与font-family完全一致。
  • 优雅选字体

    1. 优先指定具体字体(如 “微软雅黑”“Arial”),适配主流系统;
    2. 补充同风格的备选字体;
    3. 最后用通用字体系列兜底(如sans-serif);
    4. 避免使用小众字体(需配合@font-face引入),兼顾兼容性与加载性能。

CSS中的 "flex:1;" 是什么意思?

在 CSS Flexbox 布局中,flex: 1; 是 flex 复合属性的简写形式,本质是设置弹性项目(flex item)的伸缩规则,核心作用是让该元素在父容器的剩余空间中等分 / 占满可用空间

一、flex 复合属性的完整拆解

flex 是 flex-growflex-shrinkflex-basis 三个属性的简写,语法为:

flex: <flex-grow> <flex-shrink> <flex-basis>;

当只写 flex: 1; 时,等价于:

flex: 1 1 0%; 

逐个解释这三个子属性:

子属性值(flex:1 时)含义
flex-grow1「扩展因子」:父容器有剩余空间时,该元素的扩张比例(0 表示不扩张)。
flex-shrink1「收缩因子」:父容器空间不足时,该元素的收缩比例(0 表示不收缩)。
flex-basis0%「基准尺寸」:元素在伸缩前的初始尺寸(0% 表示以内容 / 子元素尺寸为基准)。

二、flex: 1; 的核心行为(举例说明)

场景 1:父容器有剩余空间(最常用)
<div class="container">
  <div class="item1">A</div>
  <div class="item2">B</div>
</div>
.container {
  display: flex; /* 开启flex布局 */
  width: 400px;
  height: 100px;
  border: 1px solid #000;
}
.item1 { flex: 1; background: red; }
.item2 { flex: 1; background: blue; }
  • 父容器宽度 400px,两个子元素都设 flex:1 → 剩余空间被等分,各占 200px。
  • 若 item1 设 flex:2item2 设 flex:1 → 剩余空间按 2:1 分配(item1 占~266px,item2 占~133px)。
场景 2:父容器空间不足

如果子元素内容总宽度超过父容器(比如两个子元素内容各 300px,父容器仅 400px):

  • flex-shrink:1 会让两个元素等比例收缩,最终总宽度适配父容器 400px。
  • 若某元素设 flex-shrink:0,则该元素不收缩,由其他元素承担全部收缩。
场景 3:flex-basis: 0% 的关键作用

如果把 flex-basis 改成 auto(比如 flex:1 1 auto),元素的初始尺寸会以自身内容宽度为基准,再分配剩余空间,结果和 flex:1 不同:

  • 例:item1 内容是 “AAAAA”(宽度 50px),item2 内容是 “B”(宽度 10px),父容器 400px。

    • flex:1(basis:0%):剩余 400px 等分 → 各 200px。
    • flex:1 1 auto(basis:auto):剩余 400 - 50 -10 = 340px 等分 → item1 50+170=220px,item2 10+170=180px。

三、常见易错点

  1. flex:1 vs width:100%

    • width:100% 是固定占父容器 100% 宽度,若有兄弟元素会溢出;
    • flex:1 是分配剩余空间,多个 flex:1 元素会自动等分,不会溢出。
  2. 父容器必须开启 flex:只有父元素设置 display: flex/inline-flex,子元素的 flex:1 才会生效。

  3. flex:1 vs flex:auto

    • flex:1 = 1 1 0% → 以 0 为基准分配剩余空间;
    • flex:auto = 1 1 auto → 以自身内容尺寸为基准分配剩余空间。

四、典型应用场景

  • 移动端顶部导航栏:左侧返回按钮,中间标题(flex:1 占满剩余空间),右侧菜单按钮;
  • 页面布局:侧边栏固定宽度,主内容区 flex:1 占满剩余宽度;
  • 均分卡片:多个卡片在一行,自动等分父容器宽度(无需计算百分比)。

总结:flex:1 是 Flexbox 中最常用的 “自适应占比” 写法,核心是让元素根据父容器空间等比例伸缩,是实现弹性布局的核心属性。

“flex: auto;”

是 CSS Flexbox 布局中flex复合属性的简写形式,等价于flex: 1 1 auto;,其核心作用是让弹性项目根据自身内容尺寸,自适应分配容器的剩余空间或收缩空间

具体拆解(对应三个子属性):

  1. flex-grow: 1当父容器有剩余空间时,该元素会按比例(与其他flex-grow元素)分配额外空间,实现 “扩展占满”。
  2. flex-shrink: 1当父容器空间不足时,该元素会按比例(与其他flex-shrink元素)缩小自身尺寸,避免溢出。
  3. flex-basis: auto元素的初始尺寸默认以自身内容的实际大小为基准(而非固定值),再结合flex-grow/flex-shrink调整最终尺寸。

与 “flex: 1;” 的核心区别:

  • flex: 1;等价于flex: 1 1 0%,以 “0 尺寸” 为基准分配空间,多个元素会严格等分容器空间;
  • flex: auto;以 “自身内容尺寸” 为基准分配空间,最终尺寸会结合内容大小和容器空间动态调整(内容多的元素,最终尺寸可能更大)。

vw vh定义和使用场景

1. 定义

  • vw(Viewport Width) :视口宽度的百分比单位,1vw 等于浏览器视口宽度的 1% (视口指浏览器可视区域的尺寸,不含浏览器的工具栏、地址栏等)。
  • vh(Viewport Height) :视口高度的百分比单位,1vh 等于浏览器视口高度的 1%

2. 使用场景

  • 全屏布局:实现元素占满视口(如全屏 banner、登录页),例如设置width: 100vw; height: 100vh可让元素完全覆盖当前可视区域。
  • 动态适配的组件:如导航栏高度、弹窗尺寸等,需随视口变化保持相对比例的场景。

使用vw和vh实现视口大小变化时的动态适配有哪些注意事项?

使用 vw/vh 实现视口动态适配时,核心要规避视口特性、设备差异和交互体验的坑,以下是关键注意事项:

1. 规避视口单位的 “边界陷阱”

  • 移动端地址栏 / 导航栏影响 vh:手机浏览器(如 Chrome)滚动时会隐藏 / 显示地址栏,导致视口高度动态变化,直接用 100vh 设置页面高度会出现 “内容被截断” 或 “滚动条闪烁”。✅ 解决方案:优先用min-height: 100dvh(动态视口高度,适配移动端地址栏变化),或给 body/html 设置height: 100%替代纯 100vh。
  • 视口溢出问题:若元素用 vw 设置宽度 + 固定 padding/border,可能触发横向滚动(如width: 100vw + padding: 20px)。✅ 解决方案:配合box-sizing: border-box,或用calc()(如width: calc(100vw - 40px))。

2. 控制缩放比例,避免极端尺寸

  • 字体 / 元素尺寸失控:vw/vh 会随视口无限制缩放,比如小屏手机(320px)下 10vw=32px(字体过大),大屏显示器(1920px)下 10vw=192px(元素过大)。✅ 解决方案:

    • clamp()限制范围(如font-size: clamp(16px, 3vw, 28px));
    • 配合媒体查询兜底(如大屏时固定最大尺寸)。

3. 兼容与降级处理

  • 低版本浏览器兼容IE11 对 vw/vh 支持不全(如不支持 dvh),部分老旧移动端浏览器存在计算偏差。✅ 解决方案:关键布局用媒体查询 + px 兜底,或通过 PostCSS 插件(如 postcss-viewport-units)自动生成兼容代码
  • 横竖屏切换适配:横竖屏切换时 vw/vh 会突变(如手机竖屏 vw 小、横屏 vw 大),需避免元素布局错乱。✅ 解决方案:核心元素用min()/max()限制尺寸(如width: min(80vw, 600px))。

4. 交互体验优化

  • 可点击元素最小尺寸:用 vw 设置按钮 / 链接尺寸时,需保证小屏下不低于可点击阈值(建议≥44px,符合移动端交互规范)。✅ 解决方案:width: clamp(44px, 10vw, 80px)
  • 避免纯 vw/vh 依赖:不要所有属性都用 vw/vh,比如行高(line-height)、间距(gap)可搭配 rem/em,减少视口变化的过度敏感。

5. 视口元标签基础

移动端必须配置正确的视口元标签,否则 vw/vh 计算会基于 “布局视口”(默认 980px)而非 “视觉视口”,导致尺寸完全错误:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

不同设备上的 px 是如何表现的?设备像素比(DPR)如何影响 px 的实际大小?

  • px的表现px(CSS 像素)是浏览器渲染的抽象单位,在同一设备中,1CSS 像素对应的 “设备像素” 数量由 设备像素比(DPR) 决定(DPR = 设备像素数 / CSS 像素数)。

  • DPR 的影响

    • 普通屏幕(DPR=1):1CSS 像素 = 1 设备像素;
    • Retina 屏幕(如 iPhone,DPR=2):1CSS 像素 = 2×2=4 设备像素;因此,相同 CSS 像素值(如width: 100px),在高 DPR 设备上会用更多设备像素渲染,视觉更清晰,但 物理尺寸(如厘米) 会因设备 PPI 不同而变化(高 DPR 设备的 1CSS 像素物理尺寸更小)。

rem 的基准值如何确定?如何动态调整基准值以实现自适应?

  • 基准值的确定rem的基准值是根元素(<html>)的font-size默认情况下,浏览器根元素font-size为 16px(即 1rem=16px)

  • 动态调整基准值:常用方式是根据视口宽度动态设置根元素font-size,实现自适应:

    1. 媒体查询:在不同屏幕宽度下修改根font-size(如小屏设 14px,大屏设 18px);
    2. JS 计算:通过脚本根据视口宽度计算根font-size(如html.style.fontSize = window.innerWidth / 10 + 'px',将视口宽分为 10 份,1rem 对应 1/10 视口宽);
    3. CSS clamp() :用font-size: clamp(14px, 2vw, 18px)限制根字体大小的范围。

在 Retina 屏幕和普通屏幕中,绝对单位是否会表现不一致?

绝对单位(如px)在两类屏幕中的CSS 逻辑尺寸一致,但物理渲染精度不同

  • 逻辑尺寸:100px 在两类屏幕中对应的 “布局空间” 相同;
  • 物理表现:Retina 屏幕会用更多设备像素渲染该 100px,视觉更清晰细腻,但 物理尺寸(如实际宽度) 可能因设备 PPI 差异而不同(高 PPI 设备的 1px 物理尺寸更小)。

哪些相对单位在旧版浏览器中可能无法正常工作?如何避免

  • 不支持的相对单位

    • vw/vh:IE11 部分支持,IE9 及以下不支持
    • rem:IE8 及以下不支持;
    • vmin/vmax:IE9 部分支持,IE8 及以下不支持。
  • 规避方法

    1. 降级方案对旧浏览器用px作为兜底(如通过媒体查询或条件注释);
    2. 工具兼容:用 PostCSS 插件(如postcss-preset-env将新单位转换为旧浏览器支持的形式
    3. 渐进增强:核心布局用px/%实现基础适配,新单位用于增强效果(旧浏览器忽略不影响核心功能)。

过度使用相对单位(如嵌套的 em)可能会导致什么问题?如何避免这种问题?

  • 可能的问题em是相对于父元素字体大小的单位,嵌套使用时会导致尺寸计算层级叠加,难以预测最终大小(如多层嵌套后,尺寸可能偏离预期);同时增加代码维护成本,修改父元素样式可能连锁影响所有子元素。

  • 避免方法

    • 优先使用rem(基于根元素字体大小,层级无关)替代嵌套em
    • 仅在局部组件内(如按钮、图标)有限使用em避免多层嵌套
    • 结合 CSS 变量统一管理基准值,减少层级依赖。

如何在单位选择中兼顾性能和维护性?比如在大型项目中优先使用 rem 而非 px

  • 核心原则:按 “场景适配性 + 维护成本” 选择单位,而非单一偏好:

    1. 大型项目优先用remrem基于根元素,全局统一基准,修改根字体大小即可批量调整界面,维护成本低;
    2. 局部组件用em:适配组件内的相对尺寸(如按钮内的图标与文字);
    3. 固定尺寸用px:如边框、图标等不需要适配的元素,px性能更优(无额外计算);
    4. 响应式布局用vw/vh结合clamp()限制范围,适配不同视口,同时避免过度依赖。
  • 性能注意rem/vw等相对单位仅在渲染时触发一次计算,性能影响可忽略,无需因性能规避。

使用 calc () 动态计算单位时,是否会对性能有明显影响?

calc()不会对性能产生明显影响:现代浏览器对calc()的解析与计算已高度优化,仅在布局渲染阶段执行一次简单运算,其性能开销远低于 DOM 操作、动画等场景。

  • 注意:避免在高频重绘的元素(如动画)中过度嵌套calc(),但常规使用无性能问题。

移动端样式适配或者做响应式布局

  1. viewport
  2. 媒体查询
  3. 相对单位 vw vh rem em %
  4. flex
  5. grid

什么是响应式设计?它的核心目标是什么?

响应式设计的定义

响应式设计是一种网页设计方法,通过灵活的布局、弹性的元素和设备适配规则,让同一个网页能自动适配不同尺寸的屏幕(如手机、平板、电脑),无需为不同设备单独开发多个版本。

核心目标

实现 “一处开发,多端适配”:让网页在任意设备上都能保持良好的布局结构、可读性和交互体验,同时降低开发与维护成本。

移动端适配中,何时使用 px、%、em、rem 和 vw/vh 等单位?各自的优缺点是什么?

移动端适配中各单位的使用场景与优缺点

1. px
  • 使用场景:需固定尺寸的元素(如 1px 边框、小图标、按钮内边距);不需要随屏幕缩放的细节元素。
  • 优点:尺寸精确、无计算开销,渲染性能优。
  • 缺点:无法随屏幕尺寸自适应,在不同设备上视觉比例易失调。
2. %
  • 使用场景:元素尺寸需相对于父容器适配(如容器宽度占父元素的 80%);流体布局中的模块宽度。
  • 优点:适配父容器尺寸,实现简单的相对布局。
  • 缺点:依赖父容器尺寸,嵌套层级复杂时易失控;无法直接关联视口尺寸。
3. em
  • 使用场景:局部组件内的相对尺寸(如按钮内的文字与图标大小适配);需随父元素样式联动的元素。
  • 优点:组件内尺寸联动性强,修改父元素样式可批量调整子元素。
  • 缺点:嵌套层级会导致尺寸叠加失控;维护成本高,全局使用易混乱。
4. rem
  • 使用场景:全局布局的自适应(如页面容器、字体大小);大型项目的统一适配基准。
  • 优点:基于根元素尺寸,全局统一基准,修改根字体即可批量适配;层级无关,易维护。
  • 缺点:需额外设置根元素基准值;极端屏幕尺寸下需配合媒体查询兜底。
5. vw/vh
  • 使用场景:视口级别的自适应(如全屏 banner、页面主容器占视口宽度的 90%);需随视口等比例缩放的元素。
  • 优点:直接关联视口尺寸,适配更精准;无需依赖父容器或根元素。
  • 缺点:小屏 / 大屏下易出现尺寸失控(需用clamp()限制范围);旧版浏览器(如 IE)兼容性差。

简单说一说 什么是 Retina 屏幕?为什么需要对高分辨率屏幕进行适配?

什么是 Retina 屏幕

Retina 屏幕是苹果公司提出的高像素密度(PPI)屏幕标准,其核心特点是屏幕像素密度足够高,人眼在正常观看距离下无法分辨单个像素点(通常 PPI≥300,如 iPhone 的 Retina 屏 PPI 约 326)。这类屏幕的设备像素比(DPR)≥2(即 1 个 CSS 像素对应 2×2 个设备像素)。

为什么需要对高分辨率屏幕适配

若不进行适配,普通分辨率的资源(如图片、图标)会在高分辨率屏幕上显示模糊:

  • 普通图片是基于 “1CSS 像素对应 1 设备像素” 设计的,当高分辨率屏幕用多个设备像素渲染 1 个 CSS 像素时,图片会被拉伸放大,细节丢失、边缘模糊;
  • 适配后,高分辨率屏幕可加载对应 DPR 的高清资源(如 2x 图),让每个设备像素都有对应的图像像素,保证画面清晰细腻,提升视觉体验。

如何使用 SVG 矢量图或 Icon Font 解决 Retina 屏幕的模糊问题?

一、用 SVG 矢量图解决模糊问题

SVG 是矢量图形格式,其内容由数学路径描述,而非像素点,因此可以无限缩放而不损失清晰度,天然适配 Retina 等高分辨率屏幕。

  • 使用方式

    1. 直接在 HTML 中嵌入 SVG 代码(如<svg width="24" height="24" viewBox="0 0 24 24"><path d="M..." /></svg>);
    2. 以图片形式引用(如<img src="icon.svg" alt="图标">);
    3. 作为 CSS 背景图(如background: url(icon.svg) no-repeat;)。
  • 优势:缩放无模糊、支持颜色修改(通过 CSS 控制 fill/stroke 属性)、文件体积小。

二、用 Icon Font 解决模糊问题

Icon Font 是将图标封装为字体文件,图标以字符形式渲染,本质是矢量图形,同样支持无限缩放,适配 Retina 屏幕。

  • 使用方式

    1. 引入 Icon Font 字体文件(如通过@font-face定义字体);
    2. 通过特定字符或 class 调用图标(如<<i class="icon-home"></</i>,配合 CSS 设置字体样式)。
  • 优势:缩放无模糊、可通过 CSS 统一修改颜色 / 大小、兼容性好(支持旧版浏览器)。

核心原理

Retina 屏幕的模糊问题源于像素类资源(如 PNG)被拉伸后像素不足,而 SVG 和 Icon Font 均为矢量形式,渲染时由浏览器根据当前屏幕的 DPR 实时绘制,始终保持边缘清晰,因此能完美解决高分辨率屏幕的模糊问题。

CSS clamp()函数的用法解析

clamp()是 CSS 的一个数值函数,作用是将一个值限制在最小值和最大值之间,语法为clamp(最小值, 中间值, 最大值):当中间值小于最小值时,取最小值;大于最大值时,取最大值;处于两者之间时,取中间值本身。

1. 动态调整属性值(自适应效果)

通过结合相对单位(如vw%)作为中间值,实现属性(如宽度、间距)的自适应:

  • 示例(控制容器宽度):

    .container {
      width: clamp(300px, 80vw, 1200px);
    }
    

    效果:容器宽度在小屏幕下不小于300px,大屏幕下不超过1200px,中间尺寸则随视口宽度(80vw)动态变化。

2. 字体的平滑适配

clamp()用于font-size,结合vw作为中间值,实现字体在不同屏幕下的自动缩放:

  • 示例:

    .title {
      font-size: clamp(1.5rem, 4vw, 3rem);
    }
    

    效果:小屏幕下字体不小于1.5rem,大屏幕下不超过3rem,中间尺寸随视口宽度(4vw)平滑过渡,避免字体在极端屏幕下过大 / 过小。

核心特点

  • 替代了传统的 “媒体查询 + 固定值” 的适配方式,代码更简洁;
  • 中间值通常结合相对单位(vw/vh),实现 “弹性” 的自适应效果;
  • 支持所有接受数值的 CSS 属性(如marginpaddingwidthfont-size等)。

不用vue-cli,你自己有搭建过vue的开发环境吗?流程是什么?

以下是手动搭建 Vue 开发环境的完整流程,涵盖从零开始配置 Webpack、Babel、热更新等核心工具。整个过程分为 基础配置进阶优化 两部分:


一、基础配置(开发环境)

1. 初始化项目
mkdir vue-manual-setup && cd vue-manual-setup
npm init -y
2. 安装核心依赖
npm install vue@2 # 或 vue@3
npm install webpack@5 webpack-cli webpack-dev-server --save-dev
npm install vue-loader@15 vue-template-compiler --save-dev
npm install css-loader style-loader file-loader --save-dev
npm install babel-loader @babel/core @babel/preset-env --save-dev
3. 项目目录结构
project/
├── src/
│   ├── App.vue        # 根组件
│   ├── main.js        # 入口文件
│   └── assets/        # 静态资源
├── public/
│   └── index.html     # HTML 模板
├── webpack.config.js  # Webpack 配置
└── babel.config.js    # Babel 配置
4. 配置 Webpack
// webpack.config.js
const path = require('path');
const { VueLoaderPlugin } = require('vue-loader');

module.exports = {
  mode: 'development',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    hot: true, // 启用热更新
    port: 8080,
  },
  module: {
    rules: [
      // Vue 单文件组件处理
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      // CSS 处理
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      // 图片等静态资源
      {
        test: /\.(png|jpe?g|gif|svg)$/i,
        type: 'asset/resource',
      },
      // Babel 转译 ES6+ 代码
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
  plugins: [
    new VueLoaderPlugin(), // 必须引入以支持 .vue 文件
  ],
};
5. 配置 Babel
// babel.config.js
module.exports = {
  presets: ['@babel/preset-env'],
};
6. 创建入口文件
<!-- public/index.html -->
<!DOCTYPE html>
<html>
  <head>
    <title>Manual Vue Setup</title>
  </head>
  <body>
    <div id="app"></div>
    <script src="/bundle.js"></script>
  </body>
</html>
// src/main.js
import Vue from 'vue';
import App from './App.vue';

new Vue({
  el: '#app',
  render: (h) => h(App),
});
<!-- src/App.vue -->
<template>
  <div>
    <h1>手动搭建的 Vue 环境</h1>
    <img src="./assets/logo.png" alt="Vue logo" />
  </div>
</template>

<script>
export default {
  name: 'App',
};
</script>

<style>
h1 {
  color: #42b983;
}
</style>
7. 添加启动脚本
// package.json
"scripts": {
  "dev": "webpack serve --config webpack.config.js",
  "build": "webpack --mode production"
}
8. 运行开发环境
npm run dev

访问 http://localhost:8080 即可看到运行效果。


二、进阶优化(生产环境)

1. 代码分割与优化
// webpack.prod.js
const { merge } = require('webpack-merge');
const baseConfig = require('./webpack.config.js');

module.exports = merge(baseConfig, {
  mode: 'production',
  optimization: {
    splitChunks: {
      chunks: 'all',
    },
    minimize: true,
  },
});
2. CSS 提取与压缩
npm install mini-css-extract-plugin css-minimizer-webpack-plugin --save-dev
// webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');

module.exports = merge(baseConfig, {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'], // 替换 style-loader
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[contenthash].css',
    }),
  ],
  optimization: {
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
});
3. 文件哈希缓存
output: {
  filename: '[name].[contenthash].js',
  path: path.resolve(__dirname, 'dist'),
  clean: true, // Webpack 5 自动清理 dist 目录
},
4. 环境变量区分
npm install dotenv-webpack --save-dev
// webpack.config.js
const Dotenv = require('dotenv-webpack');

module.exports = {
  plugins: [
    new Dotenv(), // 加载 .env 文件
  ],
};

四、手动搭建 vs Vue CLI

维度手动搭建Vue CLI
学习成本需深入理解 Webpack/Babel 配置零配置开箱即用
灵活性完全可控,适合深度定制默认配置优化,扩展需通过插件
维护成本需自行处理版本兼容性和构建优化官方维护升级,自动处理依赖更新
适用场景1. 教学/原理学习
2. 特殊构建需求项目
快速启动标准项目