从虚拟DOM到服务端渲染的

举报
8181暴风雪 发表于 2025/08/29 19:34:38 2025/08/29
【摘要】 回想我刚踏入前端这个行当的时候,jQuery 几乎是唯一的“神”。我们用它操作DOM、处理事件、发送Ajax请求,感觉一个库就能包打天下。但随着业务越来越复杂,网页从简单的“文档”变成了复杂的“应用程序”(WebApp),我们发现,仅仅依靠 jQuery 那种“面向过程”的修补模式,代码会变得越来越难以维护,性能也随之亮起红灯。就在这个时期,以 React、Vue、Angular 为代表的现...

回想我刚踏入前端这个行当的时候,jQuery 几乎是唯一的“神”。我们用它操作DOM、处理事件、发送Ajax请求,感觉一个库就能包打天下。但随着业务越来越复杂,网页从简单的“文档”变成了复杂的“应用程序”(WebApp),我们发现,仅仅依靠 jQuery 那种“面向过程”的修补模式,代码会变得越来越难以维护,性能也随之亮起红灯。

就在这个时期,以 React、Vue、Angular 为代表的现代前端框架应运而生。它们不仅仅是库,更带来了一整套全新的开发思想和工程化方案。今天,我想和大家聊聊支撑起这些现代框架的四大核心技术基石。理解了它们,你才算真正摸到了现代前端开发的脉络。

一、 虚拟DOM (Virtual DOM):不是为了更快,而是为了更合理

很多新手,包括当年的我,对虚拟DOM的第一个认知就是“它比直接操作原生DOM快”。这个说法其实不完全准确,甚至在某些场景下是错误的。

1. 痛点在哪里?

浏览器中,DOM操作的开销是相当大的。每次我们动用 document.getElementById().innerHTML = ... 之类的操作,都会触发浏览器的“重排”(Reflow)和“重绘”(Repaint),这是一个非常消耗性能的过程。如果一个复杂的应用有成百上千次DOM更新,页面就会变得卡顿不堪。

2. 虚拟DOM的巧思

虚拟DOM的本质,其实是一个普通的JavaScript对象。它就像是真实DOM结构的一份“蓝图”或“快照”。

当组件的状态发生变化时,框架会根据新的状态生成一个新的虚拟DOM树。然后,它并不会立刻去操作真实DOM,而是用一个叫做 Diff(差异对比) 的算法,去比较新旧两份“蓝图”之间的差异。

Diff算法会找出最小的变更集(比如,只是某个<span>标签的文本变了),然后才把这些“补丁”一次性地应用到真实的DOM上。

说白了,虚拟DOM的核心思想是:用计算成本较低的JavaScript计算,来代替计算成本高昂的DOM操作。 它将多次DOM操作合并为一次,从而在宏观上提升了性能和开发体验。

对比项 直接操作DOM 使用虚拟DOM
性能开销 频繁操作时,会多次触发重排和重绘,性能差。 通过Diff算法,将多次操作合并为一次,减少了DOM操作的次数,宏观性能更优。
开发心智 开发者需要手动管理DOM的增删改查,心智负担重。 开发者只需关心状态(State),由框架负责将状态映射到视图,无需关心具体DOM操作。
跨平台能力 强依赖浏览器环境,无法用于其他平台。 JavaScript对象是普适的,这为跨平台渲染(如React Native)提供了可能性。

所以你看,虚拟DOM的初衷,更多的是为了解放生产力,让开发者从繁琐的DOM操作中解脱出来,用“数据驱动视图”的模式去思考问题。

二、 状态管理 (State Management):告别混乱的数据流

随着应用变得复杂,组件之间的通信成了一个大问题。你可能遇到过这样的场景:一个状态需要从顶层组件一层层地通过 props 传递给深层的子组件,这被称为“Props Drilling”(属性逐层传递)。如果中间某个环节出了问题,调试起来简直是灾难。

1. 为什么需要它?

当多个组件需要共享或依赖同一个状态时,或者一个组件的状态需要被其他不相关的组件改变时,组件间零散的通信方式会让数据流变得混乱且不可预测。

2. 状态管理的“中央仓库”模式

状态管理库(如 Redux、Vuex、Pinia)的出现,就是为了解决这个问题。它的核心理念很简单:与其让数据在组件间传来传去,不如我们建一个全局的“中央仓库”(Store),统一存放和管理应用的所有共享状态。

  • 读取:任何组件都可以直接从这个“仓库”里读取数据。
  • 更新:组件不能直接修改“仓库”里的数据。它必须发出一个明确的“意图”(在Redux中叫Action,在Vuex中叫Mutation/Action),由“仓库管理员”来执行真正的修改操作。

这种模式带来了巨大的好处:

  • 数据流清晰:所有状态变化都是可预测、可追溯的。
  • 调试方便:配合开发者工具,你可以清晰地看到每一次状态是如何、因为什么而改变的。
  • 组件解耦:组件只需关心自己的业务逻辑和与“仓库”的交互,无需关心其他组件。
优点 缺点
解决了跨组件通信和数据共享的难题。 对于小型、简单的项目,可能会增加不必要的复杂性。
提供了可预测的状态变化,让调试变得容易。 需要学习额外的概念和API(如Action, Reducer, Mutation等)。
方便进行状态持久化、时间旅行调试等高级操作。 引入了更多的模板代码。

我个人认为,对于中大型项目,引入一个合适的状态管理库是必然的选择。它前期的学习成本,会在后期维护阶段得到丰厚的回报。

三、 摇树优化 (Tree Shaking):给你的代码“减肥”

这个词非常形象。想象一下,你摇晃一棵树,枯死的叶子会掉下来,只剩下健康的绿叶。在前端工程化里,“树”就是你的代码,“枯叶”就是那些你引入了但从未使用过的代码。

1. 它是如何工作的?

Tree Shaking 是一种通过静态分析代码,移除无用代码(Dead Code)的优化技术。它的实现强依赖于 ES6 模块规范(importexport

因为 importexport 的语法是静态的,打包工具(如 Webpack、Rollup)可以在编译时就明确地知道你从一个模块中引入了什么,以及导出了什么。

举个例子:

假设你有一个工具库 utils.js

// utils.js
export function add(a, b) {
  console.log('add function is called');
  return a + b;
}

export function subtract(a, b) {
  console.log('subtract function is called');
  return a - b;
}

在你的主文件 main.js 中,你只使用了 add 函数:

// main.js
import { add } from './utils.js';

console.log(add(5, 3));

在打包时,支持Tree Shaking的工具会分析出 subtract 函数从未被使用过,因此在最终生成的打包文件(bundle)中,subtract 函数的代码就会被“摇掉”,根本不会包含进去。

特性 摇树优化前 (Without Tree Shaking) 摇树优化后 (With Tree Shaking)
打包体积 包含模块中所有导出的代码,体积较大。 只包含实际使用到的代码,体积显著减小。
执行效率 浏览器需要解析和执行更多的无用JavaScript代码。 减少了需要解析和执行的代码量,提升了首屏加载速度。
依赖关系 整个模块被视为一个整体依赖。 依赖关系可以精确到函数/变量级别。

在当今这个对Web性能要求极致的时代,Tree Shaking 几乎是所有现代前端项目打包流程中的标配。

四、 服务端渲染 (SSR):让首屏和SEO不再是痛点

我们现在主流的开发模式是客户端渲染(Client-Side Rendering, CSR)。浏览器先下载一个几乎空白的HTML文件和一个巨大的JavaScript包,然后由JS在浏览器端执行,生成DOM并渲染出页面内容。

1. CSR的问题

  • 首屏加载慢(白屏时间长):用户需要等待JS下载、解析、执行完毕后才能看到页面内容。
  • SEO不友好:搜索引擎的爬虫可能无法正确执行JS,导致抓取到的页面是空白的,不利于搜索引擎排名。

2. SSR如何解决?

服务端渲染(Server-Side Rendering, SSR)则反其道而行之。当用户请求页面时,服务器会先在后端环境中执行前端代码(例如在Node.js环境中运行React/Vue代码),将组件渲染成完整的HTML字符串,然后将这个HTML直接发送给浏览器。

浏览器接收到HTML后可以立刻显示页面内容,用户能第一时间看到骨架。与此同时,之前在CSR模式下所需的JS文件也在后台悄悄下载。下载完毕后,JS会“接管”(这个过程叫 Hydration,注水)页面,让页面变得可交互。

对比项 客户端渲染 (CSR) 服务端渲染 (SSR)
首屏加载速度 慢,有较长的白屏时间。 快,浏览器接收到HTML后可立即渲染。
SEO友好度 差,爬虫可能抓取不到内容。 好,返回的是完整的HTML,对爬虫友好。
服务器压力 小,服务器只负责提供静态文件。 大,需要在服务器端进行计算和渲染。
交互响应时间 首屏后,页面内路由跳转和交互响应快。 首次请求后,页面完全可交互需要等待JS加载执行完毕(注水过程)。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。