内容简介:无优化点传送门:服务器对静态资源设置浏览器缓存信息,浏览器在有缓存的情况下直接从本地读取资源。
本文将从浏览器输入url到页面加载完成中经历的各个阶段来探讨web前端性能可以优化的点
1、浏览器输入URL并按下回车
无优化点
2、浏览器查找当前URL是否存在缓存
彻底弄懂HTTP缓存机制及原理
传送门: https://www.cnblogs.com/chenq...
优化点
服务器对静态资源设置浏览器缓存信息,浏览器在有缓存的情况下直接从本地读取资源。
3、DNS域名解析
地址栏输入的域名并不是最后资源所在的真实位置,域名只是与IP地址的一个映射。网络服务器的IP地址那么多,我们不可能去记一串串的数字,因此域名就产生了,域名解析的过程实际是将域名还原为IP地址的过程。
顺便介绍下,无优化点
4、TCP连接
DNS解析后得到了服务器的ip,接下来就是和服务器建立起连接,这通过TCP的三次握手完成。
具体为:
浏览器:你好~你在吗~我能和你聊会天吗
服务器:嗯!我在~我们聊会吧~
浏览器:好的,那我们开始咯
顺便介绍下,无优化点,顺便再说下四次告别
TCP连接后数据的传输是双向的,那么当浏览器不想说话了,就会发出中止连接的信号标志,服务器收到后会回一个确认标志给浏览器,这时浏览器就不能再向服务器传输数据了,但是还可以发送信号。为了对服务器的尊重,等服务器把话说完后才会发一个结束标志给浏览器,这时浏览器知道服务器也向自己传输完数据了,回一个确认标志过去,才真正结束这次TCP连接。
5、浏览器向服务器发送HTTP请求
完整的HTTP请求包含请求起始行、请求头部、请求主体三部分。缓存信息是存储在请求头中,在阶段二上的连接有介绍。
优化点
减少请求次数
- 合并外部请求的js、css文件
- 对icon文件进行处理。运用CSS精灵合并处理多个icon文件、运用图标字体、把小图标转为base64等
6、浏览器接收响应体
服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。响应体为服务器返回给浏览器的信息,主要由HTML,css,js,图片文件组成。
优化点
压缩响应体
- 对请求的文件进行打包(webpack),减少文件体积
7、页面渲染
页面是如何渲染的
传送门: https://www.cnblogs.com/tootw...
js的影响
js是会阻塞页面渲染的,那么解决方法有很多,可以把js放在body的底部,或者是异步加载js。
同步异步加载详解传送门: https://blog.csdn.net/qq_3498...
浅谈script标签的defer和async传送门: https://segmentfault.com/a/11...
css的影响
--------------------- 作者:JiajiaAz 来源:CSDN 原文: https://blog.csdn.net/qq_3265...
优化点
图片懒加载
概念:
访问页面时,先把img元素的背景图片src替换成一张占位图,这样只需请求一次,当图片出现在浏览器的可视区域内时,再设置图片的真实路径,显示图片。
方法:
页面中的img元素,若没有src属性,浏览器就不会发出请求去下载图片,只有通过Javascript设置了图片路径,浏览器才会发送请求。
1)懒加载先在页面中把需要延迟加载的图片统一使用一张占位图进行占位,把真正的路径存在元素“data-url”属性里。
2)页面加载完成后,通过scrollTop判断图片是否在用户的视野,如果在,则将 data-url的值取出来存放到src中。
vue/react项目页面渲染优化
在vue或者react的项目下,怎么解决页面渲染问题呢,毕竟初始的html就是一个空白页面,页面渲染全靠js的render,如果这个入口js过大,必然会导致页面白屏时间过长。
如果可以对入口的js进行代码分割,把后期才会用到的js先独立出来,等用时再引入那么就可以大大减少初始js的体积了,首屏页面渲染起来自然也快。
异步加载js的概念
<button>click to load js</button> <script> document.querySelector('button').onclick = () => { let loadJs = document.createElement('script') loadJs.src = './load.js' document.body.appendChild(loadJs) loadJs.onload = () => { alert("finish loading!") } } </script>
嗯简单来说原理就是这么实现的,设置个触发点,触发后创建个src为需要引进js路径的script Dom,然后设置下加载后的回调函数..
webpack上的实现方法
写在主入口main.js中:point_down:
document.querySelector('button').onclick = () => { require.ensure([], ()=> { // 引入异步加载的js let loadJS = require('./asyncJS') alert(loadJS.flag) }, 'asyncJS') }
webpack的配置文件:point_down:
output: { path: path.resolve(__dirname, './dist'), filename: '[name].bundle.js', publicPath: '../dist/', chunkFilename: 'chunks/[name]-[hash].js' }
webpack 在编译时,会静态地解析代码中的require.ensure(),同时将模块添加到一个分开的 chunk 当中。这个新的 chunk 会被 webpack 通过 jsonp来按需加载。
语法如下:
require.ensure(dependencies: String[], callback: function(require), chunkName: String)
依赖 - dependencies
这是一个字符串数组,通过这个参数,在所有的回调函数的代码被执行前,我们可以将所有需要用到的模块进行声明。
回调 - callback
当所有的依赖都加载完成后,webpack会执行这个回调函数。require对象的一个实现会作为一个参数传递给这个回调函数。因此,我们可以进一步 require() 依赖和其它模块提供下一步的执行。
chunk名称 - chunkName
chunkName 是提供给这个特定的 require.ensure() 的 chunk的名称。通过提供 require.ensure() 不同执行点相同的名称,我们可以保证所有的依赖都会一起放进相同的 文件束(bundle)。
打包出来的目录:point_down:
其中chunks文件夹里的内容就是从main.js中分离出来的,会在被需要时再引入到项目中。
页面加载时是这样:point_down:
点了按钮就是这样了:point_down:
顺便介绍下require.ensure() 的坑点
空数组作为参数 require.ensure([], function(require){
require('./a.js'); }); 以上代码保证了拆分点被创建,而且 a.js 被 webpack 分开打包。
依赖作为参数 require.ensure(['./a.js'], function(require) {
require('./b.js'); }); 上面代码, a.js 和 b.js 都被打包到一起,而且从主文件束中拆分出来。但只有 b.js 的内容被执行。a.js 的内容仅仅是可被使用,但并没有被输出。
想去执行 a.js,我们需要异步地引用它,如 require('./a.js'),让它的 JavaScritp 被执行。
vue/react项目中的实现方法
说了这么多,绕回来本题中心,这里以vue为例子来实现按需异步加载功能。按需加载什么呢?当然是组件啦!
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。为了简化,Vue
允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue
只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如:
Vue.component('async-example', function (resolve, reject) { setTimeout(function () { // 向 `resolve` 回调传递组件定义 resolve({ template: '<div>I am async!</div>' }) }, 1000) })
如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。你也可以调用 reject(reason) 来表示加载失败。
结合前面讲的直接上例子,基于异步组件我们可以实现vue的异步路由:point_down:
export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: resolve => { require.ensure([], () => { resolve(require('@/components/HelloWorld.vue')) }) } }, { path: '/other', name: 'other', component: resolve => { require.ensure([], () => { resolve(require('@/components/Other.vue')) }) } } ] })
当然require.ensure这种写法比较旧,就是对webpack的兼容性会好点,现在结合es6的写法会更加简洁
你也可以在工厂函数中返回一个 Promise,所以把 webpack 2 和 ES2015 语法加在一起,我们可以写成这样:
Vue.component( 'async-webpack-example', // 这个 `import` 函数会返回一个 `Promise` 对象。 () => import('./my-async-component') )
export default new Router({ routes: [ { path: '/', name: 'HelloWorld', component: () => import('@/components/HelloWorld.vue') }, { path: '/other', name: 'Other', component: () => import('@/components/Other.vue') } ] })
嗯这样就行了
顺便也提下如何处理加载状态
这里的异步组件工厂函数也可以返回一个如下格式的对象:
const AsyncComponent = () => ({ // 需要加载的组件 (应该是一个 `Promise` 对象) component: import('./MyComponent.vue'), // 异步组件加载时使用的组件 loading: LoadingComponent, // 加载失败时使用的组件 error: ErrorComponent, // 展示加载时组件的延时时间。默认值是 200 (毫秒) delay: 200, // 如果提供了超时时间且组件加载也超时了, // 则使用加载失败时使用的组件。默认值是:`Infinity` timeout: 3000 })
以上所述就是小编给大家介绍的《web前端性能优化 -- 从浏览器输入url到页面加载完成全过程解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据化运营速成手册
胡晨川 / 电子工业出版社 / 2017-4 / 55
《数据化运营速成手册》用于提升互联网公司员工的数据应用能力,即数据化运营能力。首先,从最常用的数据图表切入,帮助执行层正确地绘图,管理层正确地看图;接着,梳理运营中最基本的数据应用知识,涉及数据获取、数据清洗、数据认知、分析框架、指标体系、运营实验等内容。然后,介绍作者认为必要的统计学知识,包括假设检验、方差分析、回归分析和时间序列分解,并引入了管理科学中的规划求解方法。最后,介绍了数据分析工具的......一起来看看 《数据化运营速成手册》 这本书的介绍吧!