前言

前端性能优化是一个陈词滥调的话题,对于性能优化的技术文档和书籍都特地多。如果大家想深刻学习前端性能优化相干内容,有以下举荐

  • 雅虎军规35条
  • 某东上搜“前端性能优化”,书籍也特地多。
    然而前端性能优化做的所有工作,都和一个灵魂拷问有极大的关系:
    在浏览器输出url后,产生了什么?
  • 首先url是一个域名,首先它要被解析成ip地址。如果你的设施之前拜访过该url,那么本地可能会缓存ip地址。如果没有缓存过,那么就向dns服务器进行解析。
  • 依据 IP 地址和默认端口建设TCP连贯,三次握手。
  • 浏览器收回HTTP申请;
  • 服务器对申请作出响应;此时兴许会有一些304之类的返回后果。会波及到http缓存机制。
  • 开释TCP连贯;
  • 浏览器将该html文本并显示内容。

所以咱们能够从这个过程里去思考,服务器如何把文件尽快发送到客户浏览器。

  • 第一点,就是文件尽可能要小,文件尽可能少,发送起来会更快
  • 第二点,就是发送过程,在肯定条件下,缩小文件或申请的个数。
    文件也并不是越少越好,假如文件内容少到极致,内容全副合并到一个文件,那么这个文件会是十分微小的,发送起来也会十分慢。如果文件个数太多,那么浏览器也会限度并发数量,在同一个域名下,浏览器的并发数量是6个。这样,尽管每个申请发送的文件很少,然而建设申请的过程也是耗时间的。很多申请都被阻塞了。
    以上是针对第一次拜访网站时可用的计划,然而如果一个网站常常被反复拜访,还有以下办法
  • 第三点,缓存机制 就是之前用到过的文件和内容,如果没有生效,就能够重复使用,不须要再从服务器拿。

以上是我大略能想到的一些思路。如果有不精确的中央,或者有其余好的思路,心愿大家留言帮我补充。

上面咱们进入正题,说一下我在开发我的项目时遇到的一个问题,以及解决思路

开发过程遇到的一个理论问题

在vue我的项目打包后,会在我的项目的根目录下生成一个dist(你也能够扭转该名称)文件夹。一个单页面利用的dist文件夹通常蕴含一个index.html 和 一个js文件夹 和一些其余资源文件。

而后咱们把dist文件夹公布到服务器上,在浏览器下来拜访咱们的我的项目,刚开始可能会特地慢。关上chrome调试工具,查看一下资源加载状况。

太惊人了,一个要害的js文件,在nginx服务器上曾经做了压缩解决,从800k压缩到270k左右。然而加载工夫仍然达到了惊人的22.89s。这个对于任何一个我的项目来说都是不可承受的。

初步解决思路

问题曾经出现了。打包后的文件,呈现了特地大的js,而且就是这个js文件阻塞了整个我的项目的加载。
因为最近正在钻研webpack相干内容。
webpack大家应该都应用过。webpack是一个打包编译工具,它做的事件,就是把你开发的整个我的项目,编译成一个浏览器可间接辨认的我的项目。它蕴含以下一些根底概念:

  • 1,入口文件
    入口文件,就是webpack工作的终点,从入口文件开始,咱们通常会import很多其余模块,import等模块化的开发方法,就把整个我的项目给串联起来了。依据这些依赖信息,webpack把整个我的项目解析为一个ast(形象语法树),这个树记录了所有的文件依赖门路。
  • 2,进口文件
    就是我的项目打包后寄存的目录,所有资源文件都会输入到这个文件夹
  • 3,loader
    webpack只能辨认es5的语法,对于es6等更新的语法,是不能辨认的,对于一些图片,css文件,jsx文件等各种不同后缀名的文件,都是须要loader进行解析的。loader做的事件也就是这些。
  • 4,plugin
    依据webpack官网文档,咱们晓得webpack在整个打包和编译的过程中,有几十个工夫节点。具体的内容能够看这个链接,在plugins目录下: webpack.docschina.org/api/compile…

那么我做的一点小尝试,就是在文件打包并且输出到output文件夹后,找到要害的js文件(上图划红线的那个文件),上传到公司的阿里云oss。而后index.html文件本来是援用了output外面的js文件,改为援用oss外面的链接。这也是待会儿实现webpack自定义插件的次要思路。

最初的试验成果

本来须要20多秒加载的文件,放到阿里云oss后,只须要0.5s的加载速度,是不是十分惊人呢。
而后发现,影响页面加载的次要因素,曾经不是这个要害js了。咱们好能够在此基础根底上做其余优化。

插件代码 和 应用办法

先看次要代码:
在src目录下新建plugins文件夹,而后新建了一个UploadJsToCDNPlugin.js文件。这也是咱们的插件文件。##### 参考webpack视频解说:进入学习

src/plugins/UploadJsToCDNPlugin.js 文件内容如下:

// const globby = require('globby');const path = require('path');const fs = require('fs');const axios = require('axios')var FormData = require('form-data')let replaceFile = function(filePath,sourceRegx,targetStr){  fs.readFile(filePath,function(err,data){      if(err){          return err;      }      let str = data.toString();      str = str.replace(sourceRegx,targetStr);      fs.writeFile(filePath, str, function (err) {          if (err) return err;      });  });}class UploadJsToCDNPlugin {  constructor(options = {}) {    this.options = options;  }  apply(compiler) {    console.log(compiler.options.mode)    compiler.hooks.afterEmit.tap('UploadJsToCDNPlugin',  async (params) => {      try {        const js_path = Object.keys(params.assets).find(item => item.includes('js/chunk-libs.'))// 请自行调整文件名称       const html_path = path.resolve(compiler.options.output.path, 'index.html')      const file_path = path.resolve(compiler.options.output.path, js_path)      // 因为是公司我的项目,已做脱敏解决,道歉      const url = 'https://wwwxxxxxx/file/upload'      const form = FormData()      form.append('file', fs.createReadStream(file_path), {        filename: 'app.js'      })      const res = await axios.create({        headers: form.getHeaders()      })      .post(url,form)      const cdn_path = res.data.data      // 这行代码是本插件的外围代码      await replaceFile(html_path, /js\/chunk-libs.\w*.js/g, cdn_path)// 请自行调整文件名称      } catch (e) {        e      }    })  }}module.exports = UploadJsToCDNPlugin;

最初在vue.config.js外面应用webpack自定义webpack插件:
vue.config.js 文件结尾:

const UploadJsToCDNPlugin = require('./src/plugins/UploadJsToCDNPlugin')