我自己尝试用阿里云部署了一个简单的博客网站,但是加载速度非常慢,接近8s,所以尝试进行优化。
1,去掉map文件
首先默认的vue-cli会生成map文件,用于debug的时候快速定位源文件位置,但是我们部署到生产环境的时候并不需要这个,我们将config/index.js里面的productionSourceMap设置为false,这样就不会生产map文件了
2,使用gzip压缩
将config/index.js里面的productionGzip设置为true之后,build的时候就会自动将css和js打包成gzip文件,同时js文件也会保留,但是我们查看build出的dist的文件夹里面的index.html文件,会发现,其中资源文件的后缀仍然是.js或者.css,并没有变成gz,所以想要在浏览器访问网站的时候获取gz而不是未压缩的文件,一种方法是直接手动把html文件中资源后缀名加上.gz,另一种依赖后端的实现,比如后端,收到浏览器的request头,知道浏览器支持gzip类型,那就返回对应资源的gz文件,django我是不清楚怎么做,但是可以在服务器端使用nginx代理,然后开启gzip static(见https://blog.csdn.net/sadhopedream/article/details/20950519),这样nginx就可以自动完成这样的过程
3,利用webpack的代码分割功能
虽然利用方法1和方法2,首屏的加载已经从8s下降到了2s,但是这不够,远远不够,还是能够感受到明显的卡顿,我觉的还是可以优化,所以百度搜索了许多,终于找到了一个利用webpack代码分离配合浏览器异步加载来提高首屏加载速度的方式。
这时候应该先贴个效果图震惊一下,从2s变成了接近0.5s,感觉就是回车一按,页面就加载出来了
(1)首先了解一下webpack的异步加载模块的方式import()
我们在平时编写vue项目的时候,引入模块使用的语句是
import VueQuillEditor from 'vue-quill-editor'
像是这样的格式,这是es6引入的模块管理的一个引入方式,我们想将其改为异步加载可以这样写
const getEditor = () => import('vue-quill-editor')
这个语句定义了一个函数getEditor返回import(‘...’) ,其实返回的会是一个Promise对象,也就是说,我们想利用这个模块就需要使用Promise那一套,比如then
function use(get){
get().then((module)=>{
Vue.use(module.default)
})
}
use(getEditor)
先定义了一个函数use,参数是一个函数get,执行get函数,之后利用then处理引入的module,之后Vue.use(module.default),这样就是一个使用组件的例子了,Vue.use的功能建议自己去查一下,那为什么要.default呢,说起来我也很好奇,虽然我知道es6里有一个export default,但是具体还真的不了解,所以这个以后再研究一下,这是我利用console.log(module)发现module.default才是指向本来模块才发现的。
那这样子,我们就可以对一些Vue之外的组件,利用异步加载来很好的处理了,由于chrome会并行下载多个js文件(注意,统一域名下并行下载数量会有限制),可以提高加载速度了。
但是,假如,你有多个组件想要引入,多个组件的体积分别很小,你希望把他们打包在一起,这时候我们可以使用魔术注释吗,如下:
const getEditor = () => import(
/* webpackChunkName: "vue-quill-editor" */
'vue-quill-editor'
)
利用这个注释,你可以指定代码分割后的chunkName,把多个组件的设置为相同,就可以打包到同一文件了。
(2)对ElementUI的处理
于是乎,我的项目里用到了ElementUI axios vue-quill-editor,因为axios的体积本身就很小,我就不把他分离出来,就只将ElementUI和vue-quill-editor分离开来,但是,我发现ElementUI在压缩后还是占了170KB,像是editor这个,压缩后才50KB,按照阿里云的限速,恐怕速度还是不够理想,所以我又查了查,发现有老哥遇到和我一样的问题,elementUI怎么这么大?如果按照上面那种引入方式,打包的时候整个elementUI都被放进去了,属实拉胯,我们想要能够按需引用。
对于elementUI的一个按需引用方法,是利用babel,这里我们可以参考官网,https://element.eleme.cn/#/zh-CN/component/quickstart,这个页面教我们如何按需引入组件,如果这样子做,那多余的包就不会被引进,最终我就选择了这个方法,因为用到的组件确实不多,那如果我非要使用webpack的那种分离方式,把他分离出来呢?
可以这样子,记得取消注释,不过这好像是针对element-ui的一个特殊用法,不知道其他库可不可以
//const getButton = ()=>import(/* webpackChunkName: "ele-ui" */'element-ui/packages/button')
//const getInput = ()=>import(/* webpackChunkName: "ele-ui" */'element-ui/packages/input')
//const getMessage = ()=>import(/* webpackChunkName: "ele-ui" */'element-ui/packages/message')
//const getLoading = ()=>import(/* webpackChunkName: "ele-ui" */'element-ui/packages/loading')
//use(getButton)
//use(getInput)
//use(getLoading)
//getMessage().then((module)=>{
// console.log(module)
// Vue.prototype.$message = module.default
//})
最后,当我们完成后,用chrome的network来分析
我们会发现,有一个js文件,他是异步加载的,就是这个第5个,查看html文件,发现里面也没有直接导入这个,所以这个js是靠伟大的webpack做了一个异步加载,那条蓝线呢,是DomContentLoaded的,而蓝色的矩形,是资源还在下载,所以下载的时候,首屏就已经出现了,这样子很好,所以以后,我们也可以考虑这么去优化性能.