如何显著的提高前端加载性能

本文代码基于vue项目,代码源自vue不一样环境打包命令配置,但优化方案适用于全部现代化前端框架javascript

关于前端性能优化是个历史很是很是悠久的话题,百度搜一下前端性能优化,基本上都是在教咱们如何提高执行性能,好比说尽可能的减小DOM操做,js文件放在html的最底部,第三方文件使用CDN方式加载。但在如今Vue、react等现代化框架大行其道的时代下,咱们第三方库基本上都是npm install XXXX安装到项目内了,这就使得咱们的项目愈来愈大,哪怕使用Webpack压缩打包后,也会有十几兆的大小(实际大小根据来讲,不作优化的状况下,项目越大,使用的第三方库越多,打包后的项目也越大),但咱们服务器的带宽却不必定很是大,尤为是像Vue、React这样的单页面应用(本文讨论的以页面应用为主,它们虽然能够配置多页面,但做者对多页面不熟悉,本文不作讨论),若是咱们的第三方库在都挂载到全局,就会形成主包文件很是大,首页加载超级慢。css

因此咱们本文就开始尝试将项目体积减少,提高首屏加载速度。html

一,使用CDN加载第三方库

在现代化框架中咱们使用第三方UI基本都是使用npm install的方式,在vue中若是一个UI库中的组件咱们大量使用,咱们会将其在main.js中全局引用,这样使用是没有问题的,但当项目进行打包的时候,UI库也会被打包进项目,使得项目包变得很是大,以iView来讲,当咱们不使用iView的时候咱们的项目包打包出来是这个样子的。前端

我项目是在本地部的因此加载速度可参考性不大,但咱们应该能够理解你的资源越大加载速度就越慢。vue

而后咱们安装使用iView以后看一下有什么变化;java

首先能够看到打包的时候先给咱们报了警告,告诉咱们文件过大可能影响性能。而后打包后的文件体积明显变得更大了,加载速度也更慢了,若是你本身作实验,你会发现打包速度也变慢了,并且这只是咱们在全局只使用了iView,实际开发中咱们可能还会使用moment、axios、jscookies、echarts等各类各样的可能须要在全局使用的第三方工具,那么项目愈来愈大,不作其余处理的状况下,性能只会愈来愈差,很明显的感觉就是首页渲染超级慢。react

因此咱们开始进行优化,减少咱们项目体积,提升资源加载速度。webpack

1-一、经过CDN引入iView

首先因为咱们的项目是单页面应用,因此咱们在项目的html文件内经过CDN引入iView-UI库。iView的CDN传送门ios

<!DOCTYPE html>
<html lang="en">
  <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">
    <!-- S 引入iView样式-->
    <link rel="stylesheet" href="//unpkg.com/iview/dist/styles/iview.css">
    <!-- E 引入iView样式-->
    <title>myproject</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but myproject doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- S 引入VueJs和iView脚本-->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="//unpkg.com/iview/dist/iview.min.js"></script>
    <!-- E 引入VueJs和iView脚本-->
  </body>
</html>
复制代码

看到这里,可能你会想,不是引入iview吗,为何把vue也用cdn的方式引入了?这个答案呢,你猜下,而后对比下去掉vue和加上vue有什么区别,而后再思考下,我想你能够猜到答案。git

1-二、配置CDN使用

在项目根目录下新建一个vue.config.js文件,这个文件vue给咱们提供的,咱们能够在文件内定义一些webpack配置,代码以下vue.config.js配置指南

module.exports = {
  configureWebpack: {
    externals: {
      iview: 'iview', // '包名':'全局变量' 
   },
  }
}
复制代码

若是是vue-cli 2.X建立的项目,能够在/build/webpack.base.conf.js文件内这么写入;webpackConfig对象是vue帮你已经定义好了,你只须要加入externals配置就行,千万别去又建个webpackConfig对象。

const webpackConfig = {
  externals: {
      iview: 'iview', // '包名':'全局变量' 
   },
}
复制代码

若是是其余项目,而且使用了webpack,那么请找到项目的webpack配置文件,而后在配置对象内加入如下代码。webpack关于externals配置项的文档

externals: {
  iview: 'iview', // '包名':'全局变量' 
}
复制代码

1-三、使用

main.js内这么引用

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import iView from 'iview';

Vue.config.productionTip = false
Vue.use(iView);

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')
复制代码

而后你就能够在项目中正常使用,使用方式和npm install安装的没有任何区别,请放心使用。

1-四、对比

而后咱们继续进行打个包,而后部署,对比npm install安装在项目内有什么区别;

而后咱们发现,咦!!!打包后的文件确实变小了,可是怎么加载速度还变慢了,尤为是iview相关的,加载速度超级慢啊,iview.min.js竟然花费了1.14秒才加载完成。

这里就直接说答案了,因为iview的CDN是unpkg,若是在大陆访问的话,访问的节点是香港,因此呢,咱们更换下iview的cdn地址,实际开发中各家公司应该是有本身的CDN的,因此能够直接把第三方资源放在自家CDN上,我这里换成了jsDelivr,而后对比一下;

能够明显看到这加载速度直接快了一半还多啊。

1-5 总结

因此咱们就能够在实际项目开发过程直接使用这种方式来使用第三方资源,速度提高是能够用眼睛看到的,唰!唰!唰!另外咱们在1-1中已经经过CDN的方式引用vue了,那咱们可不能够在项目内npm uninstall vue移除vue,而后采用CDN方式使用呢,试一下呗!!

二,使用CDN加载项目静态资源

咱们进行项目开发的时候不可避免地会使用到图片,字体等文件,当咱们进行项目打包的时候,或者被打包成base64或者打包进静态资源目录,不可避免都在项目内,最后都上传到服务器上了,这样图片加载的时候,确定会影响其余资源加载速度,形成首页渲染速度变慢;固然咱们也能够把图片资源上传到CDN上,而后复制下地址在项目中使用,可是这样咱们每使用一张就须要上传一次,严重影响开发效率;

可是咱们若是能够在项目开发的时候从项目内加载图片,而后打包的时候从CDN上来加载图片,这样不就能够解决问题了。

1-1 首先图片打包进项目

强烈建议在服务器做此操做对比,我这里是在本地用PHPStudy模拟起的服务,资源因为在本地,因此会发现从CDN加载资源没有从本地快;在实际开发中,因为服务器性能带宽等各类因素影响,因此从CDN加载资源会很是明显的带来性能提高

咱们先来看一下咱们不使用CDN,把图片放在项目内,会有多大的影响。我在项目内引入20张图片,每一个页面加载几张,先来截个图看看。

首先是我这几个图片就比较大,因此打的包也就很大,实际项目中通常不会有一个图片八九兆的状况,但若是项目中用到的图片资源多,那么包也会比较大。

1-2 图片经过CDN方式加载

咱们但愿开发环境用本地图片,生产环境用CDN资源,那么咱们这里就须要用到Webpack的一个loader,url-loader,这是webpack推荐的一个loader,在vue、react等各类框架中也是使用频率很是高的一个loader,若是不许备很深刻研究的话,看Webpack提供的这个文档就够了。

  1. 首先在vue.config.js中加入以下配置
module.exports = {
  configureWebpack: {
    externals: {
      iview: 'iview', // '包名':'全局变量' 
    },
  },
  // 这里是新加的
  chainWebpack: config => {
    config.module
      .rule('images')
      .use('url-loader')
        .options({
          limit: 10240,
          publicPath: process.env.NODE_ENV === 'development' ? '' : 'http://static.jindll.com/img',
          outputPath: 'img',
          name: '[name].[ext]',
        })
        .end()
  }
}
复制代码
  1. 而后你就能够在项目正常使用你的图片了,不管是../的相对路径仍是@/XXX均可以,开发环境都是用的是本地的图片资源,其余环境(测试环境或者生产环境或者预发布环境等等),图片路径会被替换成publicPath所设置的路径加上你的图片名字,以我上面的配置来讲,假如我在项目中使用了@/assets/img/logo.png图片,那么打包以后路径就会是http://static.jindll.com/img/logo.png还有一个须要说,你打包以后图片不会自动就上传到CDN上,打包以后,在生成的dist文件夹下,会有一个img文件夹,这个文件夹内的图片就是你项目所使用的图片,而后将这个文件夹内的图片自行上传到CDN上就行,可是CDN的图片路径前缀必定要和publicPath设置的路径保持一致;为何打包以后图片会被放进img文件夹,这个是由于咱们经过outputPath属性设置的输出路径,若是你想改为其余的名称都随意;

  2. 对之上的配置作下解释,我以前有说过咱们须要使用url-loader可是我并无npm install安装url-loader,这是由于vue-cli内部使用了url-loader,因此咱们能够经过vue-cli提供的chainWebpack属性对内部的webpack配置作修改;vue-cli对chainWebpack这个配置解释的并很少,但告诉了咱们chainWebpack接收一个基于 webpack-chain 的 ChainableConfig实例,因此更多的使用或者api咱们其实能够查看webpack-chain官方文档

    根据webpack-chain文档rule方法表示的是这个规则的名字,也就是任意的字符串,Vue-Cli内部对其定义的名字是images(仅针对url-loader),咱们这里是修改内部配置,因此用这个名字来取对应的配置来作修改;use方法表示要使用的loader名字(若是使用plugin就是plugin名字),limit表示只有文件大于这个值的时候才会被打包进img文件夹,小于这个值文件将被处理成base64,name表示的是文件名字,它的值我设置的是[name].[ext],表示的是打包的文件名就用原名称,后缀也不改变,这个是占位符,其余的占位符能够看file-loader文档url-loader和file-loader做用相同,配置url-loader比file-loader多了limit配置,file-loader至关于打包的时候将文件进行移动,url-loader是将文件处理成base64,其余基本没有区别了

  3. 补充内容,在使用使用CDN加载第三方库中,我使用了configureWebpack配置,在使用CDN加载项目静态资源中我使用了chainWebpack配置,在Vue项目中,若是咱们想要对webpack作修改,那么这两个配置就是很重要的配置,它们均可以帮助咱们完成webpack修改;那这两个有什么区别呢?

    • configureWebpack能够接受一个对象,在这个对象内部咱们能够写原生的webpack配置;简单说它就是加新的配置,但不能改已有的配置,但使用方便;
    • chainWebpack是一个函数,咱们能够在这个函数中对Vue-Cli内部的webpack配置作修改;简单说它就是改已有的配置,也能够加新的配置,但须要看下webpack-chain文档才能够更好的使用

3、减小在全局挂载内容

这部份内容以后会在其余文章作更多描述

再经过CDN加载第三方库和静态资源经过CDN加载以后,咱们项目体积已经能够大幅度的减少了,但在实际项目开发中,因为业务须要咱们本身会写很是多的工具函数,好比后端返回的是state码,而不是翻译好的文字,咱们须要封装一些方法来对这些状态码作处理,但这些工具函数的使用频率可能并非很是高,有可能仅在项目的这个功能模块内用,其余功能模块并不使用;或者身份证校验等这些相似的方法,他们的使用频率可能也就五六各地方会用,但在我所遇到的项目中,很是多的开发人员是单独创建一个文件,文件内封装这些方法,最后将这个文件挂载到全局使用;这样会出现的问题就是,当项目打包的时候,这些方法会被打进主包内(vue项目是app.hash.js),这会增大主包的体积,无形中就形成了首屏渲染速度变慢;

因此对于这种场景,建议就是若是某几个方法仅在某一个功能模块中使用,那就给这个功能模块单独建个tool.js,而后在须要的地方引入具体的方法就好。

减小在全局挂载内容这部分暂时没有代码,这部分的内容以后也会在其余文章重点描述。

4、其余

。。。。。。。。。。。。。。。。。。。想到再更。。。。。。。。。。。。。。。。。

相关文章
相关标签/搜索