## 检查加载性能
一个网站加载性能如何主要看白屏时间和首屏时间。
白屏时间:指从输入网址,到页面开始显示内容的时间。
首屏时间:指从输入网址,到页面完全渲染的时间。
将以下脚本放在 </head> 前面就能获取白屏时间。
<script>
new Date() - performance.timing.navigationStart
performance.timing.domLoading - performance.timing.navigationStart
</script>
在 window.onload 事件里执行 new Date() - performance.timing.navigationStart 即可获取首屏时间。
## 检查运行性能
配合 chrome 的开发者工具,我们可以查看网站在运行时的性能。
打开网站,按 F12 选择 performance,点击左上角的灰色圆点,变成红色就代表开始记录了。这时可以模仿用户使用网站,在使用完毕后,点击 stop,然后你就能看到网站运行期间的性能报告。如果有红色的块,代表有掉帧的情况;如果是绿色,则代表 FPS 很好。
减少http请求数
常用的减少http请求数有以下几种:
1、合并图片。当图片较多时,可以合并为一张大图,从而减少http请求数。经常变化的图片可能不太合适,变化相对稳定的就可以考虑。合并大图除了能减少http 请求数外,还可以充分利用缓存来提升性能。 2、合并压缩css样式表和js脚本,他们的共同目的都是为了减少http连接数。 3、去掉不必要的请求。开发写代码或者系统升级之后残留的无效请求连接。 4、充分利用缓存。这里说的缓存是客户端侧缓存或者说浏览器缓存。Expires头信息是客户端侧缓存的重要依据,格式类似于Expires:sun ,20 Dec 2017 23:00:00 GMT。 如果当前时间小于Expires指定的时间,浏览器就会从缓存中直接获取相关的数据信息或html文件,如果当前时间大于Expires指定的时间,浏览器会向服务器发送请求来获取相关数据信息。 5、Connection: keep-alive 可减少握手挥手次数
样式表和JS文件的优化
1、css文件放在head中,先外链,后本页 2、js文件放在body底部,先外连,后本页 3、处理页面、处理页面布局的js文件放在head中,如babel-polyfill.js文件、flexible.js文件 4、body中尽量不写style标签和script标签 5、异步script标签 defer:异步加载,在html解析完成后执行。defer的实际效果与将代码放在body底部类似 async:异步加载,加载完成后立即执行
减少重绘重排
降低 CSS 选择器的复杂性
浏览器读取选择器,遵循的原则是从选择器的右边到左边读取
#block .text p {
color: red;
}
查找所有 P 元素。
查找结果1中的元素是否有类名为 text 的父元素
查找结果2中的元素是否有 id 为 block 的父元素
选择器越短越好。
尽量使用高优先级的选择器,例如 ID 和类选择器。
避免使用通配符 *
图片优化
1、图片的延迟加载,也叫做赖加载。 2、精灵图 3、当图片过小时(小于12k)可以把它转成base64(代码图片,转成base64的好处:减少http请求)
使用CDN
CDN即内容分发网络,可以使用户就近取得所需内容,解决网络拥挤的状况,提高用户访问网站的响应速度。
懒加载
服务端渲染
客户端渲染: 获取 HTML 文件,根据需要下载 JavaScript 文件,运行文件,生成 DOM,再渲染。
服务端渲染:服务端返回 HTML 文件,客户端只需解析 HTML。
优点:首屏渲染快,SEO 好。 缺点:配置麻烦,增加了服务器的计算压力。
客户端渲染过程 访问客户端渲染的网站。 服务器返回一个包含了引入资源语句和 <di id="app"的 HTML 文件。 客户端通过 HTTP 向服务器请求资源,当必要的资源都加载完毕后,执行 new Vue() 开始实例化并渲染页面。 服务端渲染过程 访问服务端渲染的网站。 服务器会查看当前路由组件需要哪些资源文件,然后将这些文件的内容填充到 HTML 文件。如果有 ajax 请求,就会执行它进行数据预取并填充到 HTML 文件里,最后返回这个 HTML 页面。 当客户端接收到这个 HTML 页面时,可以马上就开始渲染页面。与此同时,页面也会加载资源,当必要的资源都加载完毕后,开始执行 new Vue() 开始实例化并接管页面。 从上述两个过程中可以看出,区别就在于第二步。客户端渲染的网站会直接返回 HTML 文件,而服务端渲染的网站则会渲染完页面再返回这个 HTML 文件。
这样做的好处是什么?是更快的内容到达时间 (time-to-content)。
假设你的网站需要加载完 abcd 四个文件才能渲染完毕。并且每个文件大小为 1 M。
这样一算:客户端渲染的网站需要加载 4 个文件和 HTML 文件才能完成首页渲染,总计大小为 4M(忽略 HTML 文件大小)。而服务端渲染的网站只需要加载一个渲染完毕的 HTML 文件就能完成首页渲染,总计大小为已经渲染完毕的 HTML 文件(这种文件不会太大,一般为几百K)。这就是服务端渲染更快的原因。
webpack
- 关闭productionSourceMap
module.exports = {
productionSourceMap: false
}
- 开启Gzip压缩
安装插件compression-webpack-plugin,打开代码压缩,npm install --save-dev compression-webpack-plugin,现在的vue.config.js代码如下,但是,需要注意的是,服务器上nginx也必须开启gzip才能生效
const isProduction = process.env.NODE_ENV !== 'development';
const CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = {
productionSourceMap: false,
configureWebpack: config => {
if (isProduction) {
const productionGzipExtensions = ['html', 'js', 'css']
config.plugins.push(
new CompressionWebpackPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' + productionGzipExtensions.join('|') + ')$'
),
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false
})
)
}
}
}
# 开启gzip
gzip on;
# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 2;
# 进行压缩的文件类型。javascript有多种形式,后面的图片压缩不需要的可以自行删除
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置压缩所需要的缓冲区大小
gzip_buffers 4 16k;
- 开启CDN加速(建议选配,CDN虽然速度快,但没有本地打包稳定)
const isProduction = process.env.NODE_ENV !== 'development';
const devNeedCdn = false
const cdn = {
externals: {
vue: 'Vue',
vuex: 'Vuex',
'vue-router': 'VueRouter',
'marked': 'marked',
'highlight.js': 'hljs',
'nprogress': 'NProgress',
'axios': 'axios'
},
css: [
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css'
],
js: [
'https://cdn.bootcss.com/vue/2.6.10/vue.min.js',
'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js',
'https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js',
'https://cdn.bootcss.com/marked/0.8.0/marked.min.js',
'https://cdn.bootcss.com/highlight.js/9.18.1/highlight.min.js',
'https://cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js',
'https://cdn.bootcss.com/axios/0.19.2/axios.min.js'
]
}
module.exports = {
chainWebpack: config => {
config.plugin('html').tap(args => {
if (isProduction || devNeedCdn) args[0].cdn = cdn
return args
})
},
configureWebpack: config => {
if (isProduction || devNeedCdn) config.externals = cdn.externals
}
}
接下来,在index.html中引入使用了CDN的链接
<!DOCTYPE html>
<html lang="en" style="width: 100%;height: 100%;">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 使用CDN的CSS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn &&
htmlWebpackPlugin.options.cdn.css) { %>
<link
href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"
rel="stylesheet"
/>
<% } %>
<!-- 使用CDN的CSS文件 -->
<title>CoolDream</title>
</head>
<body style="width: 100%;height: 100%;">
<noscript>
<strong>We're sorry but blog doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<!-- 使用CDN的JS文件 -->
<% for (var i in htmlWebpackPlugin.options.cdn &&
htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
<!-- 使用CDN的JS文件 -->
</body>
</html>
- 代码压缩
安装插件npm i -D uglifyjs-webpack-plugin
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
config.plugins.push(
new UglifyJsPlugin({
uglifyOptions: {
compress: {
drop_debugger: true,
drop_console: true,
pure_funcs: ['console.log']
}
},
sourceMap: false,
parallel: true
})
)
- 公共代码抽离
SplitChunks插件是什么呢,简单的来说就是Webpack中一个提取或分离代码的插件,主要作用是提取公共代码,防止代码被重复打包,拆分过大的js文件,合并零散的js文件。
config.optimization = {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'all',
test: /node_modules/,
name: 'vendor',
minChunks: 1,
maxInitialRequests: 5,
minSize: 0,
priority: 100
},
common: {
chunks: 'all',
test: /[\\/]src[\\/]js[\\/]/,
name: 'common',
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 60
},
styles: {
name: 'styles',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true
},
runtimeChunk: {
name: 'manifest'
}
}
}
}
- 图片压缩()
安装插件npm install image-webpack-loader --save-dev
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({ bypassOnDebug: true })
.end()
|