网站性能优化实践

216 阅读3分钟

网站使用的是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的缩小

  1. 利用less的常量,提取颜色值等。

  2. Iconfont

    之前我们在使用图标时,是用了svg,最后利用插件打包成了雪碧图,现在全部换成iconfont之后一下子小了很多。

  3. 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" />