白屏优化
-
路由懒加载
{
path: '/login',
component: () => import('@aicc/components/login/index')
}
-
使用v-if代替v-show
好处是可以减少首屏渲染dom数量(除非是一些会频繁变换显隐的元素,这样的元素应该用v-show)
-
不直接显示的组件做懒加载
常见的场景是:el-tabs组件内从第二个tab开始渲染的组件都可以懒加载,目的是减少根据此路由完成首屏渲染时需加载的代码量
比如vue项目内的
import pageComponent from './pageComponent'
export default {
name: 'Recharge',
components: {
pageComponent,
},
...
改成
export default {
name: 'Recharge',
components: {
pageComponent: () => import('./pageComponent'),
},
...
-
使用resolutions统一依赖版本
假设主项目依赖包A@1.1.0,主项目依赖的包B依赖A@1.1.1,此时yarn会在node_modules根路径和node_modules/B/node_modules分别安装A的两个版本,并都会打包到最终bundle。此时可以在package.json中使用resolutions强行统一A的版本
"resolutions": {
"a": "1.1.1"
}
-
组件库按需加载
包括项目使用的第三方组件库、公司内部组件库、项目components目录内的组件
这些都可以使用babel-plugin-import插件实现,babel.config.js如下:
const babelPluginImportForComponents = [
'import',
{
libraryName: '@/components',
libraryDirectory: '',
camel2DashComponentName: false,
customName: name => {
return `@/components/${name}`
}
}
]
module.exports = {
...
'plugins': [
...
babelPluginImportForComponents
]
}
-
资源预加载
场景比如:使用element的项目打包出来的css内会通过@font-face去加载字体,也就是说字体会等css加载完并开始解析了再去加载,这样我们可以预加载字体,无需等待css
这个一般是处理字体资源:<link rel="preload" href="/ai-engine/static/fonts/element-icons.woff" as="font" type="font/woff" crossorigin="anonymous">或者其他任何首屏必须加载,却要等待其他资源先加载的资源
-
defer
一些对渲染影响不大的js资源可以在script上加defer,这样这些js不会阻塞渲染也不影响加载,比如iconfont的彩色字体js文件
-
CDN
部分静态资源可以放CDN上,好处是请求这些资源时不会带本网站的cookie,减少流量。一些优秀的CDN也会加快资源加载速度,比如七牛、ali
-
减少css加载
原因是css的加载会阻塞dom的渲染,因为浏览器去渲染dom会先构建两棵树:dom树和css规则树,然后再做渲染。
所以应该只加载首屏需要的css,并且最好先通过<style>内置到index.html内
-
gzip
打包的时候就打成gzip包,不需要服务器再去做压缩
-
静态文件缓存
目前前端资源一般通过hash区分版本,如果hash没变,可以一直缓存,在服务端设置相应的缓存策略
-
服务端渲染/预渲染
这个可以说是终极杀器,因为访问url直接就请求下来一段html和样式,可以直接渲染出来,其他的资源非阻塞式加载就好了。可以说使用此方案会减少很多优化工作量
首屏优化
其实上面的方案也都是首屏优化方案,这里重在强调白屏结束后的处理
-
骨架屏/loading动效
假如首屏上有些内容要通过接口请求数据再渲染,可以先渲染出骨架屏或者loading效果,让用户觉得页面是在加载的
-
后端数据层缓存
一些频繁查询的数据可以设置缓存,比如淘宝首页商品列表
-
图片懒加载(可以配合骨架屏方案)
-
图片压缩
tinyPng
-
尽量使用css代替图片。项目初期一些特效可能通过图片实现,后期有时间可以通过代码实现,因为图片的体积肯定会远大于实现代码的体积
如何判断优化效果
本地可以使用lighthouse(chrome浏览器自带的分析器)分析页面渲染情况
远程监控用户白屏时间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>白屏</title>
<script type="text/javascript">
// 不兼容performance.timing 的浏览器,如IE8
window.pageStartTime = Date.now();
</script>
<!-- 页面 CSS 资源 -->
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="page.css">
<script type="text/javascript">
// 白屏时间�结束点
window.firstPaint = Date.now();
</script>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
兼容Performance API时
白屏时间 = firstPaint - performance.timing.navigationStart
不兼容Performance API时
白屏时间 = firstPaint - pageStartTime
远程监控用户首屏时间
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首屏</title>
<script type="text/javascript">
window.pageStartTime = Date.now();
</script>
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="page.css">
</head>
<body>
<!-- 首屏可见元素1 -->
<div></div>
<!-- 首屏可见元素2 -->
<div></div>
<script type="text/javascript">
window.firstScreen = Date.now();
</script>
<!-- 首屏不可见元素3 -->
<div></div>
<!-- 首屏不可见元素4 -->
<div></div>
</body>
</html>
首屏时间 = firstScreen - performance.timing.navigationStart
白屏优化
路由懒加载
使用v-if代替v-show
好处是可以减少首屏渲染dom数量(除非是一些会频繁变换显隐的元素,这样的元素应该用v-show)
不直接显示的组件做懒加载
常见的场景是:
el-tabs组件内从第二个tab开始渲染的组件都可以懒加载,目的是减少根据此路由完成首屏渲染时需加载的代码量比如
vue项目内的改成
使用
resolutions统一依赖版本假设主项目依赖包
A@1.1.0,主项目依赖的包B依赖A@1.1.1,此时yarn会在node_modules根路径和node_modules/B/node_modules分别安装A的两个版本,并都会打包到最终bundle。此时可以在package.json中使用resolutions强行统一A的版本组件库按需加载
包括项目使用的第三方组件库、公司内部组件库、项目
components目录内的组件这些都可以使用babel-plugin-import插件实现,
babel.config.js如下:资源预加载
场景比如:使用
element的项目打包出来的css内会通过@font-face去加载字体,也就是说字体会等css加载完并开始解析了再去加载,这样我们可以预加载字体,无需等待css这个一般是处理字体资源:
<link rel="preload" href="/ai-engine/static/fonts/element-icons.woff" as="font" type="font/woff" crossorigin="anonymous">或者其他任何首屏必须加载,却要等待其他资源先加载的资源defer
一些对渲染影响不大的js资源可以在
script上加defer,这样这些js不会阻塞渲染也不影响加载,比如iconfont的彩色字体js文件CDN
部分静态资源可以放
CDN上,好处是请求这些资源时不会带本网站的cookie,减少流量。一些优秀的CDN也会加快资源加载速度,比如七牛、ali减少css加载
原因是css的加载会阻塞dom的渲染,因为浏览器去渲染dom会先构建两棵树:dom树和css规则树,然后再做渲染。
所以应该只加载首屏需要的css,并且最好先通过
<style>内置到index.html内gzip
打包的时候就打成
gzip包,不需要服务器再去做压缩静态文件缓存
目前前端资源一般通过
hash区分版本,如果hash没变,可以一直缓存,在服务端设置相应的缓存策略服务端渲染/预渲染
这个可以说是终极杀器,因为访问url直接就请求下来一段html和样式,可以直接渲染出来,其他的资源非阻塞式加载就好了。可以说使用此方案会减少很多优化工作量
首屏优化
其实上面的方案也都是首屏优化方案,这里重在强调白屏结束后的处理
骨架屏/loading动效
假如首屏上有些内容要通过接口请求数据再渲染,可以先渲染出骨架屏或者loading效果,让用户觉得页面是在加载的
后端数据层缓存
一些频繁查询的数据可以设置缓存,比如淘宝首页商品列表
图片懒加载(可以配合骨架屏方案)
图片压缩
tinyPng
尽量使用css代替图片。项目初期一些特效可能通过图片实现,后期有时间可以通过代码实现,因为图片的体积肯定会远大于实现代码的体积
如何判断优化效果
本地可以使用lighthouse(chrome浏览器自带的分析器)分析页面渲染情况
远程监控用户白屏时间
兼容Performance API时
白屏时间 = firstPaint - performance.timing.navigationStart不兼容Performance API时
白屏时间 = firstPaint - pageStartTime远程监控用户首屏时间
首屏时间 = firstScreen - performance.timing.navigationStart统计首屏内图片完成加载的时间
自定义模块内容计算法
只考虑首屏的主要模块,而不是严格意义首屏线以上的所有内容。这种更简单易行,按第一种方法还需要确定到具体元素,相对复杂