开始
性能优化是网站永恒的话题,里面有很多门道。我就从一个请求的生命周期去分析下,看哪些部分可以做优化。
一个请求是什么样的?
请求的基本模型是 ,比如我请求图片,会执行下面几步
- 浏览器先找缓存(disk,memory)
- dns查询
- tcp 3次握手
- 浏览器发请求包
- 服务端处理请求包
- 浏览器接收请求包
- 浏览器解析,js,html,css这些东西
- 渲染->ok 你可以看到了。
那么,我们的优化就从上面一步步来
浏览器先找缓存(disk,memory)
上一张网上图
网上讲的感觉很乱,我写下我的看法吧。让你彻底弄懂。 那我们从最简单的开始分析 打开百度,F12看请求。 上面可以看到缓存有2种,一种硬盘缓存,但是执行花了3ms,原因是磁盘的io。另一种是内存的缓存,0ms,直接从浏览器的内存缓存种拿的。硬盘缓存么可以之久保存,内存缓存么关了浏览器进程就没有了。首先,我们先看cache-controll 和expire这2个,这2个都是服务端设置,用来告诉浏览器去缓存东西的。 那他们有什么不一样? cache-controll是http1.1的,expires是http 1.0.都是设置缓存时间。同时存在的话,cache-controll会覆盖expires。但是最好还是同时都写上。 拿nginx服务端做个demo
location ~* \.(?:ico|css|js|gif|jpe?g|png)$ {
expires 30d;
add_header Pragma public;
add_header Cache-Control "public";
}
在重启下nginx即可。
接着看last-modify和etag这个东西。
什么是”Last-Modified”?
在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,格式类似这样:
Last-Modified: Fri, 12 May 2006 18:53:33 GMT
客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:如下
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
什么是etag
就是资源的hash ,一旦资源变了,hash就变了。
怎么利用last-modify和etag 缓存
服务端配置nginx的last-modify和etag,会在第一次请求的时候返回,第二次请求的时候会带上last-modify和etag。last-modify存在if-modify-since,etag存在if-not-match.当他们2个都通过验证了,就是没过期,没有修改(有没有修改看服务端的etag和浏览器传过去的etag是否一样)。就是在某个时间(last-modify判断)之后,是否修改(etag判断)。没有的话就返回304,请求体是空的。浏览器就知道,哦,我的东西没变,那我继续用了。
nginx 怎么配置last-modify和etag
注意点
还有必须注意的是,expires强缓存的静态资源,构建时候必须设置hash结尾,否则更新了,还是从缓存种读取,就不是最新的。
dns查询优化
用dns-prefetch. 当我们浏览网页时,浏览器会在加载网页时对网页中的域名进行预解析并缓存,.这样在浏览器加载网页中的链接时,就无需进行DNS解析.看淘宝。
这个域名解析会在网页加载时候自动解析掉,比如这里解析了gw.alicdn.com,下面假如有100个gw.alicdn.com的域名里的资源需要加载,他都不用走dns解析的过程了。还是很节省时间的。tcp 三次握手
3次握手是什么就不讲了。我们每次请求一个资源的时候,都要先进行3次握手。最后资源才会发送过来。tcp 3次握手的建立需要时间。假如建立1条握手线路后,其他资源也可以利用这个线路,这样就节省了其他资源的3次握手时间,从而提升效率。所以用到一种长连接的技术。上nginx 配置
这个超时时间设置很有讲究,太小tcp 上东西都没跑完,太大,socket开的太多,服务器吃不消。要看实际中的环境。发包
这个发送请求包的优化就是发的少,发的小
发的少
就是能缓存的尽量缓存,尽量别走到发送请求包这个环节。实在要发才发送。
发的小
比如get包, 我get一张图片,带了一堆该域名下的cookie过去,包就很大,耗时了。所以,可以把图片配置在另一台服务器上,主域名需要带token啊这些cookie,图片服务器就不用带cookie这些东西了。
接包
接收的请求包也是做到少和小
怎么做到小
比如vue打包的时候,配置资源压缩,webpack 来一波
js压缩
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
css 压缩
npm i extract-text-webpack-plugin --save 先安装
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module: {
rules: [..., {
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: {
loader: 'css-loader',
options: {
minimize: true
}
}
})
}]
}
html 压缩
new HtmlWebpackPlugin({
template: __dirname + '/views/index.html', // new 一个这个插件的实例,并传入相关的参数
filename: '../index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
chunksSortMode: 'dependency'
})
前端webpack构建压的差不多了,轮到后端压了。 上一波nginx的gzip压缩
gzip on;
gzip_types text/plain application/javascriptapplication/x-javascripttext/css application/xml text/javascriptapplication/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
图片的压缩
图片严格来说不叫压缩,叫采用合适的尺寸。比如我需要200x200的,我就拿200x200的,而不是拿到400x400的再显示在200x200的img标签里。 需要图片服务器做裁剪
http://img.alicdn.com/1_400-400.jpg // 400x 400的图
http://img.alicdn.com/1_200-200.jpg // 200 x 200的图
前端请求带最后面的参数就行了。
做雪碧图
就是把小图片啥的,都放在一张图上,通过背景定位去获得图片。
iconfont
阿里出的,字体文件,做图标的,很小。
图片转webp格式
webp是谷歌出的一个图片格式,比jpg还小,看下效果,可以压掉一半大小
压缩的方式可以是linux装一个包,写shell去压缩,有些cdn 平台可能就提供webp压缩的服务。某宝可以看看。cdn
这个基本都有做,国内某牛云,某度云啥的。
上面讲了把包压小的很多方法,接下来讲服务端把包搞少的方法。
怎么做少
服务端过来的包量是充足的,我们只能检测异常包,不能直接把大部分包都拦截掉,我们可以看比如某个ip,一直请求过来,就可以判断异常流量,dos啥的,就可以拦截掉。这块需要配置好策略。
上面我们把包压少和压小了。我们想看看效果呀
看看效果
去 ttps://chrome.google.com/webstore/search/pagespeed?hl=zh-CN
安装这个插件
下面还有
浏览器解析,js,html,css这些东西
渲染->ok 你可以看到了。
明天继续~~~~~~