网站使用的是vue框架开发的spa模式的PC端网站。网站的性能优化主要集中在首页。
图片的优化
图片的优化,使用了VueLazyload插件(www.npmjs.com/package/vue…
将这些代码写在入口文件中
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload, {
filter: {
webp (listener, options) {
if (!options.supportWebp) return // 是否支持webp格式的图片
const isCDN = /youCDN/
if (isCDN.test(listener.src)) { // 图片地址符合要求的,将后缀名修改成webp
const fileName = listener.src.substring(0, listener.src.lastIndexOf('.'));
listener.src = `${fileName}.webp`;
}
}
}
});
在页面中使用
<template>
<div>
<!--原先我们使用图片 <img src="youImageSrc" /> -->
<img v-lazy="youImageSrc" />
</div>
</template>
还有一种情况,图片是用在css的background-image上的,这种情况下,我们需要自行先判断一下浏览器是否支持webp格式的图片。
// 第一种方式,使用canvas
const isSupportWebp = function () {
try {
return document.createElement('canvas').toDataURL('image/webp', 0.5).indexOf('data:image/webp') === 0;
} catch(err) {
return false;
}
}
// 第二种方式 试着加载一张webp格式的图片
var isWebP = false;
var img = new Image();
img.onload = function(){
isWebP = !!(img.height>0 && img.width>0);
checkPic(isWebP);
};
img.onerror = function(){
isWebP = false;
checkPic(isWebP);
};
img.src = './c.webp';
var checkPic = function(isWebP){
$("#pics img").each(function(i,v){
var src = isWebP?$(v).attr('webppic-src'):$(v).attr('pic-src');
$(v).attr('src',src);
})
webp格式的图片目前主流浏览器基本都已支持。IE和Safari目前还未支持,IE支持JPEG XR格式图片,Safari支持JPEG 2000格式图片,这2种也是最新的图片格式,和webp可以启到一样的作用。在图片优化时,我们并没有启用JPEG XR和JPEG 2000这2种最新的图片格式,对我们来说,这2部分的用户占有量不是很高。所以我们在使用webp格式图片时,需要判断浏览器是否支持,如果不支持,则保持使用原先的jpg或者png格式的图片。
同一张png格式的图片转换成相同质量的jpg图片和webp图片,相对jpg图片,webp图片的大小可以小40%左右。
(注意:如果使用一张jpg图片去转成相同质量下的webp图片,图片不会变小,反而会变成原先的2-3倍。)
转换图片格式这事如果要前端来转的话,可以使用webpack的插件或者工具,我在使用WebPonize软件时转出来的图片是糊的,没法使用,最后选择了使用imagemin-webpack-plugin。个人认为这事交给后端来做更加的合适,可以找网上的一些插件,也有很多云服务器支持这样的服务,需要收取一定的费用。
main.js的缩小
-
利用less的常量,提取颜色值等。
-
Iconfont
之前我们在使用图标时,是用了svg,最后利用插件打包成了雪碧图,现在全部换成iconfont之后一下子小了很多。
-
base64图片
vue的脚手架默认配置是4kb以下的图片会打成base64,打入文件中,将这一默认配置去除。
const imagesRule = config.module.rule('images'); imagesRule.uses.clear(); imagesRule // you can set whatever you want or remove this line completely .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/) .use('file-loader') .loader('file-loader') .tap(options => { return { ...options, limit: -1 // no limit }; }) .end();
插件的优化
在开发中,我们使用插件的时候往往不在注意,是否需要全部引入这个插件,一般情况下,我们不会使用到插件的所有功能。如果全部引入,会影响我们最终包的大小。
首先我们通过webpack-bundle-analyzer这个webpack插件在页面上查看一下各个模块的大小情况,来分析哪些模块需要去缩小。
这里我来举一个例子,我们在项目中使用了lottie-web来实现动画效果。如果我们只需要这个插件支持svg格式,那么我们只需要引入它的轻量级包lottie_light,相对于lottie-web小了差不多4分之1。
多域名+http2.0
多域名+http2.0的使用,我们必须先要了解一下http以及浏览器的原理。简单来说,每个浏览器以及不同的http协议都有自己的tcp连接数的限制,像Chrome是6个,http1.1最多建立6个tcp连接,http1.1中一个tcp连接只能同时处理一个http请求,所以存在队头阻塞问题,就是一下子请求太多,来不及处理,都在入口处等着。
我们原先使用的是http1.1,只有一个域名,然而首页的请求有200多个(是因为错误使用路由懒加载,正确使用之后剩80多个请求),导致了首页的请求都阻塞了,增加一个域名等于增加了一倍的tcp连接。后来,我们又将http1.1升级成了http2.0,利用了http2.0的多路复用特性,有效解决了队头阻塞问题。
路由懒加载
路由懒加载的使用,可以参考官方。在使用vue-cli打包时,这个脚手架会默认在我们的js资源中加上pre-fetch标签来使浏览器在空闲的时候提前下载好js,但是像我们的网站页面太多,不太使用这一默认设置,所以我们在配置的时候想把它去除。于是,按照官方文档,我们在vue.config.js配置文件中,写道:
// 官方文档中就是这么写的,其实并未生效
chainWebpack: config => {
// 移除 prefetch插件
config.plugins.delete('prefetch');
}
其实正确的写法,应该是这样的:
// 正确的写法
chainWebpack: config => {
// 移除 prefetch插件,main是我们的入口名称
config.plugins.delete('prefetch-main');
}
一下子,将首页的请求,从200多个减少成了80多个。
dns-prefetch
将使用到的dns提前解析.只需要在html头部添加
<link rel="dns-prefetch" href="//ecpm.tanx.com" />