🔗 关系图谱 · 技术因果链

这张图在说什么

前端三十年不是一堆孤立技术的罗列,而是一条因果链:几乎每一项技术,都是为了解决上一项的副作用而诞生的。 这张图用箭头 + 边标签,把”谁催生了谁、为什么催生”画出来。读它的正确姿势不是看节点,而是顺着箭头读边上的标签——那才是历史的真正动力。

怎么看

  • 节点 = 一项技术 / 一个范式
  • 箭头方向 = 时间与因果方向(A 催生 B)
  • 边标签 = 为什么(A 的什么痛点 / 什么红利,导致了 B)
  • subgraph 分组 = 时代。横向看一层抽象的演进,纵向看时代的更替。

一、总因果图

flowchart TD
    %% ===== 浏览器时代 =====
    subgraph ERA1["🌐 浏览器时代 1995-2005"]
        js["JavaScript 1995"]
        css["CSS / DOM"]
        browserwar["浏览器战争<br/>NN vs IE"]
        xhr["XMLHttpRequest 1999"]
        js --> css
        browserwar -->|"各家私有 API 互不兼容"| compat["兼容性地狱"]
        browserwar -->|"IE 内置非标准对象"| xhr
    end

    %% ===== Ajax 时代 =====
    subgraph ERA2["📡 Ajax 时代 2005-2013"]
        ajax["Ajax 2005 命名"]
        jquery["jQuery 2006"]
        v8["V8 引擎 2008"]
        node["Node.js 2009"]
        backbone["Backbone 2010"]
        angularjs["AngularJS 2010"]
        xhr -->|"异步局部刷新成为可能"| ajax
        ajax -->|"Gmail/Google Maps 证明网页能做应用"| webapp["网页变成应用"]
        compat -->|"抹平浏览器差异的迫切需求"| jquery
        ajax -->|"需要顺手的 DOM + Ajax 封装"| jquery
        webapp --> jquery
    end

    %% ===== SPA 时代 =====
    subgraph ERA3["⚛️ SPA 时代 2013-2018"]
        react["React 2013"]
        vue["Vue 2014"]
        angular2["Angular 2+ 2016"]
        vdom["虚拟 DOM"]
        oneway["单向数据流"]
        spa["SPA 单页应用"]
        redux["Redux 2015"]
        es6["ES6 2015"]
        jquery -->|"命令式 DOM 不可维护 / 无组件复用"| react
        angularjs -->|"双向绑定+脏检查在大应用性能崩溃"| react
        angularjs -->|"概念太重, 想要渐进式"| vue
        angularjs -->|"推倒重来, 拥抱 TS"| angular2
        react --> vdom
        react --> oneway
        vdom -->|"声明式渲染在性能上变得可行"| spa
        oneway --> spa
        react --> spa
        oneway -->|"跨组件共享状态难"| redux
        es6 -->|"class/箭头/模块, 语言现代化"| react
    end

    %% ===== 工程化时代 =====
    subgraph ERA4["🔧 工程化时代 2018-2023"]
        ssr["SSR / SSG / ISR / RSC"]
        webpack["Webpack 2014→"]
        vite["Vite 2020"]
        esm["ES Modules"]
        babel["Babel"]
        ts["TypeScript 2012"]
        hooks["React Hooks 2019"]
        zustand["Zustand 2021"]
        svelte["Svelte 编译时"]
        pnpm["pnpm 2017"]
        spa -->|"首屏白屏 + SEO 灾难"| ssr
        spa -->|"组件化工程需要模块打包"| webpack
        webpack -->|"冷启动 / HMR 太慢"| vite
        esm -->|"浏览器原生支持模块, 开发期免打包"| vite
        babel -->|"让 JSX/ES6 跑在老浏览器"| react
        ts -->|"大型应用需要类型约束"| angular2
        react -->|"class 组件逻辑复用难 (HOC/render props 地狱)"| hooks
        redux -->|"样板代码太多, 想要极简"| zustand
        vdom -->|"反思: 虚拟 DOM 有运行时开销"| svelte
        npmyarn["npm → Yarn"] -->|"node_modules 黑洞 + 幽灵依赖"| pnpm
    end

    %% ===== 模块化主线(贯穿) =====
    subgraph MOD["📦 模块化主线"]
        scripttag["script 标签全局污染"]
        commonjs["CommonJS / AMD"]
        browserify["Browserify 2011"]
        scripttag -->|"全局变量冲突, 无依赖管理"| commonjs
        commonjs -->|"Node 的模块能否搬到浏览器?"| browserify
        browserify -->|"打包思路被发扬光大"| webpack
        commonjs -->|"标准缺位, 社区先行"| esm
    end

    %% ===== 运行时主线 =====
    v8 -->|"JS 终于足够快"| node
    node -->|"JS 能跑在服务端 → 前端工程化基础设施"| webpack
    node -->|"npm 生态爆发"| npmyarn
    node -->|"历史包袱: 安全/TS/模块"| deno["Deno 2020"]
    node -->|"想要更快的一体化运行时"| bun["Bun 2022"]
    ts --> deno

    %% ===== AI 时代 =====
    subgraph ERA5["🤖 AI 时代 2023-未来"]
        copilot["GitHub Copilot 2021"]
        cursor["Cursor 2023"]
        claudecode["Claude Code 2024"]
        agent["Agent"]
        mcp["MCP 2024"]
        ainative["AI-Native 开发"]
        copilot -->|"补全不够, 想要理解整个项目"| cursor
        cursor -->|"从 IDE 内补全到自主执行"| claudecode
        claudecode -->|"能用工具/多步规划"| agent
        agent -->|"需要标准化的工具/上下文协议"| mcp
        mcp --> ainative
        agent --> ainative
    end

    %% ===== 汇入 AI =====
    ts -->|"类型即给 AI 的规格说明"| copilot
    react -->|"海量训练语料, 成为 AI 默认输出"| copilot
    vite -->|"快反馈闭环利于 AI 迭代"| ainative
    ssr -->|"渲染范式继续演化"| ainative
    svelte -->|"编译时思路延续"| ainative

    %% ===== 样式 =====
    classDef era1 fill:#e3f2fd,stroke:#1976d2;
    classDef era5 fill:#f3e5f5,stroke:#7b1fa2;
    class js,css,browserwar,xhr,compat era1;
    class copilot,cursor,claudecode,agent,mcp,ainative era5;

二、读图:四条主脉络

这张网看似复杂,其实只有四条主线在反复交织。把它们单独抽出来,因果就清晰了。

脉络 1:抽象上移线(整张图的脊柱)

手写 DOM → jQuery(命令式封装) → React/Vue(声明式框架) → Svelte(编译器) → AI Coding(自然语言)

每一代都在做同一件事:让开发者少关心一层底层细节

  • jQuery:你还要关心”怎么操作 DOM”,但不用关心浏览器差异。
  • React:你连”怎么操作 DOM”都不用管了,只描述 UI = f(state)
  • Svelte:你连”运行时框架”都不用打包了,编译器在构建期把它干掉。
  • AI:你连”怎么写代码”都可以用自然语言描述,模型补全实现。

抽象每上移一层,生产力提升一个量级,但理解力也下沉一层(见 演进逻辑-五个永恒矛盾 的矛盾五)。

脉络 2:模块化线(从混乱到标准的潮汐)

script 标签(全局污染) → CommonJS/AMD(社区方案) → Browserify(把 Node 模块搬进浏览器)
    → Webpack(万物皆模块) → (慢) → Vite ← ESM(标准最终追认)

这是一条典型的”社区先行、标准追认”潮汐:浏览器迟迟没有原生模块,社区造了 CommonJS/AMD/UMD 一堆方言;Browserify/Webpack 用打包把方言抹平;最后 ESM 成为语言标准,Vite 借浏览器原生 ESM 实现”开发期免打包”,反过来淘汰了打包器的一部分存在理由

脉络 3:渲染螺旋线(否定之否定)

MPA 服务端渲染 → (交互弱) → SPA 客户端渲染 → (白屏/SEO) → SSR 回归
    → SSG(预渲染) → ISR(增量) → RSC(服务端组件)

渲染模式不是直线进步,而是螺旋:前端把渲染从服务端搬到客户端(SPA),解决了交互问题却制造了白屏和 SEO;于是又把渲染搬回服务端(SSR/RSC),但这次带着组件化和水合(hydration)的新能力回去。详见 渲染模式演进史

脉络 4:性能/DX 线(工具链的军备竞赛)

Webpack(功能全但慢) → esbuild/SWC(Go/Rust 重写) → Vite(原生 ESM + 按需编译)
npm(慢/黑洞) → Yarn(锁文件/并行) → pnpm(硬链接/解决幽灵依赖)
Node → Deno/Bun(更快的一体化运行时)

当框架格局稳定后,竞争焦点转向开发体验(DX)与构建速度。“用更快的语言(Go/Rust)重写 JS 工具链”成为 2020 年后的主旋律。详见 前端工程化演进史为什么Vite能取代Webpack


一句话总结这张图

没有一项技术是凭空出现的——每一代都是上一代副作用的解药,而每一剂解药又埋下下一代的病根。 这就是前端演化的第一性逻辑。


🔗 相关:MOC-前端技术演化史 | 时间线总览 | 演进逻辑-五个永恒矛盾 | 术语表 🔗 时代:1995-2005 浏览器时代 | 2005-2013 Ajax时代 | 2013-2018 SPA时代 | 2018-2023 工程化时代 | 2023-未来 AI时代 🔗 关键技术:jQuery | React | Vite | Webpack | Node.js | Svelte | Agent与MCP