本文主要介绍前端框架是如何实现的。
打包过程
程序员使用框架编写好网页后,往往需要执行 npm run build
之类的东西,把代码转换为浏览器可以直接运行的代码。这个过程一般包括以下几个步骤:
- 将每个 component 转换为 JavaScript
- 将所有 component 合成单个 JavaScript 文件
app.bundle.js
(对于部分 lazy-load 的页面,可能会合成多个) - 将第三方的包和框架本身合成单个 JavaScript 文件
vendor.bundle.js
- 将所有 CSS 合成单个 CSS 文件
bundle.css
(同样可能会有多个) - 生成或者直接从静态文件中获取
index.html
- 将静态文件(图片、字体等)复制到输出目录
因此,最终的输出目录结构可能如下:
dist/
├──index.html
├──app.bundle.js
├──vendor.bundle.js
├──bundle.css
└──...
之后,只需要上传到服务器就可以了。
SPA 访问过程
当用户使用浏览器访问打包好的 SPA(单页应用)网页时,通常会经历以下几个步骤:
-
浏览器向服务器请求
index.html
。该文件几乎为空,其中通常包含<link rel="stylesheet" href="bundle.css"> <script src="app.bundle.js"></script> <script src="vendors.bundle.js"></script>
-
浏览器解析
index.html
,并向服务器请求其中的bundle.css
、app.bundle.js
和vendors.bundle.js
-
Mounting:
vendor.bundle.js
中的框架代码会读取app.bundle.js
中需要被渲染的 component;然后使用 Document API 程序化生成 HTML 内容,并插入到index.html
中 -
Patching:当用户与页面交互时,框架会根据用户的操作,动态地修改页面的内容。框架通常会修改尽量少的 DOM 元素,以优化性能。
要想修改尽量少的 DOM 元素,通常有以下几种方法:
-
绝大多数框架(React、Vue 等)会维护一个 Virtual DOM,当需要修改页面时,先修改 Virtual DOM,然后比较 Virtual DOM 和真实 DOM 的差异,最后只修改差异部分。
为了知道何时需要修改 Virtual DOM,React 监控组件的 state 和 props 的变化;Vue 则通过响应式数据层,当数据变化时会触发 setter,从而通知框架重新渲染。
-
Svelte 会在编译时就确定可能会变化的部分,然后生成对应的 JavaScript 代码。这使得它在运行时的性能更好,但编译时间更长。
-
Angular 则使用了 Change detection,通过 Zone.js 捕获异步事件(event listener、HTTP 请求、或者其它事件循环中的事件),然后在事件处理函数执行完毕后,检查所有组件的状态是否发生变化,如果有变化则更新。
-
-
当用户点击内部链接时,框架会拦截这个事件,由 router 选择需要展示的 view,然后重新渲染;同时修改 URL。这样就实现了 SPA 的单页切换效果,此过程无需再与服务器通信。
SSR 访问过程
SSR(服务器端渲染)是指在服务器端生成 HTML,然后再发送给浏览器。在使用 SSR 时,通常会经历以下几个步骤:
- 浏览器向服务器请求页面,服务器根据 URL,将需要渲染的 component 组装成 HTML,然后返回给浏览器
- Hydrating:浏览器接收到 HTML 后,会根据其要求,从服务器请求 JavaScript 和 CSS 文件。然后浏览器会将接收到的 HTML 链接到 Virtual DOM 上
- 当用户与页面交互时,过程和 SPA 类似
- 当用户点击内部链接时,浏览器会向服务器请求新的页面,然后再次执行上述过程
Comments