前端技术架构-产品前端技术架构文档
前端架构
从宏观角度介绍了大型网站架构。
从本文开始,我们将着重于细节,一一介绍前面章节中提到的前端、后端、云计算服务层的技术架构。
其中,前端部分直接影响到用户体验,因此本文首先介绍一下前端部分的架构。
需要注意的是,这里的前端指的是B/S架构网站中的前端网页,是一个静态网页。
前端如何工作
在讨论前端架构之前,我们先搭建一个前端web服务器,然后通过构建一个简单的网页来了解它的工作原理。 了解了前端网页的工作原理之后,我们才能更好的理解前端架构需要注意的细节。
网站服务器搭建
如果一个网页想要被非原生浏览器访问,就需要架设一个网络服务器。 目前主流的web服务器软件有3种,分别是Apache、IIS和Nginx。
Apache 是目前使用最多的网络服务器软件。 其性能极其稳定,扩展模块全面多样,可运行于Windows、Linux等多种平台。 IIS 是 Microsoft 提供的基本 Internet 服务。 除了提供Web服务外,它还提供FTP、NNTP和SMTP等服务,但IIS只能运行在Windows操作系统上; Nginx是一款轻量级的Web服务器软件,支持负载均衡、反向代理等功能。 扩展模块虽然不如Apache全面,但比Apache占用内存和资源少,在高并发处理上表现更好。
Web服务器的选择需要根据具体情况来确定。 对于一般的大型网站,由于服务器操作系统一般基于比较稳定的Linux,服务器需要应对大量的网页请求(高并发),本书选择Nginx作为Web服务器软件。
Nginx的安装以Windows系统和CentOS系统为例。 之所以选择这两个系统进行介绍,是因为Windows一般是开发者在开发时使用的操作系统,而CentOS一般是网站服务器操作系统。
1.Windows系统安装Nginx
Windows系统安装Nginx的具体步骤如下:
(1)从Nginx官网()下载Nginx,一般选择下载稳定版。 官网的Nginx版本划分如图3.1所示。 这里我们下载Windows系统上的稳定版。
图3.1 Nginx官网版本划分
(2)下载Nginx压缩包后,解压到一个目录下。 目录结构如图3.2所示。 其中html文件夹默认存放网页资源,conf文件夹存放Nginx的相关配置文件,logs文件夹存放Nginx运行日志。
图3.2 解压后的Nginx目录结构
(3)修改Nginx配置,Nginx配置文件为conf/nginx.conf。 默认配置文件如代码3.1所示,其中“...”表示省略,“#”后为属性注释。 对于本地调试,保持默认配置即可。
代码3.1默认Nginx配置
……
服务器 {
听80; #port,80是HTTP的默认端口
服务器名称默认服务器; #服务名称
……
地点 / {
根 HTML; #Web资源文件夹,其中html指的是图3.2中的html文件夹
索引index.html; #网站默认页面
}
……
}
……
……
(4) 启动服务,双击图3.2中的nginx.exe文件,运行窗口闪过。 在不修改默认配置正常启动的情况下,在浏览器中输入地址会打开Nginx的默认网页,如图3.3所示。 默认网页是图 3.2 中 html 文件夹中的 index.html。
图 3.3 Nginx 默认网页
如果无法正常启动,可以在图3.2的logs文件夹中查看运行日志。 启动失败一般是端口冲突导致的。 此时可以修改步骤(3)中的listen配置项。
如果在步骤(3)中修改了server_name和listen配置项,需要在浏览器地址栏输入server_name:listen。 例如设置server_name为192.168.3.3,监听8081,则应在浏览器地址栏输入:8081。 一般情况下,只需将 server_name 设置为 default_server 即可。
此外,还可以通过在任务管理器中结束所有nginx.exe任务来关闭Nginx服务,如图3.4所示。
图 3.4 关闭 Nginx 服务
(5)设置防火墙。 如果非原生浏览器要访问网页,需要设置防火墙端口的权限。 对于大型网站,服务器系统一般为Linux,Windows系统下安装Nginx一般只是为了方便本地开发。 非本地浏览器访问的场景比较少,所以不需要防火墙设置。 如果开发过程中有非本地访问,可以暂时关闭Windows防火墙。
2.在CentOS系统中安装Nginx
在Centos系统安装Nginx时,虽然也可以从官网下载安装,但是操作比较复杂。 所以这里推荐使用yum安装。 这种安装方式简单、方便、不易出错。 具体操作步骤如下:
(1) 添加Nginx源。 CentOS系统默认不包含Nginx源。 添加Nginx源的命令如代码3.2所示,其中“\”为换行符。 添加成功后,/etc/yum.repos.d目录下会多出一个nginx.repo文件。
代码3.2命令添加Nginx源
sudo rpm -ivh \
el7.ngx.noarch.rpm
(2) 安装Nginx的命令如代码3.3所示。 CentOS系统中,Nginx默认安装在/etc/nginx目录下,配置文件为/etc/nginx/nginx.conf,运行日志路径为/var/log/nginx/,默认web资源存储在 /usr/share /nginx/html/ 目录中。
代码3.3命令安装Nginx
sudo yum -y 安装 nginx
(3) 修改配置。 Nginx的配置文件是/etc/nginx/nginx.conf。 默认配置文件如代码3.4所示,其中“...”表示省略,“#”后为属性注释。 对于本地调试,保持默认配置即可。
代码3.4 CentOS系统Nginx配置
服务器 {
听80; #port,80是HTTP的默认端口
服务器名称默认服务器; #服务名称
……
地点 / {
根/usr/share/nginx/html; #网页资源文件目录
索引index.html; #网站默认页面
}
……
}
……
(4) 启动服务。 设置Nginx自动启动、启动服务、停止服务的命令如代码3.5所示。 其中“#”表示注释部分,在输入命令时不需要,后面不再详述。
代码3.5 Nginx启动命令
sudo systemctl enable nginx #设置开机启动
sudo systemctl start nginx #启动服务
sudo systemctl 停止 nginx #停止服务
(5) 配置防火墙。 一般在第(4)步配置后就可以启动Nginx,但是如果开启了防火墙,非本地浏览器是无法访问网页的,所以这里需要配置防火墙。 配置防火墙的命令如代码3.6所示,需要依次执行命令。
代码3.6命令配置防火墙
sudo firewall-cmd --add-service=http --permanent #开启防火墙的HTTP服务
#开启端口,根据Nginx的端口配置,替换80即可
sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --reload #重启防火墙
防火墙配置成功后,非本地浏览器访问网页效果如图3.5所示。
图 3.5 非原生浏览器访问网页
需要注意的是,如果有明确的Nginx版本要求,需要到官网下载安装。
建立一个简单的网页
安装Nginx后,有一个默认的网页,如图3.3或图3.5所示。 这个网页只有一个HTML文件,与我们通常的网页结构不同。 这样的网页会导致我们不能完全理解前端网页的工作原理。 我们一般会将一个网页分为一个HTML文件、多个CSS样式文件和多个JavaScript文件,所以在介绍前端工作原理之前,我们还需要构建一个简单的网页,其中会包含一个HTML文件、两个CSS文件文件和两个javascript文件。
注意:本节构建的网页只是为了方便解释3.1.3节,其中的编码细节不作为实际编码的参考。
1. 创建一个 HTML 文件
创建一个 abc.html 文件,如清单 3.7 所示。 HTML文件主要用于设置网页的属性和定义页面元素。 该页面的元素主要包括标题、一行文字和按钮。
代码 3.7 abd.html文件的代码
简单的例子
简单的翻译例子
你好世界。
转变
这里需要明确的是,一个网页除了嵌入iframe的情况外,只有一个HTML文件。 在HTML的规范中,除了这样的标准声明外,还应该包括其他内容。 里面的内容主要包括head元素()和body()两部分。 head元素主要包括一些网页属性的设置,body是定义网页元素的部分。
一个HTML文件可以引用多个CSS样式文件,被引用的CSS文件的位置一般在中间,有利于网页的加载,在后面的工作原理讲解中会详细说明.
一个HTML文件可以引用多个JavaScript脚本文件,引用的位置一般在末尾,有利于网页的显示,也可以避免一些错误,在后续的工作原理中会详细说明.
注意:网页元素(如按钮等)写在外面或外面,网页仍会正常显示,因为浏览器有容错机制,但这不是HTML规范的初衷.
2.创建两个JavaScript文件
下面创建两个 JavaScript 文件,用于网页的交互处理。 第一个文件名为js_1.js,如代码3.8所示,其内容主要定义了两个变量。
代码 3.8 js_1.js文件代码
var EnglishText = "你好,世界。";
var ChineseText = "你好,世界。";
另一个文件名为js_2.js,如清单3.9所示,其内容是对网页上的文本进行转换。 该函数在网页点击按钮后被调用,代码3.7中的“转换”绑定了translates()函数。
代码 3.9 js_2.js文件代码
var 翻译 = 函数 () {
var text = document.getElementById("id_text").innerText;
如果(文本==英文文本){
document.getElementById("id_text").innerText = ChineseText;
} 别的 {
document.getElementById("id_text").innerText = EnglishText;
}
}
JavaScript本身没有命名空间等限制,只要在同一个HTML文件中引用就可以相互调用。 比如上面的例子,页面引用了js_1.js和js_2.js两个JavaScript文件,js_2.js中的函数可以直接使用js_1.js中定义的变量。
注意:这里可以将两个JavaScript文件的内容写在一个JavaScript文件中,分成两个JavaScript文件只是为了模拟多个JavaScript文件的情况。
3.创建两个CSS文件
下面创建两个 CSS 样式文件。 CSS样式文件的作用是为HTML文件中的网页元素提供样式和布局设置,比如提供字体大小、间距、颜色等设置。 一个CSS文件名为css_1.css,如清单3.10所示,其内容是定义标题的样式。 在清单 3.7 中“
简单的翻译例子
"绑定标题样式属性。
代码3.10Css_1.css文件代码
/* 定义标题的样式 */
。标题{
底部边距:10px;
字体大小:32px;
}
另一个 CSS 文件名为 css_2.css,如清单 3.11 所示,其内容是定义文本的样式。 “你好世界。” 在清单 3.7 中,通过 id(id_text) 绑定到样式属性。
代码 3.11 css_2.css 文件代码
注意:这里的两个样式定义可以写在一个CSS文件中,拆分成两个CSS文件只是为了模拟多个CSS文件的情况。
4.发布网页
为了后面解释网页地址方便,在Nginx网页资源目录下创建一个sample文件夹,将新建的abc.html、css_1.css、css_2.css、js_1.js和js_2.js文件放入sample中文件夹。 以Windows系统中的Nginx为例,其目录结构如图3.6所示。
图 3.6 Nginx 目录结构
Nginx默认配置情况下,在浏览器地址栏输入
,显示页面如图3.7所示。
图 3.7 页面效果
点击“转换”按钮后,文本将被转换,如图3.8所示。
图3.8 点击按钮后的网页效果
前端网页是如何工作的
在成功构建了一个简单的网页并运行之后,接下来介绍前端网页的工作原理。
通过3.1.1节和3.1.2节的介绍,我们知道一个网页要运行起来至少需要两步。 第一步是搭建一个web服务器,以便浏览器可以请求和获取网页资源文件; 第二步,将网页资源文件放到web服务器上。 网页前端的工作原理也分为两部分:一部分是浏览器加载网页资源,介绍浏览器与Web服务器的关系; 另一部分是浏览器运行网页,介绍浏览器与网页的关系。
注:本节默认以Chrome浏览器为描述对象。 虽然不同的浏览器在运行网页时的工作原理不同,但总体流程基本相同。 本节在原理说明中会省略很多细节,读者只需要有一个大概的了解即可。
1.浏览器加载网页资源
一个网站是由很多网页组成的,每个网页都有自己的地址。 以3.1.2节网页为例,在浏览器地址栏输入网址(
) 并回车,相当于向服务器发送请求。 该请求包含多个部分,如图 3.9 所示。 为了对URL有一个全面的解释,这里补充端口部分和参数部分。
解释:像这样的URL或者某个资源的网络地址,一般称为URL(Uniform Resource Locator,统一资源定位器),后面对URL或者网络地址的描述都会用URL代替。
图 3.9 网页地址结构
协议:请求网页资源的协议一般是HTTP或者HTTPS。 由于HTTPS的安全性更高,而浏览器对于使用HTTP的网站会提示“不安全”,所以现在普遍使用HTTPS。 如果使用 HTTPS,则需要对 Web 服务器进行额外配置。 但是,HTTPS只是在HTTP的基础上对通信进行了加密。 加解密过程由浏览器和Web服务器自动完成。 我们只需要配置web服务器,对网站开发本身没有任何影响。
Hostname(主机名):这个可以是域名,也可以是服务器的公网IP。 如果是域名,域名解析服务器(DNS)会自动将域名转换为服务器的公网IP,然后才真正向Web服务器发送请求。 域名解析服务器为公共资源(一般情况下不可操作)。 购买域名后,在购买域名的网站绑定域名和服务器的公网IP,即可自动将信息同步到DNS。
端口(port):一般使用默认端口。 端口部分如果是默认端口可以省略。 HTTP 的默认端口是 80,HTTPS 的默认端口是 443。
协议+主机名+端口:有了这三部分,Web服务器就可以接收用户发送的请求。 Web服务器收到请求后,会继续解析URL的后续部分。
Path(路径):Web服务器根据路径查找资源。 在图3.9所示的例子中,Web服务器会根据路径/sample/abc.html找到abc.html网页文件,并将文件内容发送给浏览器。 但是,资源不一定都是文件,也可能是后端接口。 但无论请求什么资源,Web 服务器都会以字节流的形式返回内容。
参数(parameters):来自“?” 到最后是参数部分,多个参数用“&”分隔。 参数一般在请求资源时使用,其处理不一定在服务器端进行,也可能由网页的JavaScript脚本进行处理。
注意:URL中也可以加入信息片段,一般以“#”开头在整个URL的末尾,如
#家。 信息片段部分只会被网页的JavaScript脚本处理,所以如果只更新这部分,网页不会被浏览器刷新。
以上就是对URL的介绍,我们再回到浏览器加载网页资源的过程。 服务器收到请求后返回网页文件,浏览器解析网页文件。 当它发现网页文件中有其他资源需要下载时(如代码3.7),它会向web服务器请求一个新的文件。 以3.1.2节的网页为例前端技术架构,浏览器加载网页资源的全过程如图3.10所示。
图 3.10 浏览器加载网页资源全过程
注意:所有的文件资源都是以字节流的形式返回的,浏览器会在获取到部分内容后立即进行处理,而不是获取到所有的文件资源后再进行解析。 资源请求的方式一般是异步请求,即不会等待上一次请求的所有资源都获取完毕,才开始请求下一个网页资源。
对于图3.10所示的请求流程,可以按F12键打开浏览器的开发工具查看具体的请求详情。 以Chrome浏览器为例,其开发者工具如图3.11所示。
图 3.11 使用开发者工具查看资源请求详情
2.浏览器运行网页
浏览器显示网页的工作流程大致可以分为四个部分,即构建 DOM 树、构建渲染树、布局处理和绘制页面,如图 3.12 所示。 由于浏览器是对网页进行流式处理,所以这个过程不是一次性完成的,可能每解析完一部分网页就执行一次。
图 3.12 浏览器显示网页过程
DOM树可以理解为结构树或者内容树。 浏览器解析HTML文档,将每个元素标签一一转化为DOM节点,即将HTML文档中的标签转化为一棵结构树。 这个解析和构建过程是流线型的,每次浏览器获取 HTML 的一部分时,它都会立即解析它。 以3.1.2节的网页为例,其DOM树如图3.13所示,省略了元素的属性。
图 3.13 DOM 树
渲染树是网页显示部分的数据结构。 在构建DOM树的同时,还会解析外部CSS文件和元素标签中的样式设置,浏览器会构建对应CSS样式的CSSOM树。 浏览器会利用 CSSOM 树中的视觉属性(如颜色和大小)和 DOM 树中相应的元素来构建另一个结构——表现树。 渲染树对应DOM树,可以简单理解为给DOM树的节点添加视觉属性。 但是渲染树和DOM树并不是一一对应的。 渲染树只记录在浏览器上可以显示的部分。 一些非可视元素(如 )和一些隐藏元素不会被记录在渲染树中。 仍以3.1.2节中的网页为例,其展示树如图3.14所示。
图 3.14 展示树
渲染树构建完成后,进入布局处理阶段。 布局处理阶段主要是根据渲染树和浏览器窗口的大小,计算出每个节点出现在屏幕上的确切坐标。 最后是绘制,也就是绘制网页。
浏览器显示网页是一个渐进的过程,上述过程不是一次性完成的。 浏览器会尽快将内容显示在屏幕上,而不是等到整个 HTML 文档解析完毕才开始构建渲染树和设置布局。
浏览器在不断接收和处理网络资源的同时,也在不断地解析和展示内容。 上面的过程中没有提到JavaScript文件的作用。 浏览器有专门的 JavaScript 解析器来处理 JavaScript 文件。 JavaScript解析器中会有一些预编译过程,但这是内部行为,我们不必太在意。
JavaScript脚本可以响应网页事件(如点击和拖动等),调用浏览器的一些功能(如全屏等),与远程服务器通信(请求数据)等。JavaScript脚本用于网页显示,它最大的作用是修改HTML内容(即可以改变DOM树,一般来说,JavaScript脚本修改HTML内容的操作也称为DOM操作),HTML内容改变后前端技术架构,浏览浏览器会自动重新排列和重新绘制网页以显示新网页。 例如3.1.2节的网页,当点击按钮时,JavaScript脚本会自动改变网页的文本内容。
以上就是前端网页的工作原理。 但是还有一个问题没有说清楚。 3.1.2小节,为什么JavaScript文件的引用要放在末尾,而CSS文件的引用要放在末尾?
这是因为,虽然浏览器对HTML文件进行了流处理,但是JavaScript文件可能会修改HTML的内容,这可能会影响DOM树的结构,进而影响渲染树的构建和后续流程,所以当browser 标签处理完后,会停止对HTML文件的解析,加载JavaScript文件并处理后再继续解析HTML文件。 一般情况下,JavaScript脚本只有在响应事件(比如点击)后才会对HTML元素进行操作,所以把JavaScript引用放在后面有利于DOM树的构建,有利于网页的早期展示。 再者,由于JavaScript脚本可能会操作DOM树,如果放在最开始,可能会因为操作的元素还未构造而导致错误。
由于CSS文件不影响DOM树的结构,所以在浏览器处理标签时会继续解析。 因为css文件会影响渲染树的构建,渲染树的构建会被挂起,直到css文件下载解析完成。 将css文件放入,可以让浏览器尽快加载css文件,有利于渲染树的构建,有利于网页的早期展示。
以3.1.2节的网页为例,解析整个网页的渐进过程如图3.15所示。 其中,粗黑线为构建过程,只反映了DOM树的构建和渲染树的构建,省略了浏览器的两个自发行为,布局处理和绘制。
图3.15 网页构建全过程
在不同的浏览器中,具体构建DOM树和渲染树的暂停点和开始点是不同的,但一般还是如图3.15所示。
本文为您讲解大型网站架构的技术细节:前端架构、前端工作原理