什么是前端渲染?什么是服务端渲染?两者区别及应用场景
举个商品列表页面为例子。
前端渲染:说的应该是刚进入页面时,商品列表这些数据都不给你,不会渲染出这些数据。然后加载script时,再用ajax或者fetch之类的发起了请求另一个接口,服务端返回了商品列表的json数据给你,你在js中用模板引擎之类的技术,把这些数据拼成html字符串插入到Dom里。
服务端渲染:服务端用php的smarty模板或者java的jsp,把页面的商品列表信息渲染出来了,返回一个html给浏览器了。
区别:如果页面要求被蜘蛛抓取,前端渲染的数据就不能被抓取到,但是服务端渲染的页面就能被抓取到。如果有SEO要求,只能用服务端渲染。如果用Nodejs渲染的话,那就都没这些问题了。
部署在服务器上公式无法渲染这种情况会发生,可以这样解决:
当用户想要把登录注册原先的表单提交改成ajax异步请求,发现服务端的resrender竟然不起作用了,根本渲染不了指定的页面,而且在服务端竟然还没有报错。
真正的原因是,原来服务端重定向针对客户端的异步请求是无效的。最后在代码中改进了一下,使用域名url来跳转页面就可以把问题给解决。
最开始的页面都是服务端渲染,渲染模板属于后端要做的工作,也就是 mvc 中的 v,各种模板库飞起。
后来出来了一个 ajax 方案,体验效果很好,并且很好的解藕了前后端工作,切图崽(前端岗位的昵称)不需要学习后端模板语法,crud崽(后端昵称)不需要学习 html 语法。并且一套 restful 搞定 web Android iOS 三端。不过呢,切图崽需要用 js 操作不少 dom 结构。
切图崽不满足于写出那么多接口数据到 dom 结构的不好维护的垃圾代码,于是做了:
1 搞出来前端的 orm,一个后端实体对应前端一个 model,再配五个接口(添加,删除,修改,获取列表,获取单个实体),接口的请求操作统一为 model 实例的方法,再也不用写各种接口请求了。 形成了前端代码中的数据中心。
2 为了 避免 dom 操作代码繁杂看不懂,于是把数据和 dom 节点绑在一起,dom 操作变成了配置,清爽不少。形成了前端的数据控制层。
现在我们的前端页面可以直接无刷新增删改查了
当然不够的,我们在切换页面的时候还是会刷新,不行,我们要 spa (单页应用),整个前端我们只需要一个入口,于是前端的路由出来了。
切图崽当然还是不满意的,既然桌面 gui 软件有那么清晰一套 mvc 开发方式,前端作为 gui 开发怎么能没有,再加上之前的工作积累。数据流,数据绑定,ui 组件。方向数据流,数据双向绑定,ui 组件库 满天飞,形成了现在 react angular vue 局势。
至此,似乎已经挺完美了,但是谁知道在这期间 nodejs 出来了,它是什么,就是 JavaScript 的语法啊,我们切图崽天然就掌握一门后端语言语法了
于是我们开始回顾历史,当年我们采用了无刷新提高体验的同时,虽然也去掉了无后端的工作耦合,但是,也放弃了服务端渲染的 seo 啊,如今,我们在不要求后端的情况下,在中间加一个 node 层,就可以解决 seo 问题,也享受 spa 的体验优势…
双击打开edge浏览器后,点击右上角“”图标,在弹出的选项中点击设置。

2、打开设置界面后,点击高级设置中的“查看高级设置”选项。

3、打开高级设置后,点击打开代理设置选项。

4、打开控制面板选项,点击代理选项,然后在右侧将自动检测设置打开就可了。

小编推荐下载:
Microsoft Edge Dev浏览器():是一款采用了Chromium内核开发的Edge Dev版浏览器。Microsoft Edge Dev浏览器中在原有的基础上新增了语言识别和笔记等功能,更好的提升了用户体验感受。欢迎用户来下载体验!
编者按其实,有关网页渲染的文章很多,但是相关信息比较分散,且论述并不是很完整。如果要想对这个主题有个大致的了解,我们还得学习很多知识。因此,Web开发者Alexander Skutin 决定写一篇文章。他相信,这篇文章不仅能帮助初学者,也能对那些想要刷新知识结构的高级前端开发者有所裨益。原文地址
译文如下:
网页渲染必须在很早的阶段进行,可以早到页面布局刚刚定型。因为样式和脚本都会对网页渲染产生关键性的影响。所以专业开发者必须了解一些技巧,从而避免在实践的过程中遇到性能问题。
这篇文章不会研究浏览器内部的详细机制,而是提出一些通用的规则。毕竟,不同浏览器引擎的工作机制各不相同,这无疑会让开发者对浏览器特性的研究变得更加复杂。
浏览器是如何完成网页渲染?
首先,我们回顾一下网页渲染时,浏览器的动作:
根据来自服务器端的HTML代码形成文档对象模型(DOM)
加载并解析样式,形成CSS对象模型。
在文档对象模型和CSS对象模型之上,创建一棵由一组待生成渲染的对象组成的渲染树(在Webkit中这些对象被称为渲染器或渲染对象,而在Gecko中称之为“frame”。)渲染树反映了文档对象模型的结构,但是不包含诸如标签或含有display:none属性的不可见元素。在渲染树中,每一段文本字符串都表现为独立的渲染器。每一个渲染对象都包含与之对应的DOM对象,或者文本块,还加上计算过的样式。换言之,渲染树是一个文档对象模型的直观展示。
对渲染树上的每个元素,计算它的坐标,称之为布局。浏览器采用一种流方法,布局一个元素只需通过一次,但是表格元素需要通过多次。
最后,渲染树上的元素最终展示在浏览器里,这一过程称为“painting”。
当用户与网页交互,或者脚本程序改动修改网页时,前文提到的一些操作将会重复执行,因为网页的内在结构已经发生了改变。
重绘
当改变那些不会影响元素在网页中的位置的元素样式时,譬如background-color(背景色), border-color(边框色), visibility(可见性),浏览器只会用新的样式将元素重绘一次(这就是重绘,或者说重新构造样式)。
重排
当改变影响到文本内容或结构,或者元素位置时,重排或者说重新布局就会发生。这些改变通常由以下事件触发:
DOM操作(元素添加,删除,修改,或者元素顺序的改变);
内容变化,包括表单域内的文本改变;
CSS属性的计算或改变;
添加或删除样式表;
更改“类”的属性;
浏览器窗口的操作(缩放,滚动);
伪类激活(:悬停)。
浏览器如何优化渲染?
浏览器尽可能将重绘/重构 限制在被改变元素的区域内。比如,对于位置固定或绝对的元素,其大小改变只影响元素本身及其子元素,然而,静态定位元素的大小改变会触发后续所有元素的重流。
另一种优化技巧是,在运行几段JavaScript代码时,浏览器会缓存这些改变,在代码运行完毕后再将这些改变经一次通过加以应用。举个例子,下面这段代码只会触发一个重构和重绘:
var $body = $('body');
$bodycss('padding', '1px'); // reflow, repaint
$bodycss('color', 'red'); // repaint
$bodycss('margin', '2px'); // reflow, repaint
// only 1 reflow and repaint will actually happen然而,如前所述,改变元素的属性会触发强制性的重排。如果我们在上面的代码块中加入一行代码,用来访问元素的属性,就会发生这种现象。
var $body = $('body'); $bodycss('padding', '1px'); $bodycss('padding'); // reading a property, a forced reflow $bodycss('color', 'red'); $bodycss('margin', '2px');
其结果就是,重排发生了两次。因此,你应该把访问元素属性的操作都组织在一起,从而优化网页性能。(你可以在JSBin查到更为详细的例子)
有时,你必须触发一个强制性重排。比如,我们必须将同样的属性(比如左边距)两次赋值给同一个元素。起初,它应该设置为100px,且不带动效。接着,它必须通过过渡(transition)动效改变为50px。你现在可以在JSbin上学习这个例子,不过我会在这儿更详细地介绍它。
首先,我们创建一个带过渡效果的CSS类:has-transition { -webkit-transition: margin-left 1s ease-out; -moz-transition: margin-left 1s ease-out; -o-transition: margin-left 1s ease-out; transition: margin-left 1s ease-out; }
然后继续执行:// our element that has a "has-transition" class by default var $targetElem = $('#targetElemId');
// remove the transition class
$targetElemremoveClass('has-transition');
// change the property expecting the transition to be off, as the class is not there
// anymore
$targetElemcss('margin-left', 100);
// put the transition class back
$targetElemaddClass('has-transition');
// change the property
$targetElemcss('margin-left', 50);然而,这个执行无法奏效。所有改变都被缓存,只在代码块末尾加以执行。我们需要的是强制性的重排,我们可以通过以下更改加以实现:
// remove the transition class $(this)removeClass('has-transition');
// change the property
$(this)css('margin-left', 100);
// trigger a forced reflow, so that changes in a class/property get applied immediately
$(this)[0]offsetHeight; // an example, other properties would work, too
// put the transition class back
$(this)addClass('has-transition');
// change the property
$(this)css('margin-left', 50);现在代码如预期那样执行了。
有关性能优化的实际建议
总结现有的资料,我提出以下建议:
创建有效的HTML和CSS文件,不要忘记指明文档的编码方式。样式应该包含在标签内,脚本代码则应该加在标签末端。
尽量简化和优化CSS选择器(这种优化方式几乎被使用CSS预处理器的开发者统一忽视了)将嵌套程度保持在最低水平。以下是CSS选择器的性能排名(从最快者开始)
1 识别器:#id
2 类:class
3 标签:div
4 相邻兄弟选择器:a + i
5 父类选择器:ul> li
6 通用选择器:
7 属性选择:input[type="text"]
8 伪类和伪元素:a:hover你应该记住,浏览器在处理选择器时依照从右到左的原则,因此最右端的选择器应该是最快的:#id或则class:div {} // bad list li {} // bad list-item {} // good #list list-item {} // good 1在你的脚本代码中,尽可能减少DOM操作。缓存所有东西,包括元素属性以及对象(如果它们被重用的话)。当进行复杂的操作时,使用“孤立”元素会更好,之后可以将其加到DOM中(所谓“孤立”元素是与DOM脱离,仅保存在内存中的元素)。
2如果你使用jQuery来选择元素,请遵从jQuery选择器最佳实践方案。
3为了改变元素的样式,修改“类”的属性是奏效的方法之一。执行这一改变时,处在DOM渲染树的位置越深越好(这还有助于将逻辑与表象脱离)。
4尽量只给位置绝对或者固定的元素添加动画效果。
5在使用滚动时禁用复杂的悬停动效(比如,在中添加一个额外的不悬停类)。读者可以阅读关于这个问题的一篇文章。
想了解更多的细节问题,大家也可以看看这两篇文章:
1,How browsers work?
2,Rendering: repaint, reflow/relayout, restyle
今天我要将关注点放到网页渲染以及其重要性上。虽然已经有很多文章提到过这个主题了,但大部分信息都是零碎的片段。为了思考这件事情,我需要研究很多信息的来源。这也就是为什么我觉得我应该写这篇文章的原因。我相信这篇文章对新手会很有用,并且对想刷新和巩固他们已经了解的东西的高手也同样适用。
渲染应该从最开始当页面布局被定义时就进行优化,样式和脚本在页面渲染中扮演着非常重要的角色。专业人员知道一些技巧以避免一些性能问题。
这篇文章不会深入研究浏览器的技术细节,而是提供一些通用的原则。不同浏览器引擎工作原理不同,这就使特定浏览器的学习更加复杂。
浏览器是怎样渲染一个页面的?
我们从浏览器渲染页面的大概过程开始说起:
由从服务器接收到的 HTML 形成 DOM(文档对象模型)。
样式被加载和解析,形成 CSSOM(CSS 对象模型)。
紧接着 DOM 和 CSSOM 创建了一个渲染树,这个渲染树是一些被渲染对象的集合( Webkit 分别叫它们”renderer”和”render object”,而在Gecko 引擎中叫”frame”)。除了不可见的元素(比如 head 标签和一些有 display:none 属性的元素),渲染树映射了 DOM 的结构。在渲染树中,每一个文本字符串都被当做一个独立的 renderer。每个渲染对象都包含了与之对应的计算过样式的DOM 对象(或者一个文本块)。换句话说,渲染树描述了 DOM 的直观的表现形式。
对每个渲染元素来说,它的坐标是经过计算的,这被叫做“布局(layout)”。浏览器使用一种只需要一次处理的“流方法”来布局所有元素(tables需要多次处理)。
最后,将布局显示在浏览器窗口中,这个过程叫做“绘制(painting)”。
重绘
当在页面上修改了一些不需要改变定位的样式的时候(比如background-color,border-color,visibility),浏览器只会将新的样式重新绘制给元素(这就叫一次“重绘”或者“重新定义样式”)。
重排
当页面上的改变影响了文档内容、结构或者元素定位时,就会发生重排(或称“重新布局”)。重排通常由以下改变触发:
· DOM 操作(如元素增、删、改或者改变元素顺序)。
· 内容的改变,包括 Form 表单中文字的变化。
· 计算或改变 CSS 属性。
· 增加或删除一个样式表。
· 改变”class”属性。
· 浏览器窗口的操作(改变大小、滚动窗口)。
· 激活伪类(如:hover状态)。
浏览器如何优化渲染?
浏览器尽最大努力限制重排的过程仅覆盖已更改的元素的区域。举个例子,一个 position 为 absolue 或 fixed 的元素的大小变化只影响它自身和子孙元素,而对一个 position 为 static 的元素做同样的操作就会引起所有它后面元素的重排。
另一个优化就是当运行一段Jjavascript 代码的时候,浏览器会将一些修改缓存起来,然后当代码执行的时候,一次性的将这些修改执行。
举例来说,这段代码会触发一次重绘和一次重排:
var $body = $('body');
$bodycss('padding', '1px'); // 重排, 重绘
$bodycss('color', 'red'); // 重绘
$bodycss('margin', '2px'); // 重排, 重绘
// 实际上只有一次重排和重绘被执行。
如上面所说,访问一个元素的属性会进行一次强制重排。如果我们给上面的代码加上一行读取元素属性的代码,这个情况就会出现:
var $body = $('body');
$bodycss('padding', '1px');
$bodycss('padding'); // 这里读取了一次元素的属性,一次强制重排就会发生
$bodycss('color', 'red');
$bodycss('margin', '2px');
上面这段代码的结果就是,进行了两次重排。因此,为了提高性能,你应该讲读取元素属性的代码组织在一起(细节的例子可以看JSBin上的代码)。
有一种情况是必须触发一次强制重排的。例如:给元素改变同一个属性两次(比如margin-left),一开始设置100px,没有动画,然后通过动画的形式将值改为50px。具体可以看例子,当然,我在这里会讲更多的细节。
我们从一个有transition的CSS class开始:
has-transition {
-webkit-transition: margin-left 1s ease-out;
-moz-transition: margin-left 1s ease-out;
-o-transition: margin-left 1s ease-out;
transition: margin-left 1s ease-out;
}
然后进行实现:
//我们的元素默认有"has-transition"属性
var $targetElem = $('#targetElemId');
//删除包含transition的class
$targetElemremoveClass('has-transition');
// 当包含transition的class已经没了的时候,改变元素属性
$targetElemcss('margin-left', 100);
// 再将包含transition的class添加回来
$targetElemaddClass('has-transition');
// 改变元素属性
$targetElemcss('margin-left', 50);
上面的实现没有按照期望的运行。所有的修改都被浏览器缓存了,只在上面这段代码的最后才会执行。我们需要的是一次强制重排,我们可以通过进行以下修改来实现:
//删除包含transition的class
$(this)removeClass('has-transition');
// 改变元素属性
$(this)css('margin-left', 100);
//触发一次强制重排,从而使变化了的class或属性能够立即执行。
$(this)[0]offsetHeight; // offsetHeight仅仅是个例子,其他的属性也可以奏效。
// 再将包含transition的class添加回来
$(this)addClass('has-transition');
// 改变元素属性
$(this)css('margin-left', 50);
现在这段代码如我们所期望的运行了。
实际的优化建议
汇总了一些有用的信息,我建议以下几点:
· 创建合法的 HTML 和 CSS ,别忘了制定文件编码,Style 应该写在 head 标签中,script 标签应该加载 body 标签结束的位置。
· 试着简化和优化 CSS 选择器(这个优化点被大多数使用 CSS 预处理器的开发者忽略了)。将嵌套层数控制在最小。以下是 CSS 选择器的性能排行(从最快的开始):
ID选择器:#id
class选择器: class
标签: div
相邻的兄弟元素:a + i
父元素选择器: ul > li
通配符选择器:
伪类和伪元素: a:hover ,你应该记住浏览器处理选择器是从右向左的,这也就是为什么最右面的选择器会更快——#id或class。
div {} // bad
list li {} // bad
list-item {} // good
#list list-item {} // good
在你的脚本中,尽可能的减少 DOM 的操作。把所有东西都缓存起来,包括属性和对象(如果它可被重复使用)。进行复杂的操作的时候,最好操作一个“离线”的元素(“离线”元素的意思是与 DOM 对象分开、仅存在内存中的元素),然后将这个元素插入到 DOM 中
如果你使用 jQuery,遵循jQuery 选择器最佳实践
要改变元素的样式,修改“class”属性是最高效的方式之一。你要改变 DOM 树的层次越深,这一条就越高效(这也有助于将表现和逻辑分开)。
尽可能的只对 position 为 absolute 或 fix 的元素做动画。
当滚动时禁用一些复杂的 :hover 动画是一个很好的主意(例如,给 body 标签加一个 no-hover 的 class)关于这个主题的文章。
想了解更多的细节,可以看一下这些文章:
1 How browsers work
2 Rendering: repaint, reflow/relayout, restyle
希望这篇文章能够对你有所帮助!
原文链接: frontendbabel 翻译: 伯乐在线 - Moejser
译文链接: http://blogjobbolecom/72692/
reactjs在服务器端渲染好处:
提升性能是需要再浏览器端的性能提升还是服务端的 性能提升,是两个概念,服务端渲染会给服务端造成一定的压力,减轻客户端的压力;好处:在整个页面级别的应用会使得浏览器在解析dom完成之后马上有东西可以渲染。再者就是对seo比较友好一些;
渲染的流程主要是:
准备数据,一般从数据库或外部API获得 (一般要先 render React 一次,去触发所需的API)
数据和React结合生成HTML Markup
除了把HMTL Markup输出外, 还要把'State'输出,这要在客户端才能保留'State'
0条评论