一次Vue2.0项目打包优化之旅

前端开发
2018年10月14日
1346

兴致冲冲地把网站打包上线,却发现首屏加载超时,查看了一下控制台的请求信息,发现vendor.js文件竟然达到了1M的大小。百度一下后发现vue-cli npm run build命令默认把dependencies中的依赖统一打包到vendor.js文件里面。

定位vendor.js大的原因

使用webpack-bundle-analyzer—— Webpack 插件和 CLI 实用程序,她可以将内容束展示为方便交互的直观树状图,让你明白你所构建包中真正引入的内容;我们可以借助她,发现它大体有哪些模块组成,找到不合时宜的存在,然后优化它。

安装

shell
npm i -D webpack-bundle-analyzer

使用

webpack.base.conf.js里面作如下配置

js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = { plugins: [ new BundleAnalyzerPlugin() ] }

为了方便运行她(npm run analyz),我们可以在package.json注入以下的命令,默认会打开 http://127.0.0.1:8888 作为展示。

json
"analyz": "NODE_ENV=production set npm_config_report=true npm run build"

在windows下运行npm run analyz会报 “NODE_ENV 不是内部或外部命令,也不是可运行的程序,或者批处理文件” 的错误,(这种操作在powershell中不被支持,在cmd中也不被支持,这是Mac中bash或Linux的shell中的独特操作)在windows下我们可以

json
"analyz": "set NODE_ENV=production && set npm_config_report=true && npm run build"

这样就很方便地查看哪个模块太长,可以针对性的优化他们。

e79fac7bccb452a27d49334ca3acd555.gif

解决方法

1.引用外部CDN

引用https://www.unpkg.com 里面的CDN地址

使用方法:

在地址栏输入https://www.unpkg.com/你的模块名称,然后回车,就能查找到你的模块的CDN地址了,
比如https://www.unpkg.com/highlight.js就会访问到https://www.unpkg.com/highlight.js@9.13.0/lib/index.js

然后在index.html里面引用

html
<body> <div id="app"></div> <script src="https://www.unpkg.com/highlight.js@9.13.0/lib/index.js"></script> </body>

配置webpack.base.conf.js,在module.exports里面加入externals,具体的externals配置可以查看https://webpack.js.org/configuration/externals/#src/components/Sidebar/Sidebar.jsx

js
externals: { 'highlight.js': 'hljs' }

删除main.js里面的import hljs from 'highlight.js',若没有删除webpack还是会把对应的依赖进行打包。

另外就是,在开启了eslint的环境下会报一个no-undef错误,所以需要在.eslintrc.js里面配置

js
rules: { 'no-undef': 0, // http://eslint.cn/docs/4.0.0/rules/no-undef }

这样,再次打包之后,highlight.js就不会被打包进vendor.js里面了。其他的模块也可以使用这样的方式引用外部的CDN,减轻服务器的压力。

js
externals: { 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex': 'Vuex', 'axios': 'axios', 'vue-meta': 'VueMeta', 'highlight.js': 'hljs', 'vue-awesome-swiper': 'VueAwesomeSwiper' }

2.路由按需加载

具体配置可以查看vue-router官网

我的配置router/index.js

之前

js
import Home from '@/pages/home/Home' const routes = [ { path: '/', name: 'home', component: Home } ]

现在

js
// import Home from '@/pages/home/Home' const routes = [ { path: '/', name: 'home', component: resolve => require(['@/pages/home/Home'], resolve) } ]

然后配置一下chunk的名称webpack.base.conf.js

js
output: { // 以文件名和8位哈希值作为最终打包的名称 chunkName: '[name]-[chunkhash:8].js' }

3.开启gzip压缩

首先安装插件compression-webpack-plugin

shell
npm i -D compression-webpack-plugin@1.1.12

我安装的1.1.12版本,其他版本会报错,具体原因未明

然后在config/index.js里面把productionGzip改为true

js
// Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin // productionGzip: false, productionGzip: true, productionGzipExtensions: ['js', 'css'],

之后npm run build执行后会发现每个js和css文件会压缩一个gz后缀的文件夹,浏览器如果支持g-zip 会自动查找有没有gz文件 找到了就加载gz然后本地解压 执行。